@versu/core 0.5.1 → 0.6.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 (44) hide show
  1. package/dist/changelog/index.d.ts.map +1 -1
  2. package/dist/changelog/index.js +1 -1
  3. package/dist/config/index.d.ts +1 -0
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +2 -0
  6. package/dist/factories/adapter-identifier-registry.d.ts +2 -1
  7. package/dist/factories/adapter-identifier-registry.d.ts.map +1 -1
  8. package/dist/factories/adapter-identifier-registry.js +2 -3
  9. package/dist/factories/module-system-factory.d.ts +2 -1
  10. package/dist/factories/module-system-factory.d.ts.map +1 -1
  11. package/dist/factories/module-system-factory.js +6 -9
  12. package/dist/index.d.ts +3 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/plugins/plugin-loader.d.ts +38 -0
  15. package/dist/plugins/plugin-loader.d.ts.map +1 -0
  16. package/dist/plugins/plugin-loader.js +85 -0
  17. package/dist/services/adapter-metadata-provider.d.ts.map +1 -1
  18. package/dist/services/adapter-metadata-provider.js +3 -1
  19. package/dist/services/configuration-loader.js +1 -1
  20. package/dist/services/versu-runner.d.ts +1 -0
  21. package/dist/services/versu-runner.d.ts.map +1 -1
  22. package/dist/services/versu-runner.js +14 -9
  23. package/dist/utils/version.d.ts +1 -1
  24. package/dist/utils/version.js +1 -1
  25. package/package.json +4 -5
  26. package/dist/adapters/gradle/constants.d.ts +0 -13
  27. package/dist/adapters/gradle/constants.d.ts.map +0 -1
  28. package/dist/adapters/gradle/constants.js +0 -12
  29. package/dist/adapters/gradle/gradle-project-information.d.ts +0 -19
  30. package/dist/adapters/gradle/gradle-project-information.d.ts.map +0 -1
  31. package/dist/adapters/gradle/gradle-project-information.js +0 -235
  32. package/dist/adapters/gradle/init-project-information.gradle.kts +0 -163
  33. package/dist/adapters/gradle/services/gradle-adapter-identifier.d.ts +0 -21
  34. package/dist/adapters/gradle/services/gradle-adapter-identifier.d.ts.map +0 -1
  35. package/dist/adapters/gradle/services/gradle-adapter-identifier.js +0 -44
  36. package/dist/adapters/gradle/services/gradle-module-detector.d.ts +0 -19
  37. package/dist/adapters/gradle/services/gradle-module-detector.d.ts.map +0 -1
  38. package/dist/adapters/gradle/services/gradle-module-detector.js +0 -28
  39. package/dist/adapters/gradle/services/gradle-module-system-factory.d.ts +0 -26
  40. package/dist/adapters/gradle/services/gradle-module-system-factory.d.ts.map +0 -1
  41. package/dist/adapters/gradle/services/gradle-module-system-factory.js +0 -29
  42. package/dist/adapters/gradle/services/gradle-version-update-strategy.d.ts +0 -23
  43. package/dist/adapters/gradle/services/gradle-version-update-strategy.d.ts.map +0 -1
  44. package/dist/adapters/gradle/services/gradle-version-update-strategy.js +0 -38
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/changelog/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAIrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAE3E,sDAAsD;AACtD,wBAAsB,mBAAmB,CACvC,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC,CAWf;AAsBD,+CAA+C;AAC/C,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,kBAAkB,EAAE,EACnC,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,EAC3D,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,MAAM,EAAE,CAAC,CA4EnB;AAED,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,kBAAkB,EAAE,EACnC,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,EAC3D,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgF7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/changelog/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAOpE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAIrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAE3E,sDAAsD;AACtD,wBAAsB,mBAAmB,CACvC,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC,CAWf;AAsBD,+CAA+C;AAC/C,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,kBAAkB,EAAE,EACnC,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,EAC3D,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,MAAM,EAAE,CAAC,CAwEnB;AAED,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,kBAAkB,EAAE,EACnC,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,EAC3D,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4E7B"}
@@ -1,6 +1,6 @@
1
1
  import { promises as fs } from "fs";
2
2
  import { join } from "path";
3
- import { writeChangelogString } from "conventional-changelog-writer";
3
+ import { writeChangelogString, } from "conventional-changelog-writer";
4
4
  import { logger } from "../utils/logger.js";
5
5
  import { exists } from "../utils/file.js";
6
6
  import { getCurrentRepoUrl, parseRepoUrl } from "../git/index.js";
@@ -90,6 +90,7 @@ export declare const configSchema: z.ZodObject<{
90
90
  versionSource: z.ZodArray<z.ZodLiteral<"package.json">>;
91
91
  updatePackageLock: z.ZodBoolean;
92
92
  }, z.core.$strip>>;
