@versu/core 0.4.0

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 (117) hide show
  1. package/README.md +241 -0
  2. package/dist/adapters/gradle/constants.d.ts +13 -0
  3. package/dist/adapters/gradle/constants.d.ts.map +1 -0
  4. package/dist/adapters/gradle/constants.js +12 -0
  5. package/dist/adapters/gradle/gradle-project-information.d.ts +19 -0
  6. package/dist/adapters/gradle/gradle-project-information.d.ts.map +1 -0
  7. package/dist/adapters/gradle/gradle-project-information.js +233 -0
  8. package/dist/adapters/gradle/init-project-information.gradle.kts +163 -0
  9. package/dist/adapters/gradle/services/gradle-adapter-identifier.d.ts +21 -0
  10. package/dist/adapters/gradle/services/gradle-adapter-identifier.d.ts.map +1 -0
  11. package/dist/adapters/gradle/services/gradle-adapter-identifier.js +44 -0
  12. package/dist/adapters/gradle/services/gradle-module-detector.d.ts +19 -0
  13. package/dist/adapters/gradle/services/gradle-module-detector.d.ts.map +1 -0
  14. package/dist/adapters/gradle/services/gradle-module-detector.js +28 -0
  15. package/dist/adapters/gradle/services/gradle-module-system-factory.d.ts +26 -0
  16. package/dist/adapters/gradle/services/gradle-module-system-factory.d.ts.map +1 -0
  17. package/dist/adapters/gradle/services/gradle-module-system-factory.js +29 -0
  18. package/dist/adapters/gradle/services/gradle-version-update-strategy.d.ts +23 -0
  19. package/dist/adapters/gradle/services/gradle-version-update-strategy.d.ts.map +1 -0
  20. package/dist/adapters/gradle/services/gradle-version-update-strategy.js +38 -0
  21. package/dist/adapters/project-information.d.ts +62 -0
  22. package/dist/adapters/project-information.d.ts.map +1 -0
  23. package/dist/adapters/project-information.js +1 -0
  24. package/dist/changelog/index.d.ts +14 -0
  25. package/dist/changelog/index.d.ts.map +1 -0
  26. package/dist/changelog/index.js +132 -0
  27. package/dist/config/index.d.ts +122 -0
  28. package/dist/config/index.d.ts.map +1 -0
  29. package/dist/config/index.js +117 -0
  30. package/dist/factories/adapter-identifier-registry.d.ts +12 -0
  31. package/dist/factories/adapter-identifier-registry.d.ts.map +1 -0
  32. package/dist/factories/adapter-identifier-registry.js +24 -0
  33. package/dist/factories/module-system-factory.d.ts +10 -0
  34. package/dist/factories/module-system-factory.d.ts.map +1 -0
  35. package/dist/factories/module-system-factory.js +18 -0
  36. package/dist/git/index.d.ts +355 -0
  37. package/dist/git/index.d.ts.map +1 -0
  38. package/dist/git/index.js +702 -0
  39. package/dist/index.d.ts +23 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +22 -0
  42. package/dist/semver/index.d.ts +86 -0
  43. package/dist/semver/index.d.ts.map +1 -0
  44. package/dist/semver/index.js +186 -0
  45. package/dist/services/adapter-identifier-registry.d.ts +38 -0
  46. package/dist/services/adapter-identifier-registry.d.ts.map +1 -0
  47. package/dist/services/adapter-identifier-registry.js +59 -0
  48. package/dist/services/adapter-identifier.d.ts +31 -0
  49. package/dist/services/adapter-identifier.d.ts.map +1 -0
  50. package/dist/services/adapter-identifier.js +1 -0
  51. package/dist/services/adapter-metadata-provider.d.ts +51 -0
  52. package/dist/services/adapter-metadata-provider.d.ts.map +1 -0
  53. package/dist/services/adapter-metadata-provider.js +66 -0
  54. package/dist/services/changelog-generator.d.ts +16 -0
  55. package/dist/services/changelog-generator.d.ts.map +1 -0
  56. package/dist/services/changelog-generator.js +28 -0
  57. package/dist/services/commit-analyzer.d.ts +47 -0
  58. package/dist/services/commit-analyzer.d.ts.map +1 -0
  59. package/dist/services/commit-analyzer.js +89 -0
  60. package/dist/services/configuration-loader.d.ts +23 -0
  61. package/dist/services/configuration-loader.d.ts.map +1 -0
  62. package/dist/services/configuration-loader.js +79 -0
  63. package/dist/services/configuration-validator.d.ts +16 -0
  64. package/dist/services/configuration-validator.d.ts.map +1 -0
  65. package/dist/services/configuration-validator.js +24 -0
  66. package/dist/services/git-operations.d.ts +16 -0
  67. package/dist/services/git-operations.d.ts.map +1 -0
  68. package/dist/services/git-operations.js +89 -0
  69. package/dist/services/module-detector.d.ts +24 -0
  70. package/dist/services/module-detector.d.ts.map +1 -0
  71. package/dist/services/module-detector.js +1 -0
  72. package/dist/services/module-registry.d.ts +45 -0
  73. package/dist/services/module-registry.d.ts.map +1 -0
  74. package/dist/services/module-registry.js +57 -0
  75. package/dist/services/module-system-factory.d.ts +27 -0
  76. package/dist/services/module-system-factory.d.ts.map +1 -0
  77. package/dist/services/module-system-factory.js +1 -0
  78. package/dist/services/version-applier.d.ts +26 -0
  79. package/dist/services/version-applier.d.ts.map +1 -0
  80. package/dist/services/version-applier.js +63 -0
  81. package/dist/services/version-bumper.d.ts +159 -0
  82. package/dist/services/version-bumper.d.ts.map +1 -0
  83. package/dist/services/version-bumper.js +291 -0
  84. package/dist/services/version-manager.d.ts +68 -0
  85. package/dist/services/version-manager.d.ts.map +1 -0
  86. package/dist/services/version-manager.js +94 -0
  87. package/dist/services/version-update-strategy.d.ts +18 -0
  88. package/dist/services/version-update-strategy.d.ts.map +1 -0
  89. package/dist/services/version-update-strategy.js +1 -0
  90. package/dist/services/versu-runner.d.ts +46 -0
  91. package/dist/services/versu-runner.d.ts.map +1 -0
  92. package/dist/services/versu-runner.js +188 -0
  93. package/dist/utils/banner.d.ts +2 -0
  94. package/dist/utils/banner.d.ts.map +1 -0
  95. package/dist/utils/banner.js +12 -0
  96. package/dist/utils/commits.d.ts +12 -0
  97. package/dist/utils/commits.d.ts.map +1 -0
  98. package/dist/utils/commits.js +24 -0
  99. package/dist/utils/file.d.ts +7 -0
  100. package/dist/utils/file.d.ts.map +1 -0
  101. package/dist/utils/file.js +19 -0
  102. package/dist/utils/index.d.ts +6 -0
  103. package/dist/utils/index.d.ts.map +1 -0
  104. package/dist/utils/index.js +5 -0
  105. package/dist/utils/logger.d.ts +14 -0
  106. package/dist/utils/logger.d.ts.map +1 -0
  107. package/dist/utils/logger.js +22 -0
  108. package/dist/utils/properties.d.ts +24 -0
  109. package/dist/utils/properties.d.ts.map +1 -0
  110. package/dist/utils/properties.js +94 -0
  111. package/dist/utils/version.d.ts +3 -0
  112. package/dist/utils/version.d.ts.map +1 -0
  113. package/dist/utils/version.js +4 -0
  114. package/dist/utils/versioning.d.ts +9 -0
  115. package/dist/utils/versioning.d.ts.map +1 -0
  116. package/dist/utils/versioning.js +20 -0
  117. package/package.json +73 -0
