bmad-enhanced 1.1.2 → 1.3.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.
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs-extra');
4
+ const path = require('path');
5
+ const yaml = require('js-yaml');
6
+
7
+ /**
8
+ * Migration Registry for BMAD-Enhanced
9
+ * Tracks available migrations and determines execution order
10
+ */
11
+
12
+ // Registry of all available migrations
13
+ const MIGRATIONS = [
14
+ {
15
+ name: '1.0.x-to-1.3.0',
16
+ fromVersion: '1.0.x',
17
+ toVersion: '1.3.0',
18
+ breaking: true,
19
+ description: 'Migrate empathy-map workflow to lean-persona',
20
+ module: null // Loaded on demand
21
+ },
22
+ {
23
+ name: '1.1.x-to-1.3.0',
24
+ fromVersion: '1.1.x',
25
+ toVersion: '1.3.0',
26
+ breaking: false,
27
+ description: 'Archive deprecated workflows, update agents',
28
+ module: null // Loaded on demand
29
+ },
30
+ {
31
+ name: '1.2.x-to-1.3.0',
32
+ fromVersion: '1.2.x',
33
+ toVersion: '1.3.0',
34
+ breaking: false,
35
+ description: 'Update to v1.3.0 with migration system',
36
+ module: null // Loaded on demand
37
+ }
38
+ ];
39
+
40
+ /**
41
+ * Get migrations applicable for version upgrade
42
+ * @param {string} fromVersion - Current version
43
+ * @param {string} toVersion - Target version
44
+ * @returns {Array} List of applicable migrations
45
+ */
46
+ function getMigrationsFor(fromVersion, toVersion) {
47
+ const applicable = [];
48
+
49
+ for (const migration of MIGRATIONS) {
50
+ if (matchesVersionRange(fromVersion, migration.fromVersion) &&
51
+ matchesVersionRange(toVersion, migration.toVersion)) {
52
+
53
+ // Lazy load the migration module
54
+ if (!migration.module) {
55
+ try {
56
+ migration.module = require(`./${migration.name}`);
57
+ } catch (error) {
58
+ console.error(`Failed to load migration ${migration.name}:`, error.message);
59
+ continue;
60
+ }
61
+ }
62
+
63
+ applicable.push(migration);
64
+ }
65
+ }
66
+
67
+ // Sort by version order (oldest to newest)
68
+ applicable.sort((a, b) => {
69
+ const aVersion = a.fromVersion.replace('.x', '.0');
70
+ const bVersion = b.fromVersion.replace('.x', '.0');
71
+ return compareVersions(aVersion, bVersion);
72
+ });
73
+
74
+ return applicable;
75
+ }
76
+
77
+ /**
78
+ * Check if migration has already been applied
79
+ * @param {string} migrationName - Name of migration
80
+ * @param {string} configPath - Path to config.yaml
81
+ * @returns {boolean} True if already applied
82
+ */
83
+ function hasMigrationBeenApplied(migrationName, configPath) {
84
+ if (!fs.existsSync(configPath)) {
85
+ return false;
86
+ }
87
+
88
+ try {
89
+ const configContent = fs.readFileSync(configPath, 'utf8');
90
+ const config = yaml.load(configContent);
91
+
92
+ if (!config.migration_history || !Array.isArray(config.migration_history)) {
93
+ return false;
94
+ }
95
+
96
+ return config.migration_history.some(entry =>
97
+ entry.migrations_applied && entry.migrations_applied.includes(migrationName)
98
+ );
99
+ } catch (error) {
100
+ console.warn('Could not check migration history:', error.message);
101
+ return false;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Get breaking changes for version upgrade
107
+ * @param {string} fromVersion - Current version
108
+ * @param {string} toVersion - Target version
109
+ * @returns {Array<string>} List of breaking change descriptions
110
+ */
111
+ function getBreakingChanges(fromVersion, toVersion) {
112
+ const migrations = getMigrationsFor(fromVersion, toVersion);
113
+ const breakingChanges = [];
114
+
115
+ for (const migration of migrations) {
116
+ if (migration.breaking) {
117
+ breakingChanges.push(migration.description);
118
+ }
119
+ }
120
+
121
+ return breakingChanges;
122
+ }
123
+
124
+ /**
125
+ * Match version against version range pattern
126
+ * @param {string} version - Version to check (e.g., "1.0.5")
127
+ * @param {string} pattern - Pattern to match (e.g., "1.0.x")
128
+ * @returns {boolean} True if matches
129
+ */
130
+ function matchesVersionRange(version, pattern) {
131
+ if (pattern === version) {
132
+ return true;
133
+ }
134
+
135
+ // Handle wildcard patterns (e.g., "1.0.x")
136
+ if (pattern.endsWith('.x')) {
137
+ const patternParts = pattern.split('.');
138
+ const versionParts = version.split('.');
139
+
140
+ // Match major.minor, ignore patch
141
+ return patternParts[0] === versionParts[0] &&
142
+ patternParts[1] === versionParts[1];
143
+ }
144
+
145
+ return false;
146
+ }
147
+
148
+ /**
149
+ * Compare two semantic versions
150
+ * @param {string} v1 - First version
151
+ * @param {string} v2 - Second version
152
+ * @returns {number} -1 if v1 < v2, 0 if equal, 1 if v1 > v2
153
+ */
154
+ function compareVersions(v1, v2) {
155
+ const parts1 = v1.split('.').map(Number);
156
+ const parts2 = v2.split('.').map(Number);
157
+
158
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
159
+ const part1 = parts1[i] || 0;
160
+ const part2 = parts2[i] || 0;
161
+
162
+ if (part1 < part2) return -1;
163
+ if (part1 > part2) return 1;
164
+ }
165
+
166
+ return 0;
167
+ }
168
+
169
+ /**
170
+ * Get all registered migrations
171
+ * @returns {Array} All migrations
172
+ */
173
+ function getAllMigrations() {
174
+ return [...MIGRATIONS];
175
+ }
176
+
177
+ module.exports = {
178
+ MIGRATIONS,
179
+ getMigrationsFor,
180
+ hasMigrationBeenApplied,
181
+ getBreakingChanges,
182
+ matchesVersionRange,
183
+ compareVersions,
184
+ getAllMigrations
185
+ };