@quark-hq/quark-scripts 0.0.1

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 (86) hide show
  1. package/LICENSE +21 -0
  2. package/dist/app/base-application.js +67 -0
  3. package/dist/app/buildApplication.js +20 -0
  4. package/dist/app/copyStaticApplication.js +34 -0
  5. package/dist/app/devApplication.js +59 -0
  6. package/dist/app/prod-publish-application.js +124 -0
  7. package/dist/app/publish-dev-application.js +104 -0
  8. package/dist/app/publishDevApplication.js +16 -0
  9. package/dist/app/release-application.js +85 -0
  10. package/dist/app/releaseApplication.js +154 -0
  11. package/dist/app/unfreeze-application.js +75 -0
  12. package/dist/app/watchStaticApplication.js +34 -0
  13. package/dist/cli/cli-containers.js +70 -0
  14. package/dist/cli/cliCommand.js +2 -0
  15. package/dist/cli/cliContainers.js +62 -0
  16. package/dist/cli/commands/buildCommands.js +17 -0
  17. package/dist/cli/commands/copyStaticCommands.js +17 -0
  18. package/dist/cli/commands/devCommands.js +17 -0
  19. package/dist/cli/commands/prod-publish-commands.js +18 -0
  20. package/dist/cli/commands/publish-dev-commands.js +17 -0
  21. package/dist/cli/commands/publishDevCommands.js +17 -0
  22. package/dist/cli/commands/release-commands.js +17 -0
  23. package/dist/cli/commands/releaseCommands.js +17 -0
  24. package/dist/cli/commands/relesaeCommand.js +15 -0
  25. package/dist/cli/commands/unfreeze-commands.js +17 -0
  26. package/dist/cli/commands/watchStaticCommands.js +17 -0
  27. package/dist/cli/program.js +16 -0
  28. package/dist/commands/index.d.ts +8 -0
  29. package/dist/commands/index.js +132 -0
  30. package/dist/commands/index.js.map +1 -0
  31. package/dist/domain/graph.js +2 -0
  32. package/dist/domain/new-package-freeze-from-map.js +21 -0
  33. package/dist/domain/resolve-workspace-dependency-specifier-for-freeze-map.js +33 -0
  34. package/dist/domain/reverse-dependents.js +45 -0
  35. package/dist/domain/topological-sorting.js +43 -0
  36. package/dist/domain/transitive-dependents.js +25 -0
  37. package/dist/domain/workspace-transitive-dependencies.js +25 -0
  38. package/dist/errors/unfreeze-blocked-error.js +44 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js +32 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/infrastructure/adapters/base-release-adapter.js +281 -0
  43. package/dist/infrastructure/adapters/maven-prod-publish-adapter.js +48 -0
  44. package/dist/infrastructure/adapters/maven-release-adapter.js +58 -0
  45. package/dist/infrastructure/adapters/node-prod-publish-adapter.js +111 -0
  46. package/dist/infrastructure/adapters/node-release-adapter/node-file-update.js +1 -0
  47. package/dist/infrastructure/adapters/node-release-adapter/node-release-adapter.js +289 -0
  48. package/dist/infrastructure/adapters/node-release-adapter.js +202 -0
  49. package/dist/infrastructure/config/loadDotEnv.js +38 -0
  50. package/dist/infrastructure/config/nodeRegistryEnv.js +41 -0
  51. package/dist/infrastructure/config/quarkConfigProvider.js +50 -0
  52. package/dist/infrastructure/git/gitService.js +179 -0
  53. package/dist/infrastructure/graph/nxGraphProvide.js +84 -0
  54. package/dist/infrastructure/logging/consoleLogger.js +25 -0
  55. package/dist/infrastructure/process/nodeProcessRunner.js +14 -0
  56. package/dist/infrastructure/release/git-release-map-store.js +64 -0
  57. package/dist/ports/config.js +2 -0
  58. package/dist/ports/git.js +2 -0
  59. package/dist/ports/graph.js +2 -0
  60. package/dist/ports/logger.js +2 -0
  61. package/dist/ports/map.js +2 -0
  62. package/dist/ports/platform-dev-publish-adapter.js +2 -0
  63. package/dist/ports/platform-prod-publish-adapter.js +2 -0
  64. package/dist/ports/platform-release-adapter.js +2 -0
  65. package/dist/ports/processRunner.js +2 -0
  66. package/dist/ports/prompts.js +2 -0
  67. package/dist/ports/release-map-store.js +2 -0
  68. package/dist/scripts/dev.d.ts +20 -0
  69. package/dist/scripts/dev.js +204 -0
  70. package/dist/scripts/dev.js.map +1 -0
  71. package/dist/scripts/map.json +1616 -0
  72. package/dist/scripts/prod.d.ts +1 -0
  73. package/dist/scripts/prod.js +143 -0
  74. package/dist/scripts/prod.js.map +1 -0
  75. package/dist/scripts/release.d.ts +51 -0
  76. package/dist/scripts/release.js +833 -0
  77. package/dist/scripts/release.js.map +1 -0
  78. package/dist/tests/index.test.js +13 -0
  79. package/dist/tests/mocks/release.js +8 -0
  80. package/dist/tests/unit/release/index.test.js +32 -0
  81. package/dist/utils/checkIfFreeze.js +1 -0
  82. package/dist/utils/commit.js +39 -0
  83. package/dist/utils/drawRepoStatus.js +66 -0
  84. package/dist/utils/file.js +14 -0
  85. package/dist/utils/metrics.js +22 -0
  86. package/package.json +64 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Acko Technologies
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseApplication = void 0;
4
+ const path_1 = require("path");
5
+ /**
6
+ * Shared infrastructure for any command that operates on the monorepo graph:
7
+ * - repository health checks
8
+ * - dependency graph construction
9
+ * - changed-file detection and package ownership resolution
10
+ */
11
+ class BaseApplication {
12
+ constructor(logger, git, graphProvider, masterBranch) {
13
+ this.logger = logger;
14
+ this.git = git;
15
+ this.graphProvider = graphProvider;
16
+ this.masterBranch = masterBranch;
17
+ }
18
+ async ensureRepositoryHealthy() {
19
+ const repoRoot = await this.git.getRepositoryRoot();
20
+ this.logger.info(`Repo root: ${repoRoot}`);
21
+ const currentBranch = await this.git.getCurrentBranch();
22
+ this.logger.info(`Current branch: ${currentBranch}`);
23
+ await this.git.fetch(this.masterBranch);
24
+ const behind = await this.git.commitsBehind(this.masterBranch);
25
+ if (behind > 0) {
26
+ throw new Error(`Branch is ${behind} commits behind origin/${this.masterBranch}`);
27
+ }
28
+ return repoRoot;
29
+ }
30
+ async buildGraph() {
31
+ const graph = await this.graphProvider.build();
32
+ if (!graph || Object.keys(graph.adjacency).length === 0) {
33
+ throw new Error("Dependency graph is empty");
34
+ }
35
+ return graph;
36
+ }
37
+ async getChangedAbsolutePaths(repoRoot) {
38
+ const relativeFiles = await this.git.getChangedFiles(this.masterBranch);
39
+ return relativeFiles.map((f) => (0, path_1.resolve)(repoRoot, f));
40
+ }
41
+ isPackageAffected(packageDir, changedFiles) {
42
+ return changedFiles.some((file) => file.startsWith(packageDir + "/"));
43
+ }
44
+ mapFilesToPackages(changedFiles, metadata) {
45
+ const changed = new Set();
46
+ for (const file of changedFiles) {
47
+ const owner = this.findOwningPackage(file, metadata);
48
+ if (owner !== null) {
49
+ changed.add(owner);
50
+ }
51
+ }
52
+ return changed;
53
+ }
54
+ findOwningPackage(file, metadata) {
55
+ let bestMatch = null;
56
+ for (const [name, { rootDir }] of Object.entries(metadata)) {
57
+ if (!file.startsWith(rootDir + "/"))
58
+ continue;
59
+ if (bestMatch === null ||
60
+ rootDir.length > bestMatch.rootDir.length) {
61
+ bestMatch = { name, rootDir };
62
+ }
63
+ }
64
+ return bestMatch?.name ?? null;
65
+ }
66
+ }
67
+ exports.BaseApplication = BaseApplication;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BuildApplication = void 0;
4
+ class BuildApplication {
5
+ constructor(logger, processRunner) {
6
+ this.logger = logger;
7
+ this.processRunner = processRunner;
8
+ }
9
+ async execute(options) {
10
+ this.logger.info("🔨 Building package...");
11
+ this.logger.info("→ Compiling TypeScript...");
12
+ this.processRunner.run("npx", ["--yes", "tsc"]);
13
+ if (!options.skipStatic) {
14
+ this.logger.info("→ Copying static assets...");
15
+ this.processRunner.run("npx", ["--yes", "quark-scripts", "copy-static"]);
16
+ }
17
+ this.logger.success("✅ Build completed successfully");
18
+ }
19
+ }
20
+ exports.BuildApplication = BuildApplication;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CopyStaticApplication = void 0;
4
+ const IGNORE_PATTERNS = [
5
+ "dist/**",
6
+ "node_modules/**",
7
+ "**/*.ts",
8
+ "**/*.tsx",
9
+ "**/*.js",
10
+ "**/*.jsx",
11
+ "**/*.tsbuildinfo",
12
+ "**/tsconfig.json",
13
+ "**/.npmrc",
14
+ "**/package-lock.json",
15
+ ];
16
+ class CopyStaticApplication {
17
+ constructor(logger, processRunner) {
18
+ this.logger = logger;
19
+ this.processRunner = processRunner;
20
+ }
21
+ async execute() {
22
+ this.logger.info("📦 Copying static assets...");
23
+ const copyfilesArgs = [
24
+ "--yes",
25
+ "copyfiles",
26
+ "**/*",
27
+ "dist/",
28
+ ...IGNORE_PATTERNS.flatMap((p) => ["--exclude", p]),
29
+ ];
30
+ this.processRunner.run("npx", copyfilesArgs);
31
+ this.logger.success("✅ Static assets copied successfully");
32
+ }
33
+ }
34
+ exports.CopyStaticApplication = CopyStaticApplication;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DevApplication = void 0;
4
+ const IGNORE_PATTERNS = [
5
+ "dist/**",
6
+ "node_modules/**",
7
+ "**/*.ts",
8
+ "**/*.tsx",
9
+ "**/*.js",
10
+ "**/*.jsx",
11
+ "**/*.tsbuildinfo",
12
+ "**/tsconfig.json",
13
+ "**/.npmrc",
14
+ "**/package-lock.json",
15
+ ];
16
+ class DevApplication {
17
+ constructor(logger, processRunner) {
18
+ this.logger = logger;
19
+ this.processRunner = processRunner;
20
+ }
21
+ async execute(options) {
22
+ this.logger.info("🚀 Starting development mode...");
23
+ if (!options.skipInitialCopy) {
24
+ this.logger.info("→ Initial copy of static assets...");
25
+ try {
26
+ this.processRunner.run("npx", [
27
+ "--yes",
28
+ "quark-scripts",
29
+ "copy-static",
30
+ ]);
31
+ }
32
+ catch {
33
+ this.logger.warn("⚠️ Initial copy failed, continuing...");
34
+ }
35
+ }
36
+ const tscWatchCmd = "npx --yes tsc --watch --preserveWatchOutput";
37
+ const chokidarCmd = [
38
+ "npx",
39
+ "--yes",
40
+ "chokidar",
41
+ "**/*",
42
+ ...IGNORE_PATTERNS.flatMap((p) => ["-i", p]),
43
+ "-c",
44
+ "quark-scripts copy-static",
45
+ ].join(" ");
46
+ this.logger.info("→ Starting watchers...");
47
+ this.processRunner.run("npx", [
48
+ "--yes",
49
+ "concurrently",
50
+ "--names",
51
+ "TSC,ASSETS",
52
+ "--prefix-colors",
53
+ "cyan,magenta",
54
+ tscWatchCmd,
55
+ chokidarCmd,
56
+ ]);
57
+ }
58
+ }
59
+ exports.DevApplication = DevApplication;
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProdPublishApplication = void 0;
4
+ class ProdPublishApplication {
5
+ constructor(logger, git, graphProvider, adapters, topoSorter, quarkConfig) {
6
+ this.logger = logger;
7
+ this.git = git;
8
+ this.graphProvider = graphProvider;
9
+ this.adapters = adapters;
10
+ this.topoSorter = topoSorter;
11
+ this.quarkConfig = quarkConfig;
12
+ }
13
+ async execute(targetTag) {
14
+ this.logger.info("Building dependency graph...");
15
+ const graph = await this.graphProvider.build();
16
+ this.logger.info("Resolving git tags...");
17
+ const [previousTag, latestTag] = await this.git.getTags(targetTag);
18
+ if (previousTag === null) {
19
+ this.logger.info(`No older tag: using empty release map baseline → ${latestTag}`);
20
+ }
21
+ else {
22
+ this.logger.info(`Comparing tags: ${previousTag} → ${latestTag}`);
23
+ }
24
+ const { changedPackages, oldMap, newMap } = await this.detectChangedPackages(previousTag, latestTag);
25
+ const freezeFiltered = this.applyFreezePublishFilter(changedPackages, oldMap, newMap);
26
+ if (freezeFiltered.length === 0) {
27
+ this.logger.warn(changedPackages.length === 0
28
+ ? "No package changes detected for this release (map at latest tag vs baseline)."
29
+ : "No packages qualify for prod publish after freeze policy (same-version unfrozen map-only updates are skipped).");
30
+ return;
31
+ }
32
+ const ordered = this.topoSorter.sort(graph.adjacency, freezeFiltered);
33
+ this.logger.info(`Changed packages: ${ordered.join(", ")}`);
34
+ const validated = await this.validateAll(ordered, graph.metadata);
35
+ await this.publishAll(validated);
36
+ this.logger.success(`Published ${validated.length} package(s) to prod registry.`);
37
+ }
38
+ async validateAll(changedPackages, metadata) {
39
+ const toPublish = [];
40
+ for (const pkgName of changedPackages) {
41
+ const meta = metadata[pkgName];
42
+ if (!meta) {
43
+ this.logger.warn(`Package "${pkgName}" not found in graph, skipping.`);
44
+ continue;
45
+ }
46
+ const adapter = this.adapters.find((a) => a.supports(meta));
47
+ if (!adapter) {
48
+ this.logger.warn(`No prod-publish adapter for platform "${meta.platform}", skipping ${pkgName}.`);
49
+ continue;
50
+ }
51
+ const identity = await adapter.readPackageIdentity(meta.rootDir);
52
+ const exists = await adapter.versionExistsInRegistry(identity.name, identity.version);
53
+ if (exists) {
54
+ throw new Error(`Version ${identity.name}@${identity.version} already exists in prod registry. Aborting all publish operations.`);
55
+ }
56
+ toPublish.push({
57
+ packageName: pkgName,
58
+ packageDir: meta.rootDir,
59
+ adapter,
60
+ identity,
61
+ });
62
+ }
63
+ return toPublish;
64
+ }
65
+ async publishAll(packages) {
66
+ for (const { adapter, identity, packageDir } of packages) {
67
+ this.logger.info(`Publishing ${identity.name}@${identity.version}...`);
68
+ await adapter.publish(packageDir);
69
+ this.logger.success(`Published ${identity.name}@${identity.version}`);
70
+ }
71
+ }
72
+ /**
73
+ * When {@link QuarkConfig.release.freeze} is enabled, skip **updated** packages that
74
+ * stayed on the same `newVersion` while remaining unfrozen — those
75
+ * are map-only churn (e.g. changelog) and are not registry-ready compared to frozen
76
+ * artifacts. New packages and any version bump still publish.
77
+ */
78
+ applyFreezePublishFilter(changed, oldMap, newMap) {
79
+ if (!this.quarkConfig.release.freeze) {
80
+ return changed;
81
+ }
82
+ return changed.filter((key) => {
83
+ const prev = oldMap[key];
84
+ const next = newMap[key];
85
+ if (!prev) {
86
+ return true;
87
+ }
88
+ const prevVer = prev.newVersion ?? "";
89
+ const nextVer = next.newVersion ?? "";
90
+ if (prevVer !== nextVer) {
91
+ return true;
92
+ }
93
+ if (next.frozen === true) {
94
+ return true;
95
+ }
96
+ this.logger.warn(`Skipping prod publish for "${key}": release.freeze is enabled, version unchanged (${nextVer}), and package is not frozen (map-only update).`);
97
+ return false;
98
+ });
99
+ }
100
+ async detectChangedPackages(previousTag, latestTag) {
101
+ const oldMapRaw = previousTag === null
102
+ ? "{}"
103
+ : await this.git.readFileFromRef(".release/map.json", previousTag);
104
+ const newMapRaw = await this.git.readFileFromRef(".release/map.json", latestTag);
105
+ const oldMap = JSON.parse(oldMapRaw);
106
+ const newMap = JSON.parse(newMapRaw);
107
+ const allKeys = new Set([
108
+ ...Object.keys(oldMap),
109
+ ...Object.keys(newMap),
110
+ ]);
111
+ const changed = [];
112
+ for (const key of allKeys) {
113
+ const isAdded = !(key in oldMap);
114
+ const isUpdated = key in oldMap &&
115
+ key in newMap &&
116
+ JSON.stringify(oldMap[key]) !== JSON.stringify(newMap[key]);
117
+ if (isAdded || isUpdated) {
118
+ changed.push(key);
119
+ }
120
+ }
121
+ return { changedPackages: changed, oldMap, newMap };
122
+ }
123
+ }
124
+ exports.ProdPublishApplication = ProdPublishApplication;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.PublishDevApplication = void 0;
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const prompts_1 = __importDefault(require("prompts"));
42
+ const semver = __importStar(require("semver"));
43
+ const base_application_1 = require("./base-application");
44
+ class PublishDevApplication extends base_application_1.BaseApplication {
45
+ constructor(logger, git, graphProvider, adapters, masterBranch = "main") {
46
+ super(logger, git, graphProvider, masterBranch);
47
+ this.adapters = adapters;
48
+ }
49
+ async execute() {
50
+ this.logger.info("Performing repository checks...");
51
+ const repoRoot = await this.ensureRepositoryHealthy();
52
+ this.logger.info("Building dependency graph...");
53
+ const graph = await this.buildGraph();
54
+ const changedFiles = await this.getChangedAbsolutePaths(repoRoot);
55
+ const changedPackages = this.mapFilesToPackages(changedFiles, graph.metadata);
56
+ if (changedPackages.size === 0) {
57
+ this.logger.warn(`No packages have changed since ${this.masterBranch}. Nothing to publish.`);
58
+ return;
59
+ }
60
+ this.logger.info(`Changed packages: ${[...changedPackages].join(", ")}`);
61
+ const packageName = await this.promptPackageName(changedPackages);
62
+ const meta = graph.metadata[packageName];
63
+ const adapter = this.adapters.find((a) => a.supports(meta));
64
+ if (!adapter) {
65
+ throw new Error(`No dev-publish adapter for platform "${meta.platform}"`);
66
+ }
67
+ const currentVersion = await adapter.getCurrentVersion(meta.rootDir);
68
+ const alphaVersion = this.generateAlphaVersion(currentVersion);
69
+ this.logger.info(`Version: ${currentVersion} → ${chalk_1.default.bold(alphaVersion)}`);
70
+ await adapter.publish({ packageName, packageDir: meta.rootDir, repoRoot }, alphaVersion);
71
+ }
72
+ async promptPackageName(changedPackages) {
73
+ const packages = [...changedPackages].sort();
74
+ const response = await (0, prompts_1.default)({
75
+ type: "autocomplete",
76
+ name: "packageName",
77
+ message: chalk_1.default.yellow("Select the changed package to publish as alpha:"),
78
+ choices: packages.map((pkg) => ({
79
+ title: pkg,
80
+ value: pkg,
81
+ })),
82
+ suggest: async (input, choices) => choices.filter((c) => c.title
83
+ .toLowerCase()
84
+ .includes(input.toLowerCase())),
85
+ }, {
86
+ onCancel: () => {
87
+ throw new Error("Publish cancelled by user");
88
+ },
89
+ });
90
+ if (!response.packageName) {
91
+ throw new Error("No package name provided");
92
+ }
93
+ return response.packageName;
94
+ }
95
+ generateAlphaVersion(currentVersion) {
96
+ const parsed = semver.parse(currentVersion);
97
+ if (!parsed) {
98
+ throw new Error(`Invalid semver version: ${currentVersion}`);
99
+ }
100
+ const base = `${parsed.major}.${parsed.minor}.${parsed.patch}`;
101
+ return `${base}-alpha.${Date.now()}`;
102
+ }
103
+ }
104
+ exports.PublishDevApplication = PublishDevApplication;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PublishDevApplication = void 0;
4
+ class PublishDevApplication {
5
+ constructor(logger) {
6
+ this.logger = logger;
7
+ }
8
+ async execute() {
9
+ this.logger.info("📦 Publishing to dev registry...");
10
+ const PublishScript = require("../scripts/dev").default;
11
+ const publish = new PublishScript();
12
+ await publish.run();
13
+ this.logger.success("✅ Published to dev registry");
14
+ }
15
+ }
16
+ exports.PublishDevApplication = PublishDevApplication;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReleaseApplication = void 0;
4
+ const base_application_1 = require("./base-application");
5
+ class ReleaseApplication extends base_application_1.BaseApplication {
6
+ constructor(logger, git, graphProvider, adapters, topoSorter, releaseMapStore, masterBranch = "main") {
7
+ super(logger, git, graphProvider, masterBranch);
8
+ this.adapters = adapters;
9
+ this.topoSorter = topoSorter;
10
+ this.releaseMapStore = releaseMapStore;
11
+ }
12
+ async execute() {
13
+ this.logger.info("Performing repository checks...");
14
+ const repoRoot = await this.ensureRepositoryHealthy();
15
+ this.logger.info("Building dependency graph...");
16
+ const graph = await this.buildGraph();
17
+ this.logger.success("Repository checks passed");
18
+ this.logger.info(`Total packages: ${Object.keys(graph.adjacency).length}`);
19
+ const changedFiles = await this.getChangedAbsolutePaths(repoRoot);
20
+ this.logger.info(`Changed files: ${changedFiles.length}`);
21
+ const affected = this.resolveDirectlyChangedPackages(changedFiles, graph.metadata);
22
+ this.logger.info(`Affected packages: ${[...affected].join(", ")}`);
23
+ const sorted = this.topoSorter.sort(graph.adjacency, [...affected]);
24
+ this.logger.info(`Execution order: ${sorted.join(" → ")}`);
25
+ await this.executeRelease([...affected], graph, sorted);
26
+ }
27
+ // ── Affected-package resolution ────────────────────────────────────
28
+ /**
29
+ * Only packages whose files changed. Dependents are not included here;
30
+ * when the user chooses a **major** bump for a package, the release adapter
31
+ * adds direct dependents (freeze / cascade) via {@link BaseReleaseAdapter}.
32
+ */
33
+ resolveDirectlyChangedPackages(changedFiles, metadata) {
34
+ return this.mapFilesToPackages(changedFiles, metadata);
35
+ }
36
+ // ── Release orchestration ──────────────────────────────────────────
37
+ async executeRelease(affected, graph, sorted) {
38
+ const existingMap = await this.releaseMapStore.readMergedWithLocal(this.masterBranch);
39
+ const allPrompts = await this.collectPrompts(affected, graph, sorted, existingMap);
40
+ await this.writePromptResults(allPrompts, graph, existingMap);
41
+ await this.releaseMapStore.write(existingMap);
42
+ }
43
+ async collectPrompts(affected, graph, sorted, existingMap) {
44
+ const grouped = this.groupByAdapter(affected, graph);
45
+ let allPrompts = {};
46
+ for (const [adapter, packages] of grouped.entries()) {
47
+ this.logger.info(`Executing adapter for ${packages.length} package(s)`);
48
+ const adapterPrompts = await adapter.execute(packages, graph, sorted, existingMap);
49
+ allPrompts = { ...allPrompts, ...adapterPrompts };
50
+ }
51
+ return allPrompts;
52
+ }
53
+ async writePromptResults(allPrompts, graph, mapJsonObject) {
54
+ for (const [pkg, prompt] of Object.entries(allPrompts)) {
55
+ const meta = graph.metadata[pkg];
56
+ if (!meta)
57
+ continue;
58
+ const adapter = this.adapters.find((a) => a.supports(meta));
59
+ if (!adapter) {
60
+ this.logger.warn(`No adapter found for ${pkg}`);
61
+ continue;
62
+ }
63
+ await adapter.writeUserPromptsToFiles(pkg, prompt, mapJsonObject, graph);
64
+ }
65
+ }
66
+ groupByAdapter(affected, graph) {
67
+ const grouped = new Map();
68
+ for (const pkg of affected) {
69
+ const meta = graph.metadata[pkg];
70
+ if (!meta)
71
+ continue;
72
+ const adapter = this.adapters.find((a) => a.supports(meta));
73
+ if (!adapter) {
74
+ this.logger.warn(`No adapter found for ${pkg}`);
75
+ continue;
76
+ }
77
+ if (!grouped.has(adapter)) {
78
+ grouped.set(adapter, []);
79
+ }
80
+ grouped.get(adapter).push(pkg);
81
+ }
82
+ return grouped;
83
+ }
84
+ }
85
+ exports.ReleaseApplication = ReleaseApplication;