93
+ plugins: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
93
94
  changelog: z.ZodOptional<z.ZodObject<{
94
95
  root: z.ZodOptional<z.ZodObject<{
95
96
  context: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAqBrD;;;GAGG;AACH,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;iBAIzB,CAAC;AAEH;;;GAGG;AACH,QAAA,MAAM,kBAAkB;;;iBAGtB,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;kBAmBf,CAAC;AAEd;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAWvB,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAmB5B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAe7E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,kBAAkB,EAAE,QAAQ,EAC5B,MAAM,EAAE,MAAM,GACb,QAAQ,CAaV;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,MAAM,EACrD,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,CAAC,GACb,MAAM,CAAC,CAAC,CAAC,CAEX"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAqBrD;;;GAGG;AACH,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;iBAIzB,CAAC;AAEH;;;GAGG;AACH,QAAA,MAAM,kBAAkB;;;iBAGtB,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;kBAmBf,CAAC;AAEd;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYvB,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAoB5B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAe7E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,kBAAkB,EAAE,QAAQ,EAC5B,MAAM,EAAE,MAAM,GACb,QAAQ,CAaV;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,MAAM,EACrD,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,CAAC,GACb,MAAM,CAAC,CAAC,CAAC,CAEX"}
@@ -63,6 +63,7 @@ export const configSchema = z.object({
63
63
  commitTypes: z.record(z.string(), bumpTypeOrIgnoreSchema),
64
64
  dependencyRules: dependencyRulesSchema,
65
65
  nodejs: nodeJSConfigSchema.optional(),
66
+ plugins: z.array(z.string()).optional().default([]),
66
67
  changelog: z
67
68
  .object({
68
69
  root: changelogSchema,
@@ -88,6 +89,7 @@ export const DEFAULT_CONFIG = {
88
89
  ci: "ignore",
89
90
  build: "ignore",
90
91
  },
92
+ plugins: [],
91
93
  dependencyRules: {
92
94
  onMajorOfDependency: "major",
93
95
  onMinorOfDependency: "minor",
@@ -1,4 +1,5 @@
1
1
  import { AdapterIdentifierRegistry } from "../services/adapter-identifier-registry.js";
2
+ import { PluginContract } from "../plugins/plugin-loader.js";
2
3
  /**
3
4
  * Creates and configures the global adapter identifier registry.
4
5
  *
@@ -8,5 +9,5 @@ import { AdapterIdentifierRegistry } from "../services/adapter-identifier-regist
8
9
  * Central point for registering all supported project adapters.
9
10
  * To add a new adapter, implement {@link AdapterIdentifier} and add it to the array.
10
11
  */
11
- export declare function createAdapterIdentifierRegistry(): AdapterIdentifierRegistry;
12
+ export declare function createAdapterIdentifierRegistry(plugins: PluginContract[]): AdapterIdentifierRegistry;
12
13
  //# sourceMappingURL=adapter-identifier-registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-identifier-registry.d.ts","sourceRoot":"","sources":["../../src/factories/adapter-identifier-registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AAEvF;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,IAAI,yBAAyB,CAc3E"}
1
+ {"version":3,"file":"adapter-identifier-registry.d.ts","sourceRoot":"","sources":["../../src/factories/adapter-identifier-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,cAAc,EAAE,GACxB,yBAAyB,CAe3B"}
@@ -1,4 +1,3 @@
1
- import { GradleAdapterIdentifier } from "../adapters/gradle/services/gradle-adapter-identifier.js";
2
1
  import { AdapterIdentifierRegistry } from "../services/adapter-identifier-registry.js";
3
2
  /**
4
3
  * Creates and configures the global adapter identifier registry.
@@ -9,15 +8,15 @@ import { AdapterIdentifierRegistry } from "../services/adapter-identifier-regist
9
8
  * Central point for registering all supported project adapters.
10
9
  * To add a new adapter, implement {@link AdapterIdentifier} and add it to the array.
11
10
  */
12
- export function createAdapterIdentifierRegistry() {
11
+ export function createAdapterIdentifierRegistry(plugins) {
13
12
  // Array of all registered adapter identifiers
14
13
  // Order matters: first matching adapter is selected during auto-detection
15
14
  const identifiers = [
16
- new GradleAdapterIdentifier(),
17
15
  // Add future adapter identifiers here as they are implemented:
18
16
  // new MavenAdapterIdentifier(),
19
17
  // new NodeJSAdapterIdentifier(),
20
18
  // new PythonAdapterIdentifier(),
19
+ ...plugins.flatMap((plugin) => plugin.adapters.map((adapter) => adapter.adapterIdentifier())),
21
20
  ];
22
21
  // Create and return the registry with all registered identifiers
23
22
  return new AdapterIdentifierRegistry(identifiers);
@@ -1,4 +1,5 @@
1
1
  import { ModuleSystemFactory } from "../services/module-system-factory.js";
2
+ import { AdapterPluginContract } from "../plugins/plugin-loader.js";
2
3
  /**
3
4
  * Creates the appropriate module system factory for a given adapter.
4
5
  * @param adapterName - The identifier of the build system adapter (e.g., 'gradle', 'maven', 'npm')
@@ -6,5 +7,5 @@ import { ModuleSystemFactory } from "../services/module-system-factory.js";
6
7
  * @returns A ModuleSystemFactory instance configured for the specified adapter
7
8
  * @throws {Error} If the adapter name is not recognized or supported
8
9
  */
9
- export declare function createModuleSystemFactory(adapterName: string, repoRoot: string): ModuleSystemFactory;
10
+ export declare function createModuleSystemFactory(adapterName: string, adapterPlugins: AdapterPluginContract[], repoRoot: string): ModuleSystemFactory;
10
11
  //# sourceMappingURL=module-system-factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-system-factory.d.ts","sourceRoot":"","sources":["../../src/factories/module-system-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAI3E;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,mBAAmB,CASrB"}
1
+ {"version":3,"file":"module-system-factory.d.ts","sourceRoot":"","sources":["../../src/factories/module-system-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEpE;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,qBAAqB,EAAE,EACvC,QAAQ,EAAE,MAAM,GACf,mBAAmB,CASrB"}
@@ -1,5 +1,3 @@
1
- import { GradleModuleSystemFactory } from "../adapters/gradle/services/gradle-module-system-factory.js";
2
- import { GRADLE_ID } from "../adapters/gradle/constants.js";
3
1
  /**
4
2
  * Creates the appropriate module system factory for a given adapter.
5
3
  * @param adapterName - The identifier of the build system adapter (e.g., 'gradle', 'maven', 'npm')
@@ -7,12 +5,11 @@ import { GRADLE_ID } from "../adapters/gradle/constants.js";
7
5
  * @returns A ModuleSystemFactory instance configured for the specified adapter
8
6
  * @throws {Error} If the adapter name is not recognized or supported
9
7
  */
10
- export function createModuleSystemFactory(adapterName, repoRoot) {
11
- // Normalize adapter name to lowercase for case-insensitive matching
12
- switch (adapterName.toLowerCase()) {
13
- case GRADLE_ID:
14
- return new GradleModuleSystemFactory(repoRoot);
15
- default:
16
- throw new Error(`Unsupported adapter: ${adapterName}`);
8
+ export function createModuleSystemFactory(adapterName, adapterPlugins, repoRoot) {
9
+ const lowerCasedAdapterName = adapterName.toLowerCase();
10
+ const candidatePlugin = adapterPlugins.find((plugin) => plugin.id.toLowerCase() === lowerCasedAdapterName);
11
+ if (!candidatePlugin) {
12
+ throw new Error(`Unsupported adapter: ${adapterName}`);
17
13
  }
14
+ return candidatePlugin.moduleSystemFactory(repoRoot);
18
15
  }
package/dist/index.d.ts CHANGED
@@ -14,7 +14,9 @@ export { CommitAnalyzer } from './services/commit-analyzer.js';
14
14
  export { ConfigurationLoader } from './services/configuration-loader.js';
15
15
  export type { AdapterIdentifier, AdapterMetadata } from './services/adapter-identifier.js';
16
16
  export { AdapterIdentifierRegistry } from './services/adapter-identifier-registry.js';
17
- export type { ProjectInformation, Module } from './adapters/project-information.js';
17
+ export type { ModuleDetector } from './services/module-detector.js';
18
+ export type { VersionUpdateStrategy } from './services/version-update-strategy.js';
19
+ export type { RawProjectInformation, ProjectInformation, Module, BaseModule } from './adapters/project-information.js';
18
20
  export { createModuleSystemFactory } from './factories/module-system-factory.js';
19
21
  export type { ModuleSystemFactory } from './services/module-system-factory.js';
20
22
  export * from './git/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AAGtF,YAAY,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAGpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,YAAY,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAG/E,cAAc,gBAAgB,CAAC;AAG/B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,YAAY,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,YAAY,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAGnF,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAGvH,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,YAAY,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAG/E,cAAc,gBAAgB,CAAC;AAG/B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { AdapterIdentifier } from "../services/adapter-identifier.js";
2
+ import { ModuleSystemFactory } from "../services/module-system-factory.js";
3
+ export type PluginContract = {
4
+ id: string;
5
+ name: string;
6
+ description: string;
7
+ version: string;
8
+ author: string;
9
+ adapters: AdapterPluginContract[];
10
+ };
11
+ export type AdapterPluginContract = {
12
+ id: string;
13
+ adapterIdentifier: () => AdapterIdentifier;
14
+ moduleSystemFactory: (repoRoot: string) => ModuleSystemFactory;
15
+ };
16
+ export type PluginLoaderOptions = {
17
+ plugins: string[];
18
+ };
19
+ export declare class PluginLoader {
20
+ private readonly _plugins;
21
+ get plugins(): PluginContract[];
22
+ /**
23
+ * 1. Find the global node_modules path
24
+ * This is safer than guessing strings because it varies by OS (Windows vs Mac)
25
+ */
26
+ private getGlobalNodeModulesPath;
27
+ /**
28
+ * 2. Load ONLY the plugins specified in the whitelist
29
+ * @param pluginNames List of package names (e.g. ['my-plugin-alpha', '@scope/my-plugin-beta'])
30
+ */
31
+ loadSelectedPlugins(pluginNames: string[]): Promise<void>;
32
+ /**
33
+ * 3. Dynamically require the plugin
34
+ */
35
+ private loadSinglePlugin;
36
+ private isValidPlugin;
37
+ }
38
+ //# sourceMappingURL=plugin-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAM3E,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,qBAAqB,EAAE,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;IAC3C,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAChE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IAEnE,IAAI,OAAO,IAAI,cAAc,EAAE,CAE9B;IAED;;;OAGG;YACW,wBAAwB;IActC;;;OAGG;IACU,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE;IAyBtD;;OAEG;YACW,gBAAgB;IAoC9B,OAAO,CAAC,aAAa;CAGtB"}
@@ -0,0 +1,85 @@
1
+ import * as path from "path";
2
+ import { execa } from "execa";
3
+ import { exists } from "../utils/file.js";
4
+ import { logger } from "../utils/logger.js";
5
+ export class PluginLoader {
6
+ _plugins = new Map();
7
+ get plugins() {
8
+ return Array.from(this._plugins.values());
9
+ }
10
+ /**
11
+ * 1. Find the global node_modules path
12
+ * This is safer than guessing strings because it varies by OS (Windows vs Mac)
13
+ */
14
+ async getGlobalNodeModulesPath() {
15
+ try {
16
+ // Ask npm where the global root is
17
+ const { stdout } = await execa("npm", ["root", "-g"], {
18
+ encoding: "utf8",
19
+ });
20
+ const root = stdout.trim();
21
+ return root;
22
+ }
23
+ catch (e) {
24
+ logger.error("Could not determine global path");
25
+ return "";
26
+ }
27
+ }
28
+ /**
29
+ * 2. Load ONLY the plugins specified in the whitelist
30
+ * @param pluginNames List of package names (e.g. ['my-plugin-alpha', '@scope/my-plugin-beta'])
31
+ */
32
+ async loadSelectedPlugins(pluginNames) {
33
+ logger.info(`🔍 Loading plugins...`);
34
+ const globalRoot = await this.getGlobalNodeModulesPath();
35
+ if (!globalRoot || !(await exists(globalRoot))) {
36
+ logger.error(`❌ Global node_modules not found at: ${globalRoot}`);
37
+ return;
38
+ }
39
+ logger.info(`Plugins to load: ${pluginNames.join(", ")}`);
40
+ pluginNames.forEach(async (pluginName) => {
41
+ // Construct the absolute path to the specific package
42
+ const pluginPath = path.join(globalRoot, pluginName);
43
+ if (await exists(pluginPath)) {
44
+ await this.loadSinglePlugin(pluginPath);
45
+ }
46
+ else {
47
+ logger.warning(`⚠️ Plugin not found: ${pluginName} (looked in ${globalRoot})`);
48
+ logger.warning(` Run 'npm install -g ${pluginName}' to fix this.`);
49
+ }
50
+ });
51
+ }
52
+ /**
53
+ * 3. Dynamically require the plugin
54
+ */
55
+ async loadSinglePlugin(absolutePath) {
56
+ try {
57
+ // Dynamic require using the absolute path
58
+ // Note: If using ESM (import), use await import(absolutePath)
59
+ const rawModule = await import(absolutePath);
60
+ // Handle both "export default" and "module.exports"
61
+ const plugin = rawModule.default;
62
+ const isValid = this.isValidPlugin(plugin);
63
+ const isAlreadyLoaded = this._plugins.has(plugin.id);
64
+ if (!isValid) {
65
+ logger.error(`❌ Invalid plugin structure at ${absolutePath}. Missing required properties or methods.`);
66
+ return;
67
+ }
68
+ if (isAlreadyLoaded) {
69
+ logger.warning(`⚠️ Plugin with ID '${plugin.id}' is already loaded. Skipping duplicate from ${absolutePath}.`);
70
+ return;
71
+ }
72
+ this._plugins.set(plugin.id, plugin);
73
+ logger.info(`✅ Loaded: ${plugin.name}`);
74
+ }
75
+ catch (err) {
76
+ logger.error(`❌ Failed to load plugin at ${absolutePath}`, {
77
+ error: err,
78
+ });
79
+ }
80
+ }
81
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
+ isValidPlugin(plugin) {
83
+ return plugin && typeof plugin.onInit === "function";
84
+ }
85
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-metadata-provider.d.ts","sourceRoot":"","sources":["../../src/services/adapter-metadata-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAqB,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,qBAAa,uBAAuB;IAYhC,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZ1B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAE/C;;;;OAIG;gBAEgB,yBAAyB,EAAE,yBAAyB,EACpD,OAAO,EAAE,8BAA8B;IAK1D;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAQ7C;;;;OAIG;YACW,mBAAmB;IAoBjC;;;;OAIG;YACW,sBAAsB;CAiBrC"}
1
+ {"version":3,"file":"adapter-metadata-provider.d.ts","sourceRoot":"","sources":["../../src/services/adapter-metadata-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAqB,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,qBAAa,uBAAuB;IAYhC,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZ1B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAE/C;;;;OAIG;gBAEgB,yBAAyB,EAAE,yBAAyB,EACpD,OAAO,EAAE,8BAA8B;IAK1D;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAQ7C;;;;OAIG;YACW,mBAAmB;IAoBjC;;;;OAIG;YACW,sBAAsB;CAmBrC"}
@@ -58,7 +58,9 @@ export class AdapterMetadataProvider {
58
58
  if (!identifier) {
59
59
  throw new Error("No project adapter could be auto-detected. " +
60
60
  'Please specify the "adapter" input explicitly in your workflow. ' +
61
- "Supported adapters: gradle. For more information, see the documentation.");
61
+ "Supported adapters: " +
62
+ this.adapterIdentifierRegistry.getSupportedAdapters().join(", ") +
63
+ ". For more information, see the documentation.");
62
64
  }
63
65
  logger.info(`🔍 Auto-detected adapter: ${identifier.metadata.id}`);
64
66
  return identifier;
@@ -16,7 +16,7 @@ export class ConfigurationLoader {
16
16
  constructor(configurationValidator) {
17
17
  this.configurationValidator = configurationValidator;
18
18
  // Initialize cosmiconfig explorer once for reuse across multiple loads
19
- this.explorer = cosmiconfig("versu", { searchStrategy: 'global' });
19
+ this.explorer = cosmiconfig("versu", { searchStrategy: "global" });
20
20
  }
21
21
  /**
22
22
  * Loads and validates the VERSU configuration.
@@ -36,6 +36,7 @@ export declare class VersuRunner {
36
36
  private gitOperations;
37
37
  private adapterIdentifierRegistry;
38
38
  private adapterMetadataProvider;
39
+ private pluginLoader;
39
40
  constructor(options: RunnerOptions);
40
41
  private logStartupInfo;
41
42
  private logShutdownInfo;
@@ -1 +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;CACrC,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,CAAsB;IAChD,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,yBAAyB,CAA4B;IAC7D,OAAO,CAAC,uBAAuB,CAA0B;gBAE7C,OAAO,EAAE,aAAa;IAoBlC,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,eAAe;IAgCjB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC;YAYpB,KAAK;CA0IpB"}
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;AAM5D,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;CACrC,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,CAAsB;IAChD,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,yBAAyB,CAA6B;IAC9D,OAAO,CAAC,uBAAuB,CAA2B;IAC1D,OAAO,CAAC,YAAY,CAAgB;gBAExB,OAAO,EAAE,aAAa;IAYlC,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,eAAe;IAgCjB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC;YAYpB,KAAK;CA0JpB"}
@@ -14,6 +14,7 @@ import { createAdapterIdentifierRegistry } from "../factories/adapter-identifier
14
14
  import { ConfigurationValidator } from "./configuration-validator.js";
15
15
  import { banner } from "../utils/banner.js";
16
16
  import path from "path";
17
+ import { PluginLoader } from "../plugins/plugin-loader.js";
17
18
  export class VersuRunner {
18
19
  moduleSystemFactory; // Will be initialized in run()
19
20
  moduleRegistry; // Will be initialized in run()
@@ -30,6 +31,7 @@ export class VersuRunner {
30
31
  gitOperations; // Will be initialized in run()
31
32
  adapterIdentifierRegistry;
32
33
  adapterMetadataProvider;
34
+ pluginLoader; // Will be initialized in run()
33
35
  constructor(options) {
34
36
  this.options = {
35
37
  ...options,
@@ -37,11 +39,6 @@ export class VersuRunner {
37
39
  };
38
40
  // Initialize services
39
41
  this.configurationLoader = new ConfigurationLoader(new ConfigurationValidator());
40
- this.adapterIdentifierRegistry = createAdapterIdentifierRegistry();
41
- this.adapterMetadataProvider = new AdapterMetadataProvider(this.adapterIdentifierRegistry, {
42
- repoRoot: options.repoRoot,
43
- adapter: options.adapter,
44
- });
45
42
  }
46
43
  logStartupInfo() {
47
44
  logger.info(banner);
@@ -98,12 +95,20 @@ export class VersuRunner {
98
95
  }
99
96
  }
100
97
  async doRun() {
101
- this.adapter = await this.adapterMetadataProvider.getMetadata();
102
- // Initialize module system factory with resolved adapter
103
- this.moduleSystemFactory = createModuleSystemFactory(this.adapter.id, this.options.repoRoot);
104
98
  // Load configuration
105
99
  const configDirectory = path.join(this.options.repoRoot, ".versu");
106
100
  this.config = await this.configurationLoader.load(configDirectory);
101
+ this.pluginLoader = new PluginLoader();
102
+ await this.pluginLoader.loadSelectedPlugins(this.config.plugins);
103
+ const plugins = this.pluginLoader.plugins;
104
+ this.adapterIdentifierRegistry = createAdapterIdentifierRegistry(plugins);
105
+ this.adapterMetadataProvider = new AdapterMetadataProvider(this.adapterIdentifierRegistry, {
106
+ repoRoot: this.options.repoRoot,
107
+ adapter: this.options.adapter,
108
+ });
109
+ this.adapter = await this.adapterMetadataProvider.getMetadata();
110
+ // Initialize module system factory with resolved adapter
111
+ this.moduleSystemFactory = createModuleSystemFactory(this.adapter.id, plugins.flatMap((plugin) => plugin.adapters), this.options.repoRoot);
107
112
  // Check if working directory is clean
108
113
  if (!this.options.dryRun &&
109
114
  !isWorkingDirectoryClean({ cwd: this.options.repoRoot })) {
@@ -111,7 +116,7 @@ export class VersuRunner {
111
116
  }
112
117
  // Discover modules and get hierarchy manager
113
118
  logger.info("🔍 Discovering modules...");
114
- const detector = this.moduleSystemFactory.createDetector(path.resolve(path.join(configDirectory, 'project-information.json')));
119
+ const detector = this.moduleSystemFactory.createDetector(path.resolve(path.join(configDirectory, "project-information.json")));
115
120
  this.moduleRegistry = await detector.detect();
116
121
  // Log discovered modules through hierarchy manager
117
122
  const moduleIds = this.moduleRegistry.getModuleIds();
@@ -1,3 +1,3 @@
1
- export declare const VERSION = "0.5.1";
1
+ export declare const VERSION = "0.6.0";
2
2
  export declare const PACKAGE_NAME = "@versu/core";
3
3
  //# sourceMappingURL=version.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
2
  // Run 'npm run generate-version' to update this file.
3
- export const VERSION = "0.5.1";
3
+ export const VERSION = "0.6.0";
4
4
  export const PACKAGE_NAME = "@versu/core";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versu/core",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "VERSU (Core Library)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,13 +13,12 @@
13
13
  "scripts": {
14
14
  "prebuild": "node scripts/generate-version.js",
15
15
  "build": "npm run build:esm",
16
- "build:esm": "tsc --project tsconfig.json --outDir dist && npm run copy-assets",
17
- "build:cjs": "tsc --project tsconfig.cjs.json --outDir dist && npm run copy-assets",
16
+ "build:esm": "tsc --project tsconfig.json --outDir dist",
17
+ "build:cjs": "tsc --project tsconfig.cjs.json --outDir dist",
18
18
  "test": "vitest",
19
19
  "test:coverage": "vitest --coverage",
20
20
  "lint": "eslint src/**/*.ts",
21
- "format": "prettier --write src/**/*.ts",
22
- "copy-assets": "cpx \"src/adapters/gradle/init-project-information.gradle.kts\" \"dist/adapters/gradle/\""
21
+ "format": "prettier --write src/**/*.ts"
23
22
  },
24
23
  "keywords": [
25
24
  "versu",
@@ -1,13 +0,0 @@
1
- /** Standard filename for Gradle project properties file ('gradle.properties'). */
2
- export declare const GRADLE_PROPERTIES_FILE = "gradle.properties";
3
- /** Standard filename for Gradle build script using Groovy DSL ('build.gradle'). */
4
- export declare const GRADLE_BUILD_FILE = "build.gradle";
5
- /** Standard filename for Gradle build script using Kotlin DSL ('build.gradle.kts'). */
6
- export declare const GRADLE_BUILD_KTS_FILE = "build.gradle.kts";
7
- /** Standard filename for Gradle settings file using Groovy DSL ('settings.gradle'). */
8
- export declare const GRADLE_SETTINGS_FILE = "settings.gradle";
9
- /** Standard filename for Gradle settings file using Kotlin DSL ('settings.gradle.kts'). */
10
- export declare const GRADLE_SETTINGS_KTS_FILE = "settings.gradle.kts";
11
- /** Unique identifier for the Gradle adapter ('gradle'). */
12
- export declare const GRADLE_ID = "gradle";
13
- //# sourceMappingURL=constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/adapters/gradle/constants.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAE1D,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,uFAAuF;AACvF,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,uFAAuF;AACvF,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AAEtD,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D,2DAA2D;AAC3D,eAAO,MAAM,SAAS,WAAW,CAAC"}
@@ -1,12 +0,0 @@
1
- /** Standard filename for Gradle project properties file ('gradle.properties'). */
2
- export const GRADLE_PROPERTIES_FILE = 'gradle.properties';
3
- /** Standard filename for Gradle build script using Groovy DSL ('build.gradle'). */
4
- export const GRADLE_BUILD_FILE = 'build.gradle';
5
- /** Standard filename for Gradle build script using Kotlin DSL ('build.gradle.kts'). */
6
- export const GRADLE_BUILD_KTS_FILE = 'build.gradle.kts';
7
- /** Standard filename for Gradle settings file using Groovy DSL ('settings.gradle'). */
8
- export const GRADLE_SETTINGS_FILE = 'settings.gradle';
9
- /** Standard filename for Gradle settings file using Kotlin DSL ('settings.gradle.kts'). */
10
- export const GRADLE_SETTINGS_KTS_FILE = 'settings.gradle.kts';
11
- /** Unique identifier for the Gradle adapter ('gradle'). */
12
- export const GRADLE_ID = 'gradle';
@@ -1,19 +0,0 @@
1
- import { ProjectInformation, RawProjectInformation } from '../project-information.js';
2
- /**
3
- * Executes Gradle to collect raw project structure information.
4
- * Runs gradlew with init script to output JSON containing module hierarchy, versions, and dependencies.
5
- * @param projectRoot - Absolute path to the Gradle project root directory
6
- * @param outputFile - Path to output JSON file to be generated
7
- * @returns Promise resolving to raw project information as JSON
8
- * @throws {Error} If initialization script not found or Gradle execution fails
9
- */
10
- export declare function getRawProjectInformation(projectRoot: string, outputFile: string): Promise<RawProjectInformation>;
11
- /**
12
- * Transforms raw project information into structured, queryable format.
13
- * Normalizes modules, identifies root, parses versions, and maps dependencies.
14
- * @param projectInformation - Raw project information from Gradle
15
- * @returns Structured ProjectInformation with normalized data
16
- * @throws {Error} If no root module found in hierarchy
17
- */
18
- export declare function getProjectInformation(projectInformation: RawProjectInformation): ProjectInformation;
19
- //# sourceMappingURL=gradle-project-information.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gradle-project-information.d.ts","sourceRoot":"","sources":["../../../src/adapters/gradle/gradle-project-information.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AA4H1G;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAyEtH;AA2CD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,kBAAkB,EAAE,qBAAqB,GAAG,kBAAkB,CA6CnG"}
@@ -1,235 +0,0 @@
1
- import path, { join } from 'path';
2
- import { createInitialVersion, parseSemVer } from '../../semver/index.js';
3
- import { exists } from '../../utils/file.js';
4
- import { fileURLToPath } from 'url';
5
- import { execa } from 'execa';
6
- import fs from 'fs/promises';
7
- import crypto from 'crypto';
8
- import fg from 'fast-glob';
9
- import { parseProperties } from '../../utils/properties.js';
10
- import { logger } from '../../utils/logger.js';
11
- /**
12
- * Name of the Gradle wrapper script file.
13
- * Ensures consistent builds without requiring pre-installed Gradle.
14
- */
15
- const GRADLE_WRAPPER = 'gradlew';
16
- /**
17
- * Relative path to the Gradle initialization script within the action.
18
- * Injected into Gradle to collect project structure information as JSON.
19
- */
20
- const GRADLE_INIT_SCRIPT = './init-project-information.gradle.kts';
21
- /**
22
- * Finds all Gradle build files recursively under the project root.
23
- * Searches for settings.gradle, settings.gradle.kts, build.gradle, and build.gradle.kts files.
24
- * @param projectRoot - Absolute path to the Gradle project root directory
25
- * @returns Promise resolving to array of relative paths to Gradle build files
26
- */
27
- async function findGradleFiles(projectRoot) {
28
- const patterns = [
29
- '**/settings.gradle',
30
- '**/settings.gradle.kts',
31
- '**/build.gradle',
32
- '**/build.gradle.kts'
33
- ];
34
- const files = await fg(patterns, {
35
- cwd: projectRoot,
36
- absolute: false,
37
- ignore: ['**/node_modules/**', '**/build/**', '**/.gradle/**']
38
- });
39
- // Sort for consistent ordering
40
- return files.sort();
41
- }
42
- /**
43
- * Computes SHA-256 hash of all Gradle build files.
44
- * Used to detect changes in project configuration that would invalidate cached information.
45
- * @param projectRoot - Absolute path to the Gradle project root directory
46
- * @returns Promise resolving to hexadecimal hash string
47
- */
48
- async function computeGradleFilesHash(projectRoot) {
49
- const files = await findGradleFiles(projectRoot);
50
- const hash = crypto.createHash('sha256');
51
- for (const file of files) {
52
- const content = await fs.readFile(join(projectRoot, file), 'utf-8');
53
- hash.update(file); // Include file path for uniqueness
54
- hash.update(content);
55
- }
56
- return hash.digest('hex');
57
- }
58
- /**
59
- * Executes the Gradle wrapper script to generate project information.
60
- * Runs gradlew with initialization script to create the project-information.json file.
61
- * @param projectRoot - Absolute path to the Gradle project root directory
62
- * @param outputFile - Path to output JSON file to be generated
63
- * @throws {Error} If initialization script not found or Gradle execution fails
64
- */
65
- async function executeGradleScript(projectRoot, outputFile) {
66
- logger.info(`⚙️ Executing Gradle to collect project information...`);
67
- const gradlew = join(projectRoot, GRADLE_WRAPPER);
68
- const dirname = path.dirname(fileURLToPath(import.meta.url));
69
- const initScriptPath = join(dirname, GRADLE_INIT_SCRIPT);
70
- // Check if init script exists
71
- const scriptExists = await exists(initScriptPath);
72
- if (!scriptExists) {
73
- throw new Error(`Init script not found at ${initScriptPath}. ` +
74
- `Please create the ${GRADLE_INIT_SCRIPT} file.`);
75
- }
76
- // Prepare Gradle command arguments
77
- const args = [
78
- '--quiet', // Suppress non-error output for clean JSON
79
- '--console=plain', // Disable ANSI formatting
80
- '--init-script', // Inject initialization script
81
- initScriptPath,
82
- 'structure', // Custom task that outputs project structure
83
- `-PprojectInfoOutput=${outputFile}`
84
- ];
85
- // Execute Gradle wrapper with the prepared arguments
86
- const result = await execa(gradlew, args, {
87
- cwd: projectRoot, // Run from project root
88
- reject: false // Handle non-zero exit codes ourselves
89
- });
90
- // Check for Gradle execution failure
91
- if (result.exitCode !== 0) {
92
- throw new Error(`Gradle command failed with exit code ${result.exitCode}: ${result.stderr}`);
93
- }
94
- logger.info(`✅ Gradle project information generated at ${outputFile}.`);
95
- }
96
- /**
97
- * Executes Gradle to collect raw project structure information.
98
- * Runs gradlew with init script to output JSON containing module hierarchy, versions, and dependencies.
99
- * @param projectRoot - Absolute path to the Gradle project root directory
100
- * @param outputFile - Path to output JSON file to be generated
101
- * @returns Promise resolving to raw project information as JSON
102
- * @throws {Error} If initialization script not found or Gradle execution fails
103
- */
104
- export async function getRawProjectInformation(projectRoot, outputFile) {
105
- // Step 1: Check if project-information.json exists
106
- const fileExists = await exists(outputFile);
107
- let data = {};
108
- let executeScript = true;
109
- // Compute hash of all Gradle build files
110
- const currentHash = await computeGradleFilesHash(projectRoot);
111
- logger.debug(`🔍 Computed Gradle files hash: ${currentHash}`);
112
- if (fileExists) {
113
- logger.info(`💾 Cached project information found at ${outputFile}. Validating cache...`);
114
- // Step 2: File exists, check cache validity
115
- try {
116
- const fileContent = await fs.readFile(outputFile, 'utf-8');
117
- const cachedData = JSON.parse(fileContent);
118
- // Step 2.1: Compare hashes
119
- if (cachedData.hash === currentHash) {
120
- logger.info(`✅ Cache is valid. Using cached project information.`);
121
- // Cache hit - use cached data
122
- executeScript = false;
123
- data = cachedData.data;
124
- }
125
- else {
126
- logger.debug(`❌ Cache is invalid. Cached hash: ${cachedData.hash}`);
127
- logger.info(`🔄 Gradle files changed, regenerating project information...`);
128
- }
129
- // Cache miss - hash mismatch, need to regenerate
130
- }
131
- catch (error) {
132
- // If there's any error reading/parsing cached file, regenerate
133
- logger.warning(`⚠️ Failed to read cached project information: ${error}`);
134
- }
135
- }
136
- if (executeScript) {
137
- // Step 3: File doesn't exist or cache is invalid - execute Gradle script
138
- const outputFile = join(projectRoot, 'build', 'project-information.json');
139
- await executeGradleScript(projectRoot, outputFile);
140
- // Verify that the output file was created
141
- const fileExistsAfterExec = await exists(outputFile);
142
- if (!fileExistsAfterExec) {
143
- throw new Error(`Expected output file not found at ${outputFile}. ` +
144
- `Ensure that the Gradle init script is correctly generating the project information.`);
145
- }
146
- // Read the output file content
147
- const fileContent = await fs.readFile(outputFile, 'utf-8');
148
- // Parse JSON output from Gradle
149
- data = JSON.parse(fileContent.trim() || '{}');
150
- }
151
- // Compute hash and save with cache information
152
- const cachedData = {
153
- hash: currentHash,
154
- data
155
- };
156
- // Read gradle.properites and add version
157
- const projectInformation = await getInformationWithVersions(projectRoot, data);
158
- if (executeScript) {
159
- // Write back to file with hash for future cache validation
160
- const dirname = path.dirname(outputFile);
161
- await fs.mkdir(dirname, { recursive: true });
162
- await fs.writeFile(outputFile, JSON.stringify(cachedData, null, 2), 'utf-8');
163
- }
164
- return projectInformation;
165
- }
166
- /**
167
- * Reads gradle.properties to extract module versions and augment raw project information.
168
- * @param projectRoot - Absolute path to the Gradle project root directory
169
- * @param projectInformation - Gradle project information without versions
170
- * @returns Promise resolving to augmented RawProjectInformation with versions
171
- */
172
- async function getInformationWithVersions(projectRoot, projectInformation) {
173
- const gradlePropertiesFile = join(projectRoot, 'gradle.properties');
174
- const gradlePropertiesExists = await exists(gradlePropertiesFile);
175
- const result = {};
176
- let moduleVersions = new Map();
177
- if (gradlePropertiesExists) {
178
- moduleVersions = await parseProperties(gradlePropertiesFile);
179
- for (const [moduleId, module] of Object.entries(projectInformation)) {
180
- const version = moduleVersions.get(module.versionProperty);
181
- const resultVersion = version ? version : undefined;
182
- result[moduleId] = {
183
- ...module,
184
- version: resultVersion,
185
- declaredVersion: resultVersion !== undefined
186
- };
187
- }
188
- }
189
- return result;
190
- }
191
- /**
192
- * Transforms raw project information into structured, queryable format.
193
- * Normalizes modules, identifies root, parses versions, and maps dependencies.
194
- * @param projectInformation - Raw project information from Gradle
195
- * @returns Structured ProjectInformation with normalized data
196
- * @throws {Error} If no root module found in hierarchy
197
- */
198
- export function getProjectInformation(projectInformation) {
199
- const moduleIds = Object.keys(projectInformation);
200
- const modules = new Map();
201
- // Find root module by looking for the one with type 'root'
202
- let rootModule;
203
- for (const [moduleId, rawModule] of Object.entries(projectInformation)) {
204
- if (rawModule.type === 'root') {
205
- rootModule = moduleId;
206
- }
207
- // Create normalized Module object
208
- const module = {
209
- id: moduleId,
210
- name: rawModule.name,
211
- path: rawModule.path,
212
- type: rawModule.type,
213
- affectedModules: new Set(rawModule.affectedModules),
214
- // Parse version if present, otherwise create initial version
215
- version: rawModule.version === undefined ?
216
- createInitialVersion() :
217
- parseSemVer(rawModule.version),
218
- declaredVersion: rawModule.declaredVersion,
219
- };
220
- if ('versionProperty' in rawModule) {
221
- module['versionProperty'] = rawModule.versionProperty;
222
- }
223
- modules.set(moduleId, module);
224
- }
225
- // Validate that a root module was found
226
- if (!rootModule) {
227
- throw new Error('No root module found in hierarchy. ' +
228
- 'Every project hierarchy must contain exactly one module with type "root".');
229
- }
230
- return {
231
- moduleIds,
232
- modules,
233
- rootModule
234
- };
235
- }
@@ -1,163 +0,0 @@
1
- import groovy.json.JsonOutput
2
- import groovy.json.JsonGenerator
3
-
4
- /**
5
- * Retrieves the qualified version property name for the project.
6
- * Checks for properties in the order: "<projectName>.version", "<rootProjectName>.version", "version".
7
- */
8
- fun Project.qualifiedVersionProperty(): String {
9
- val candidates = listOf("${name}.version", "${rootProject.name}.version", "version")
10
- return candidates.first(::hasProperty)
11
- }
12
-
13
- /**
14
- * Retrieves the qualified version value for the project.
15
- * Uses the qualified version property name to find the property value.
16
- */
17
- fun Project.qualifiedVersion(): String =
18
- qualifiedVersionProperty().run(::findProperty) as String
19
-
20
- gradle.rootProject {
21
- /**
22
- * Collects and outputs project structure information as JSON.
23
- * Includes module hierarchy, paths, versions, and affected modules.
24
- */
25
- tasks.register("printProjectInformation") {
26
- group = "help"
27
- description = "Shows which subprojects are affected by changes (hierarchy + direct dependencies)."
28
- notCompatibleWithConfigurationCache("uses project information at configuration time")
29
-
30
- // Capture hierarchy data at configuration time
31
- val hierarchyDepsProvider = provider {
32
- val hierarchyEdges = linkedMapOf<String, Set<String>>()
33
-
34
- gradle.rootProject.allprojects.forEach { project ->
35
- val affectedChildren = mutableSetOf<String>()
36
-
37
- // Recursively collect all subprojects
38
- fun collectSubprojects(parent: org.gradle.api.Project) {
39
- parent.subprojects.forEach { child ->
40
- affectedChildren.add(child.path)
41
- collectSubprojects(child)
42
- }
43
- }
44
-
45
- collectSubprojects(project)
46
- hierarchyEdges[project.path] = affectedChildren.toSet()
47
- }
48
- hierarchyEdges
49
- }
50
-
51
- // Capture direct project dependencies at configuration time
52
- val dependencyDepsProvider = provider {
53
- val dependencyEdges = linkedMapOf<String, Set<String>>()
54
-
55
- gradle.rootProject.allprojects.forEach { project ->
56
- val directDeps = mutableSetOf<String>()
57
-
58
- project.configurations.forEach { config ->
59
- // Check regular dependencies
60
- config.dependencies.forEach { dep ->
61
- if (dep is ProjectDependency) {
62
- directDeps.add(dep.path)
63
- }
64
- }
65
-
66
- // Check dependency constraints (platform/BOM imports)
67
- config.dependencyConstraints.forEach { constraint ->
68
- // Constraints reference projects by group:name, need to resolve to project path
69
- val constraintProject = gradle.rootProject.allprojects.find { proj ->
70
- proj.group.toString() == constraint.group && proj.name == constraint.name
71
- }
72
- constraintProject?.let { directDeps.add(it.path) }
73
- }
74
- }
75
-
76
- dependencyEdges[project.path] = directDeps.toSet()
77
- }
78
- dependencyEdges
79
- }
80
-
81
- // Capture project metadata at configuration time
82
- val projectDataProvider = provider {
83
- val projectData = linkedMapOf<String, Map<String, Any?>>()
84
-
85
- gradle.rootProject.allprojects.forEach { project ->
86
- val relativePath = gradle.rootProject.projectDir.toPath().relativize(project.projectDir.toPath()).toString()
87
- val path = relativePath.ifEmpty { "." }
88
- val version = if (project.version == "unspecified") null else project.version
89
- val type = if (project == gradle.rootProject) "root" else "module"
90
- val versionProperty = project.qualifiedVersionProperty()
91
- val versionFromProperty = project.qualifiedVersion().takeIf {
92
- it.isNotBlank() && it != "unspecified"
93
- }
94
-
95
- projectData[project.path] = mapOf(
96
- "path" to path,
97
- "version" to version,
98
- "type" to type,
99
- "name" to project.name,
100
- "declaredVersion" to (versionFromProperty != null),
101
- "versionProperty" to versionProperty
102
- )
103
- }
104
- projectData
105
- }
106
-
107
- doLast {
108
- val hierarchyMap = hierarchyDepsProvider.get()
109
- val dependencyMap = dependencyDepsProvider.get()
110
- val projectDataMap = projectDataProvider.get()
111
-
112
- // Calculate directly affected modules only
113
- val result = projectDataMap.keys.sorted().associateWith { projectPath ->
114
- val projectInfo = projectDataMap.getValue(projectPath)
115
- val affectedModules = mutableSetOf<String>()
116
-
117
- // Add hierarchy children
118
- hierarchyMap[projectPath]?.let { affectedModules.addAll(it) }
119
-
120
- // Add projects that directly depend on this one
121
- dependencyMap.forEach { (dependent, dependencies) ->
122
- if (projectPath in dependencies) {
123
- affectedModules.add(dependent)
124
- }
125
- }
126
-
127
- mapOf(
128
- "path" to projectInfo["path"],
129
- "affectedModules" to affectedModules.toSortedSet(),
130
- "type" to projectInfo["type"],
131
- "name" to projectInfo["name"],
132
- "versionProperty" to projectInfo["versionProperty"]
133
- )
134
- }
135
-
136
- val generator = JsonGenerator.Options()
137
- .excludeNulls()
138
- .build()
139
-
140
- val json = JsonOutput.prettyPrint(generator.toJson(result))
141
-
142
- // Get output path from project property or use default
143
- val outputPath = project.findProperty("projectInfoOutput") as? String
144
- ?: "${layout.buildDirectory.asFile.get().path}/project-information.json"
145
-
146
- val outputFile = file(outputPath)
147
- outputFile.parentFile.mkdirs()
148
- outputFile.writeText(json)
149
-
150
- println("Project information written to: ${outputFile.absolutePath}")
151
- }
152
- }
153
-
154
- /**
155
- * Convenience alias for printProjectInformation task.
156
- * Usage: ./gradlew --init-script <path> structure
157
- */
158
- tasks.register("structure") {
159
- group = "help"
160
- description = "Show project structure information"
161
- dependsOn("printProjectInformation")
162
- }
163
- }
@@ -1,21 +0,0 @@
1
- import { AdapterIdentifier } from '../../../services/adapter-identifier.js';
2
- /**
3
- * Adapter identifier for Gradle-based projects.
4
- * Detects Gradle projects by looking for gradle.properties, build.gradle(.kts), or settings.gradle(.kts) files.
5
- */
6
- export declare class GradleAdapterIdentifier implements AdapterIdentifier {
7
- /** Metadata describing this Gradle adapter (id: 'gradle', supports snapshots). */
8
- readonly metadata: {
9
- id: string;
10
- capabilities: {
11
- supportsSnapshots: boolean;
12
- };
13
- };
14
- /**
15
- * Determines whether the specified project is a Gradle project.
16
- * @param projectRoot - Absolute path to the project root directory
17
- * @returns True if any Gradle-specific file is found in the project root
18
- */
19
- accept(projectRoot: string): Promise<boolean>;
20
- }
21
- //# sourceMappingURL=gradle-adapter-identifier.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gradle-adapter-identifier.d.ts","sourceRoot":"","sources":["../../../../src/adapters/gradle/services/gradle-adapter-identifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAe5E;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,iBAAiB;IAC/D,kFAAkF;IAClF,QAAQ,CAAC,QAAQ;;;;;MAKf;IAEF;;;;OAIG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAkBpD"}
@@ -1,44 +0,0 @@
1
- import * as fs from 'fs/promises';
2
- import { GRADLE_PROPERTIES_FILE, GRADLE_BUILD_FILE, GRADLE_BUILD_KTS_FILE, GRADLE_SETTINGS_FILE, GRADLE_SETTINGS_KTS_FILE, GRADLE_ID } from '../constants.js';
3
- import { exists } from '../../../utils/file.js';
4
- import { logger } from '../../../utils/logger.js';
5
- /** List of file names that indicate a Gradle project. */
6
- const GRADLE_FILES = [
7
- GRADLE_PROPERTIES_FILE,
8
- GRADLE_BUILD_FILE,
9
- GRADLE_BUILD_KTS_FILE,
10
- GRADLE_SETTINGS_FILE,
11
- GRADLE_SETTINGS_KTS_FILE
12
- ];
13
- /**
14
- * Adapter identifier for Gradle-based projects.
15
- * Detects Gradle projects by looking for gradle.properties, build.gradle(.kts), or settings.gradle(.kts) files.
16
- */
17
- export class GradleAdapterIdentifier {
18
- /** Metadata describing this Gradle adapter (id: 'gradle', supports snapshots). */
19
- metadata = {
20
- id: GRADLE_ID,
21
- capabilities: {
22
- supportsSnapshots: true
23
- }
24
- };
25
- /**
26
- * Determines whether the specified project is a Gradle project.
27
- * @param projectRoot - Absolute path to the project root directory
28
- * @returns True if any Gradle-specific file is found in the project root
29
- */
30
- async accept(projectRoot) {
31
- // Check if project root directory exists
32
- const projectRootExists = await exists(projectRoot);
33
- if (!projectRootExists) {
34
- // Log for debugging and return false immediately
35
- logger.debug(`Project root does not exist: ${projectRoot}`);
36
- return false;
37
- }
38
- // Read directory contents (only top-level files)
39
- const files = await fs.readdir(projectRoot);
40
- // Check if any known Gradle file is present in the directory
41
- const hasGradleFile = GRADLE_FILES.some(file => files.includes(file));
42
- return hasGradleFile;
43
- }
44
- }
@@ -1,19 +0,0 @@
1
- import { ModuleDetector } from "../../../services/module-detector.js";
2
- import { ModuleRegistry } from '../../../services/module-registry.js';
3
- /**
4
- * Module detector for Gradle-based projects.
5
- * Executes Gradle to discover all modules and their dependencies, returning a ModuleRegistry.
6
- */
7
- export declare class GradleModuleDetector implements ModuleDetector {
8
- readonly repoRoot: string;
9
- readonly outputFile: string;
10
- /** Absolute path to the repository root directory. */
11
- constructor(repoRoot: string, outputFile: string);
12
- /**
13
- * Detects and catalogs all modules in the Gradle project.
14
- * @returns ModuleRegistry containing all discovered modules and their relationships
15
- * @throws {Error} If Gradle execution fails or project information cannot be parsed
16
- */
17
- detect(): Promise<ModuleRegistry>;
18
- }
19
- //# sourceMappingURL=gradle-module-detector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gradle-module-detector.d.ts","sourceRoot":"","sources":["../../../../src/adapters/gradle/services/gradle-module-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAMtE;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IAE7C,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM;IADlE,sDAAsD;gBACjC,QAAQ,EAAE,MAAM,EAAW,UAAU,EAAE,MAAM;IAElE;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;CAUxC"}
@@ -1,28 +0,0 @@
1
- import { ModuleRegistry } from '../../../services/module-registry.js';
2
- import { getRawProjectInformation, getProjectInformation } from '../gradle-project-information.js';
3
- /**
4
- * Module detector for Gradle-based projects.
5
- * Executes Gradle to discover all modules and their dependencies, returning a ModuleRegistry.
6
- */
7
- export class GradleModuleDetector {
8
- repoRoot;
9
- outputFile;
10
- /** Absolute path to the repository root directory. */
11
- constructor(repoRoot, outputFile) {
12
- this.repoRoot = repoRoot;
13
- this.outputFile = outputFile;
14
- }
15
- /**
16
- * Detects and catalogs all modules in the Gradle project.
17
- * @returns ModuleRegistry containing all discovered modules and their relationships
18
- * @throws {Error} If Gradle execution fails or project information cannot be parsed
19
- */
20
- async detect() {
21
- // Step 1: Execute Gradle and collect raw project structure data
22
- const rawProjectInformation = await getRawProjectInformation(this.repoRoot, this.outputFile);
23
- // Step 2: Parse and transform raw data into structured module information
24
- const projectInformation = getProjectInformation(rawProjectInformation);
25
- // Step 3: Create a registry for efficient module access and querying
26
- return new ModuleRegistry(projectInformation);
27
- }
28
- }
@@ -1,26 +0,0 @@
1
- import { ModuleSystemFactory } from "../../../services/module-system-factory.js";
2
- import { ModuleDetector } from "../../../services/module-detector.js";
3
- import { VersionUpdateStrategy } from "../../../services/version-update-strategy.js";
4
- import { ModuleRegistry } from "../../../services/module-registry.js";
5
- /**
6
- * Factory for creating Gradle-specific module system components.
7
- * Creates module detector and version update strategy instances.
8
- */
9
- export declare class GradleModuleSystemFactory implements ModuleSystemFactory {
10
- private readonly repoRoot;
11
- /** Absolute path to the repository root directory. */
12
- constructor(repoRoot: string);
13
- /**
14
- * Creates a Gradle-specific module detector.
15
- * @param outputFile - Path to the output file for project information
16
- * @returns GradleModuleDetector instance configured with the repository root
17
- */
18
- createDetector(outputFile: string): ModuleDetector;
19
- /**
20
- * Creates a Gradle-specific version update strategy.
21
- * @param moduleRegistry - ModuleRegistry containing all detected modules
22
- * @returns GradleVersionUpdateStrategy instance configured with the repository root
23
- */
24
- createVersionUpdateStrategy(moduleRegistry: ModuleRegistry): VersionUpdateStrategy;
25
- }
26
- //# sourceMappingURL=gradle-module-system-factory.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gradle-module-system-factory.d.ts","sourceRoot":"","sources":["../../../../src/adapters/gradle/services/gradle-module-system-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AAGrF,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,mBAAmB;IAEvD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IADrC,sDAAsD;gBACzB,QAAQ,EAAE,MAAM;IAE7C;;;;OAIG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc;IAIlD;;;;OAIG;IACH,2BAA2B,CAAC,cAAc,EAAE,cAAc,GAAG,qBAAqB;CAGnF"}
@@ -1,29 +0,0 @@
1
- import { GradleModuleDetector } from './gradle-module-detector.js';
2
- import { GradleVersionUpdateStrategy } from './gradle-version-update-strategy.js';
3
- /**
4
- * Factory for creating Gradle-specific module system components.
5
- * Creates module detector and version update strategy instances.
6
- */
7
- export class GradleModuleSystemFactory {
8
- repoRoot;
9
- /** Absolute path to the repository root directory. */
10
- constructor(repoRoot) {
11
- this.repoRoot = repoRoot;
12
- }
13
- /**
14
- * Creates a Gradle-specific module detector.
15
- * @param outputFile - Path to the output file for project information
16
- * @returns GradleModuleDetector instance configured with the repository root
17
- */
18
- createDetector(outputFile) {
19
- return new GradleModuleDetector(this.repoRoot, outputFile);
20
- }
21
- /**
22
- * Creates a Gradle-specific version update strategy.
23
- * @param moduleRegistry - ModuleRegistry containing all detected modules
24
- * @returns GradleVersionUpdateStrategy instance configured with the repository root
25
- */
26
- createVersionUpdateStrategy(moduleRegistry) {
27
- return new GradleVersionUpdateStrategy(this.repoRoot, moduleRegistry);
28
- }
29
- }
@@ -1,23 +0,0 @@
1
- import { VersionUpdateStrategy } from "../../../services/version-update-strategy.js";
2
- import { ModuleRegistry } from '../../../services/module-registry.js';
3
- /**
4
- * Gradle-specific implementation for version update operations.
5
- * Updates module versions by modifying gradle.properties file.
6
- */
7
- export declare class GradleVersionUpdateStrategy implements VersionUpdateStrategy {
8
- private readonly moduleRegistry;
9
- /** Absolute path to the gradle.properties file. */
10
- private readonly versionFilePath;
11
- /**
12
- * Creates a new Gradle version update strategy.
13
- * @param repoRoot - Absolute path to the repository root directory
14
- */
15
- constructor(repoRoot: string, moduleRegistry: ModuleRegistry);
16
- /**
17
- * Writes version updates for multiple modules to gradle.properties.
18
- * @param moduleVersions - Map of module IDs to new version strings
19
- * @throws {Error} If the file cannot be read or written
20
- */
21
- writeVersionUpdates(moduleVersions: Map<string, string>): Promise<void>;
22
- }
23
- //# sourceMappingURL=gradle-version-update-strategy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gradle-version-update-strategy.d.ts","sourceRoot":"","sources":["../../../../src/adapters/gradle/services/gradle-version-update-strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AAGrF,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;GAGG;AACH,qBAAa,2BAA4B,YAAW,qBAAqB;IAQzC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAP7D,mDAAmD;IACnD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAEzC;;;OAGG;gBACS,QAAQ,EAAE,MAAM,EAAmB,cAAc,EAAE,cAAc;IAI7E;;;;OAIG;IACG,mBAAmB,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAe9E"}
@@ -1,38 +0,0 @@
1
- import { join } from 'path';
2
- import { upsertProperties } from '../../../utils/properties.js';
3
- import { GRADLE_PROPERTIES_FILE } from '../constants.js';
4
- /**
5
- * Gradle-specific implementation for version update operations.
6
- * Updates module versions by modifying gradle.properties file.
7
- */
8
- export class GradleVersionUpdateStrategy {
9
- moduleRegistry;
10
- /** Absolute path to the gradle.properties file. */
11
- versionFilePath;
12
- /**
13
- * Creates a new Gradle version update strategy.
14
- * @param repoRoot - Absolute path to the repository root directory
15
- */
16
- constructor(repoRoot, moduleRegistry) {
17
- this.moduleRegistry = moduleRegistry;
18
- this.versionFilePath = join(repoRoot, GRADLE_PROPERTIES_FILE);
19
- }
20
- /**
21
- * Writes version updates for multiple modules to gradle.properties.
22
- * @param moduleVersions - Map of module IDs to new version strings
23
- * @throws {Error} If the file cannot be read or written
24
- */
25
- async writeVersionUpdates(moduleVersions) {
26
- // Convert module IDs to property names
27
- // Example: ':app' → 'app.version', ':' → 'version'
28
- const propertyUpdates = new Map();
29
- for (const [moduleId, versionString] of moduleVersions) {
30
- const module = this.moduleRegistry.getModule(moduleId);
31
- const propertyName = module['versionProperty'];
32
- propertyUpdates.set(propertyName, versionString);
33
- }
34
- // Write all properties to gradle.properties file in one atomic operation
35
- // This ensures consistency and prevents partial updates
36
- await upsertProperties(this.versionFilePath, propertyUpdates);
37
- }
38
- }