@@ -0,0 +1,94 @@
1
+ import { formatSemVer } from "../semver/index.js";
2
+ /**
3
+ * Manages version updates for modules with staged commits and batch persistence.
4
+ *
5
+ * @remarks
6
+ * Implements a two-phase update strategy:
7
+ * 1. Stage updates in memory via `updateVersion()`
8
+ * 2. Persist all updates via `commit()`
9
+ *
10
+ * Uses {@link VersionUpdateStrategy} for build system-specific operations.
11
+ * Validates modules against {@link ModuleRegistry}.
12
+ */
13
+ export class VersionManager {
14
+ moduleRegistry;
15
+ strategy;
16
+ /** Pending version updates awaiting commit (module ID → version string). */
17
+ pendingUpdates = new Map();
18
+ /**
19
+ * Creates a new VersionManager.
20
+ *
21
+ * @param moduleRegistry - Module registry for validation
22
+ * @param strategy - Build system-specific strategy for writing updates
23
+ */
24
+ constructor(moduleRegistry, strategy) {
25
+ this.moduleRegistry = moduleRegistry;
26
+ this.strategy = strategy;
27
+ }
28
+ /**
29
+ * Stages a version update for a module without persisting to files.
30
+ *
31
+ * @param moduleId - Module identifier (e.g., `':'`, `':core'`)
32
+ * @param newVersion - New version as SemVer object or string
33
+ * @throws {Error} If module ID doesn't exist in registry
34
+ */
35
+ updateVersion(moduleId, newVersion) {
36
+ // Validate module exists in registry
37
+ if (!this.moduleRegistry.hasModule(moduleId)) {
38
+ throw new Error(`Module ${moduleId} not found`);
39
+ }
40
+ // Convert SemVer to string if needed, otherwise use string directly
41
+ const versionString = typeof newVersion === "string" ? newVersion : formatSemVer(newVersion);
42
+ // Store update in pending updates map
43
+ this.pendingUpdates.set(moduleId, versionString);
44
+ }
45
+ /**
46
+ * Commits all pending version updates to build files in a single batch operation.
47
+ *
48
+ * @returns Promise that resolves when all updates are written
49
+ * @throws {Error} If file operations fail (specific errors depend on strategy)
50
+ */
51
+ async commit() {
52
+ // Early return if nothing to commit
53
+ if (this.pendingUpdates.size === 0) {
54
+ return; // Nothing to commit
55
+ }
56
+ // Write all version updates using build system-specific strategy
57
+ await this.strategy.writeVersionUpdates(this.pendingUpdates);
58
+ // Clear the pending updates after successful commit
59
+ this.pendingUpdates.clear();
60
+ }
61
+ /**
62
+ * Returns a copy of all pending updates that haven't been committed.
63
+ *
64
+ * @returns Map of module ID to version string
65
+ */
66
+ getPendingUpdates() {
67
+ return new Map(this.pendingUpdates);
68
+ }
69
+ /**
70
+ * Checks whether there are any pending updates awaiting commit.
71
+ *
72
+ * @returns `true` if updates are staged, `false` otherwise
73
+ */
74
+ hasPendingUpdates() {
75
+ return this.pendingUpdates.size > 0;
76
+ }
77
+ /**
78
+ * Clears all pending updates without committing them.
79
+ *
80
+ * @remarks
81
+ * Use with caution - this operation cannot be undone.
82
+ */
83
+ clearPendingUpdates() {
84
+ this.pendingUpdates.clear();
85
+ }
86
+ /**
87
+ * Gets the number of pending updates in the queue.
88
+ *
89
+ * @returns The count of pending updates that have not been processed yet.
90
+ */
91
+ getPendingUpdatesCount() {
92
+ return this.pendingUpdates.size;
93
+ }
94
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Strategy for writing version updates to build system-specific files.
3
+ *
4
+ * @remarks
5
+ * Implementations handle version persistence for different build systems (Gradle, Maven, npm).
6
+ * Created by {@link ModuleSystemFactory} and used by {@link VersionManager}.
7
+ */
8
+ export interface VersionUpdateStrategy {
9
+ /**
10
+ * Writes version updates for multiple modules to build system configuration files.
11
+ *
12
+ * @param moduleVersions - Map of module ID to new version string
13
+ * @returns Promise that resolves when all updates are written
14
+ * @throws {Error} If build files cannot be found, are not writable, or I/O operations fail
15
+ */
16
+ writeVersionUpdates(moduleVersions: Map<string, string>): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=version-update-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-update-strategy.d.ts","sourceRoot":"","sources":["../../src/services/version-update-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,mBAAmB,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzE"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import { ModuleChangeResult } from "./version-applier.js";
2
+ import { Module } from "../adapters/project-information.js";
3
+ export type RunnerOptions = {
4
+ readonly repoRoot: string;
5
+ readonly adapter?: string;
6
+ readonly dryRun: boolean;
7
+ readonly pushTags: boolean;
8
+ readonly prereleaseMode: boolean;
9
+ readonly prereleaseId: string;
10
+ readonly bumpUnchanged: boolean;
11
+ readonly addBuildMetadata: boolean;
12
+ readonly timestampVersions: boolean;
13
+ readonly appendSnapshot: boolean;
14
+ readonly pushChanges: boolean;
15
+ readonly generateChangelog: boolean;
16
+ readonly outputFile: string;
17
+ };
18
+ export type RunnerResult = {
19
+ readonly bumped: boolean;
20
+ readonly discoveredModules: Array<Module>;
21
+ readonly changedModules: Array<ModuleChangeResult>;
22
+ readonly createdTags: string[];
23
+ readonly changelogPaths: string[];
24
+ };
25
+ export declare class VersuRunner {
26
+ private moduleSystemFactory;
27
+ private moduleRegistry;
28
+ private versionManager;
29
+ private config;
30
+ private adapter;
31
+ private options;
32
+ private configurationLoader;
33
+ private commitAnalyzer;
34
+ private versionBumper;
35
+ private versionApplier;
36
+ private changelogGenerator;
37
+ private gitOperations;
38
+ private adapterIdentifierRegistry;
39
+ private adapterMetadataProvider;
40
+ constructor(options: RunnerOptions);
41
+ private logStartupInfo;
42
+ private logShutdownInfo;
43
+ run(): Promise<RunnerResult>;
44
+ private doRun;
45
+ }
46
+ //# sourceMappingURL=versu-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versu-runner.d.ts","sourceRoot":"","sources":["../../src/services/versu-runner.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAK5D,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,cAAc,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,qBAAa,WAAW;IACtB,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,OAAO,CAAgB;IAG/B,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,yBAAyB,CAA4B;IAC7D,OAAO,CAAC,uBAAuB,CAA0B;gBAE7C,OAAO,EAAE,aAAa;IA0BlC,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,eAAe;IAgCjB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC;YAYpB,KAAK;CAkIpB"}
@@ -0,0 +1,188 @@
1
+ import { logger } from "../utils/logger.js";
2
+ import { VersionManager } from "./version-manager.js";
3
+ import { createModuleSystemFactory } from "../factories/module-system-factory.js";
4
+ import { isWorkingDirectoryClean } from "../git/index.js";
5
+ // Service imports
6
+ import { ConfigurationLoader } from "./configuration-loader.js";
7
+ import { CommitAnalyzer } from "./commit-analyzer.js";
8
+ import { VersionBumper } from "./version-bumper.js";
9
+ import { VersionApplier, } from "./version-applier.js";
10
+ import { ChangelogGenerator } from "./changelog-generator.js";
11
+ import { GitOperations } from "./git-operations.js";
12
+ import { AdapterMetadataProvider } from "./adapter-metadata-provider.js";
13
+ import { createAdapterIdentifierRegistry } from "../factories/adapter-identifier-registry.js";
14
+ import { ConfigurationValidator } from "./configuration-validator.js";
15
+ import { banner } from "../utils/banner.js";
16
+ import path from "path";
17
+ export class VersuRunner {
18
+ moduleSystemFactory; // Will be initialized in run()
19
+ moduleRegistry; // Will be initialized in run()
20
+ versionManager; // Will be initialized in run()
21
+ config; // Will be initialized in run()
22
+ adapter; // Will be initialized in run()
23
+ options;
24
+ // Service instances
25
+ configurationLoader;
26
+ commitAnalyzer;
27
+ versionBumper; // Will be initialized in run()
28
+ versionApplier; // Will be initialized in run()
29
+ changelogGenerator;
30
+ gitOperations; // Will be initialized in run()
31
+ adapterIdentifierRegistry;
32
+ adapterMetadataProvider;
33
+ constructor(options) {
34
+ this.options = {
35
+ ...options,
36
+ repoRoot: path.resolve(options.repoRoot),
37
+ outputFile: path.resolve(options.outputFile),
38
+ };
39
+ // Initialize services
40
+ this.configurationLoader = new ConfigurationLoader(new ConfigurationValidator());
41
+ this.changelogGenerator = new ChangelogGenerator({
42
+ generateChangelog: options.generateChangelog,
43
+ repoRoot: options.repoRoot,
44
+ dryRun: options.dryRun,
45
+ });
46
+ this.adapterIdentifierRegistry = createAdapterIdentifierRegistry();
47
+ this.adapterMetadataProvider = new AdapterMetadataProvider(this.adapterIdentifierRegistry, {
48
+ repoRoot: options.repoRoot,
49
+ adapter: options.adapter,
50
+ });
51
+ }
52
+ logStartupInfo() {
53
+ logger.info(banner);
54
+ logger.info("🌌 Version Engine for Repo Semantic Evolution");
55
+ logger.info(" Orchestrating your monorepo multiverse...");
56
+ logger.info("");
57
+ logger.info("🚀 Starting VERSU engine...");
58
+ logger.info(`Repository: ${this.options.repoRoot}`);
59
+ logger.info(`Output file: ${this.options.outputFile}`);
60
+ logger.info(`Adapter: ${this.options.adapter || "(auto-detect)"}`);
61
+ logger.info(`Dry run: ${this.options.dryRun}`);
62
+ logger.info(`Prerelease mode: ${this.options.prereleaseMode}`);
63
+ if (this.options.prereleaseMode) {
64
+ logger.info(`Prerelease ID: ${this.options.prereleaseId}`);
65
+ logger.info(`Bump unchanged modules: ${this.options.bumpUnchanged}`);
66
+ }
67
+ logger.info(`Add build metadata: ${this.options.addBuildMetadata}`);
68
+ logger.info(`Timestamp versions: ${this.options.timestampVersions}`);
69
+ logger.info(`Append snapshot: ${this.options.appendSnapshot}`);
70
+ logger.info(`Push changes: ${this.options.pushChanges}`);
71
+ logger.info(`Generate changelog: ${this.options.generateChangelog}`);
72
+ logger.info("🏃 Running VERSU semantic evolution...");
73
+ }
74
+ logShutdownInfo(result) {
75
+ if (!result)
76
+ return;
77
+ if (result.bumped) {
78
+ logger.info(`✅ Successfully updated ${result.changedModules.length} modules`);
79
+ for (const module of result.changedModules) {
80
+ logger.info(` ${module.id}: ${module.from} → ${module.to} (${module.bumpType})`);
81
+ }
82
+ if (result.createdTags.length > 0) {
83
+ logger.info(`🏷️ Created ${result.createdTags.length} tags: ${result.createdTags.join(", ")}`);
84
+ }
85
+ if (result.changelogPaths.length > 0) {
86
+ logger.info(`📚 Generated ${result.changelogPaths.length} changelog files`);
87
+ }
88
+ }
89
+ else {
90
+ logger.info("✨ No version changes needed");
91
+ }
92
+ logger.info("");
93
+ logger.info("🎯 VERSU completed successfully!");
94
+ logger.info(" Your multiverse has evolved semantically ✨");
95
+ }
96
+ async run() {
97
+ this.logStartupInfo();
98
+ let result = null;
99
+ try {
100
+ result = await this.doRun();
101
+ return result;
102
+ }
103
+ finally {
104
+ // Any cleanup if needed
105
+ this.logShutdownInfo(result);
106
+ }
107
+ }
108
+ async doRun() {
109
+ this.adapter = await this.adapterMetadataProvider.getMetadata();
110
+ // Initialize module system factory with resolved adapter
111
+ this.moduleSystemFactory = createModuleSystemFactory(this.adapter.id, this.options.repoRoot);
112
+ // Load configuration
113
+ this.config = await this.configurationLoader.load(this.options.repoRoot);
114
+ // Check if working directory is clean
115
+ if (!this.options.dryRun &&
116
+ !isWorkingDirectoryClean({ cwd: this.options.repoRoot })) {
117
+ throw new Error("Working directory is not clean. Please commit or stash your changes.");
118
+ }
119
+ // Discover modules and get hierarchy manager
120
+ logger.info("🔍 Discovering modules...");
121
+ const detector = this.moduleSystemFactory.createDetector(this.options.outputFile);
122
+ this.moduleRegistry = await detector.detect();
123
+ // Log discovered modules through hierarchy manager
124
+ const moduleIds = this.moduleRegistry.getModuleIds();
125
+ logger.info(`Found ${moduleIds.length} modules: ${moduleIds.join(", ")}`);
126
+ // Analyze commits since last release
127
+ this.commitAnalyzer = new CommitAnalyzer(this.moduleRegistry, this.options.repoRoot);
128
+ const moduleCommits = await this.commitAnalyzer.analyzeCommitsSinceLastRelease();
129
+ // Initialize version bumper service
130
+ const versionBumperOptions = {
131
+ prereleaseMode: this.options.prereleaseMode,
132
+ bumpUnchanged: this.options.bumpUnchanged,
133
+ addBuildMetadata: this.options.addBuildMetadata,
134
+ appendSnapshot: this.options.appendSnapshot,
135
+ adapter: this.adapter,
136
+ timestampVersions: this.options.timestampVersions,
137
+ prereleaseId: this.options.prereleaseId,
138
+ repoRoot: this.options.repoRoot,
139
+ config: this.config,
140
+ };
141
+ this.versionBumper = new VersionBumper(this.moduleRegistry, versionBumperOptions);
142
+ // Calculate version bumps with cascade effects
143
+ const processedModuleChanges = await this.versionBumper.calculateVersionBumps(moduleCommits);
144
+ const discoveredModules = Array.from(this.moduleRegistry.getModules().values());
145
+ if (processedModuleChanges.length === 0) {
146
+ logger.info("✨ No version changes needed");
147
+ return {
148
+ bumped: false,
149
+ discoveredModules,
150
+ changedModules: [],
151
+ createdTags: [],
152
+ changelogPaths: [],
153
+ };
154
+ }
155
+ // Create version manager
156
+ const versionUpdateStrategy = this.moduleSystemFactory.createVersionUpdateStrategy(this.moduleRegistry);
157
+ this.versionManager = new VersionManager(this.moduleRegistry, versionUpdateStrategy);
158
+ // Initialize version applier and apply changes
159
+ const versionApplierOptions = {
160
+ dryRun: this.options.dryRun,
161
+ };
162
+ this.versionApplier = new VersionApplier(this.versionManager, versionApplierOptions);
163
+ const changedModules = await this.versionApplier.applyVersionChanges(processedModuleChanges);
164
+ // Generate changelogs
165
+ const changelogPaths = await this.changelogGenerator.generateChangelogs(changedModules, moduleCommits);
166
+ // Initialize git operations service
167
+ const gitOperationsOptions = {
168
+ pushChanges: this.options.pushChanges,
169
+ pushTags: this.options.pushTags,
170
+ repoRoot: this.options.repoRoot,
171
+ dryRun: this.options.dryRun,
172
+ isTemporaryVersion: this.options.prereleaseMode || this.options.appendSnapshot,
173
+ };
174
+ this.gitOperations = new GitOperations(gitOperationsOptions);
175
+ // Commit and push changes
176
+ await this.gitOperations.commitAndPushChanges(changedModules);
177
+ // Create and push tags
178
+ const createdTags = await this.gitOperations.createAndPushTags(changedModules);
179
+ logger.info("✅ VERSU semantic evolution completed successfully!");
180
+ return {
181
+ bumped: true,
182
+ discoveredModules,
183
+ changedModules,
184
+ createdTags,
185
+ changelogPaths,
186
+ };
187
+ }
188
+ }
@@ -0,0 +1,2 @@
1
+ export declare const banner: string;
2
+ //# sourceMappingURL=banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/utils/banner.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,EAAE,MASpB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { VERSION, PACKAGE_NAME } from "./version.js";
2
+ const info = `${PACKAGE_NAME} v${VERSION}`;
3
+ export const banner = `
4
+ ██╗ ██╗███████╗██████╗ ███████╗██╗ ██╗
5
+ ██║ ██║██╔════╝██╔══██╗██╔════╝██║ ██║
6
+ ██║ ██║█████╗ ██████╔╝███████╗██║ ██║
7
+ ╚██╗ ██╔╝██╔══╝ ██╔══██╗╚════██║██║ ██║
8
+ ╚████╔╝ ███████╗██║ ██║███████║╚██████╔╝
9
+ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═════╝
10
+
11
+ ${info.padStart(44)}
12
+ `;
@@ -0,0 +1,12 @@
1
+ import { Commit } from "conventional-commits-parser";
2
+ import { Config } from "../config/index.js";
3
+ import { BumpType } from "../semver/index.js";
4
+ /**
5
+ * Calculates the overall semantic version bump type from a collection of commits.
6
+ * Returns the highest bump type: major > minor > patch > none.
7
+ * @param commits - Array of commit information to analyze
8
+ * @param config - Configuration containing commit type mappings
9
+ * @returns The highest BumpType required across all commits
10
+ */
11
+ export declare function calculateBumpFromCommits(commits: Commit[], config: Config): BumpType;
12
+ //# sourceMappingURL=commits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commits.d.ts","sourceRoot":"","sources":["../../src/utils/commits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAwB,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAe,MAAM,oBAAoB,CAAC;AAE3D;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,MAAM,GACb,QAAQ,CAiBV"}
@@ -0,0 +1,24 @@
1
+ import { getBumpTypeForCommit } from "../config/index.js";
2
+ import { maxBumpType } from "../semver/index.js";
3
+ /**
4
+ * Calculates the overall semantic version bump type from a collection of commits.
5
+ * Returns the highest bump type: major > minor > patch > none.
6
+ * @param commits - Array of commit information to analyze
7
+ * @param config - Configuration containing commit type mappings
8
+ * @returns The highest BumpType required across all commits
9
+ */
10
+ export function calculateBumpFromCommits(commits, config) {
11
+ // Collect bump types for all commits
12
+ const bumpTypes = [];
13
+ // Analyze each commit and determine its version impact
14
+ for (const commit of commits) {
15
+ const bumpType = getBumpTypeForCommit(commit, config);
16
+ // Only include commits that require a version bump
17
+ if (bumpType !== "none") {
18
+ bumpTypes.push(bumpType);
19
+ }
20
+ }
21
+ // Return the highest bump type required across all commits
22
+ // If no meaningful commits found, returns 'none'
23
+ return maxBumpType(bumpTypes);
24
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Checks whether a file or directory exists at the specified path.
3
+ * @param path - Absolute or relative path to check
4
+ * @returns True if the path exists and is accessible, false otherwise
5
+ */
6
+ export declare function exists(path: string): Promise<boolean>;
7
+ //# sourceMappingURL=file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/utils/file.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAW3D"}
@@ -0,0 +1,19 @@
1
+ import { promises as fs } from "fs";
2
+ /**
3
+ * Checks whether a file or directory exists at the specified path.
4
+ * @param path - Absolute or relative path to check
5
+ * @returns True if the path exists and is accessible, false otherwise
6
+ */
7
+ export async function exists(path) {
8
+ try {
9
+ // Attempt to access the path
10
+ // If access succeeds, the path exists and is accessible
11
+ await fs.access(path);
12
+ return true;
13
+ }
14
+ catch {
15
+ // If access fails (any error), consider path as non-existent
16
+ // This includes ENOENT (doesn't exist) and EACCES (no permission)
17
+ return false;
18
+ }
19
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./commits.js";
2
+ export * from "./file.js";
3
+ export * from "./properties.js";
4
+ export * from "./versioning.js";
5
+ export * from "./logger.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from "./commits.js";
2
+ export * from "./file.js";
3
+ export * from "./properties.js";
4
+ export * from "./versioning.js";
5
+ export * from "./logger.js";
@@ -0,0 +1,14 @@
1
+ export interface Logger {
2
+ debug(message: string): void;
3
+ info(message: string): void;
4
+ warning(message: string | Error, context?: Record<string, unknown>): void;
5
+ error(message: string | Error, context?: Record<string, unknown>): void;
6
+ }
7
+ export declare function initLogger(logger: Logger): void;
8
+ /**
9
+ * Convenience proxy so existing call sites can
10
+ * import `logger` and call methods. The proxy delegates
11
+ * to the mutable `_current` at call-time.
12
+ */
13
+ export declare const logger: Logger;
14
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1E,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACzE;AAYD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,QAExC;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,MAOpB,CAAC"}
@@ -0,0 +1,22 @@
1
+ // default no-op
2
+ const noopLogger = {
3
+ debug: (_message) => { },
4
+ info: (_message) => { },
5
+ warning: (_message, _context) => { },
6
+ error: (_message, _context) => { },
7
+ };
8
+ let _current = noopLogger;
9
+ export function initLogger(logger) {
10
+ _current = logger;
11
+ }
12
+ /**
13
+ * Convenience proxy so existing call sites can
14
+ * import `logger` and call methods. The proxy delegates
15
+ * to the mutable `_current` at call-time.
16
+ */
17
+ export const logger = {
18
+ debug: (message) => _current.debug(message),
19
+ info: (message) => _current.info(message),
20
+ warning: (message, context) => _current.warning(message, context),
21
+ error: (message, context) => _current.error(message, context),
22
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Parse a generic properties file into key-value pairs
3
+ * Supports both '=' and ':' as delimiters
4
+ * Skips comments (lines starting with # or !) and empty lines
5
+ * @param propertiesPath - Path to the properties file
6
+ * @returns Map of property keys to values
7
+ */
8
+ export declare function parseProperties(propertiesPath: string): Promise<Map<string, string>>;
9
+ /**
10
+ * Updates or inserts a single property in a Java-style properties file.
11
+ * @param propertiesPath - Path to the properties file
12
+ * @param key - Property key to update or insert
13
+ * @param value - Property value to set
14
+ */
15
+ export declare function upsertProperty(propertiesPath: string, key: string, value: string): Promise<void>;
16
+ /**
17
+ * Updates or inserts multiple properties in a Java-style properties file.
18
+ * Updates existing properties in place, appends new ones to the end.
19
+ * @param propertiesPath - Path to the properties file
20
+ * @param properties - Map of property keys to values
21
+ * @throws {Error} If file operations fail
22
+ */
23
+ export declare function upsertProperties(propertiesPath: string, properties: Map<string, string>): Promise<void>;
24
+ //# sourceMappingURL=properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../../src/utils/properties.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAiC9B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CAgDf"}
@@ -0,0 +1,94 @@
1
+ import { promises as fs } from "fs";
2
+ import { exists } from "./file.js";
3
+ /**
4
+ * Parse a generic properties file into key-value pairs
5
+ * Supports both '=' and ':' as delimiters
6
+ * Skips comments (lines starting with # or !) and empty lines
7
+ * @param propertiesPath - Path to the properties file
8
+ * @returns Map of property keys to values
9
+ */
10
+ export async function parseProperties(propertiesPath) {
11
+ const content = await fs.readFile(propertiesPath, "utf8");
12
+ const properties = new Map();
13
+ // Parse all properties line by line
14
+ const lines = content.split("\n");
15
+ for (const line of lines) {
16
+ const trimmedLine = line.trim();
17
+ // Skip comments and empty lines
18
+ if (trimmedLine.startsWith("#") ||
19
+ trimmedLine.startsWith("!") ||
20
+ !trimmedLine) {
21
+ continue;
22
+ }
23
+ // Parse property: key=value or key:value
24
+ const match = trimmedLine.match(/^([^=:]+)[=:]\s*(.+)$/);
25
+ if (!match) {
26
+ continue;
27
+ }
28
+ const [, key, value] = match;
29
+ const trimmedKey = key.trim();
30
+ const trimmedValue = value.trim();
31
+ properties.set(trimmedKey, trimmedValue);
32
+ }
33
+ return properties;
34
+ }
35
+ /**
36
+ * Updates or inserts a single property in a Java-style properties file.
37
+ * @param propertiesPath - Path to the properties file
38
+ * @param key - Property key to update or insert
39
+ * @param value - Property value to set
40
+ */
41
+ export async function upsertProperty(propertiesPath, key, value) {
42
+ // Delegate to batch function with single-entry map
43
+ await upsertProperties(propertiesPath, new Map([[key, value]]));
44
+ }
45
+ /**
46
+ * Updates or inserts multiple properties in a Java-style properties file.
47
+ * Updates existing properties in place, appends new ones to the end.
48
+ * @param propertiesPath - Path to the properties file
49
+ * @param properties - Map of property keys to values
50
+ * @throws {Error} If file operations fail
51
+ */
52
+ export async function upsertProperties(propertiesPath, properties) {
53
+ // Early return for empty updates (optimization)
54
+ if (properties.size === 0) {
55
+ return; // Nothing to update
56
+ }
57
+ // Check if properties file already exists
58
+ const propertiesExist = await exists(propertiesPath);
59
+ let updatedContent;
60
+ if (propertiesExist) {
61
+ // File exists - read current content and update properties
62
+ let content = await fs.readFile(propertiesPath, "utf8");
63
+ // Process each property update
64
+ for (const [key, value] of properties) {
65
+ // Escape special regex characters in property key
66
+ // This ensures keys like 'my.app.version' don't become regex patterns
67
+ const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
68
+ // Match property lines: key=value or key:value (with optional whitespace)
69
+ // Anchored to line start (^) and end ($) with multiline flag (m)
70
+ const propertyRegex = new RegExp(`^${escapedKey}\\s*[=:]\\s*.*$`, "m");
71
+ if (propertyRegex.test(content)) {
72
+ // Property exists - replace the line with updated value
73
+ content = content.replace(propertyRegex, `${key}=${value}`);
74
+ }
75
+ else {
76
+ // Property doesn't exist - append to end of file
77
+ // Add newline separator if file doesn't end with one
78
+ const separator = content.endsWith("\n") ? "" : "\n";
79
+ content = content + separator + `${key}=${value}\n`;
80
+ }
81
+ }
82
+ updatedContent = content;
83
+ }
84
+ else {
85
+ // File doesn't exist - create new properties content
86
+ const lines = [];
87
+ for (const [key, value] of properties) {
88
+ lines.push(`${key}=${value}`);
89
+ }
90
+ updatedContent = lines.join("\n") + "\n";
91
+ }
92
+ // Write updated content to file (creates or overwrites)
93
+ await fs.writeFile(propertiesPath, updatedContent, "utf8");
94
+ }
@@ -0,0 +1,3 @@
1
+ export declare const VERSION = "0.4.0";
2
+ export declare const PACKAGE_NAME = "@versu/core";
3
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,YAAY,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // This file is auto-generated. Do not edit manually.
2
+ // Run 'npm run generate-version' to update this file.
3
+ export const VERSION = "0.4.0";
4
+ export const PACKAGE_NAME = "@versu/core";