specweave 1.0.461 → 1.0.462
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.
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts +0 -1
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +1 -7
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js +1 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.d.ts +0 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +2 -9
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/lib/vendor/utils/clean-env.d.ts +47 -0
- package/plugins/specweave/lib/vendor/utils/clean-env.js +63 -0
- package/plugins/specweave/lib/vendor/utils/clean-env.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/execFileNoThrow.d.ts +99 -0
- package/plugins/specweave/lib/vendor/utils/execFileNoThrow.js +149 -0
- package/plugins/specweave/lib/vendor/utils/execFileNoThrow.js.map +1 -0
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +0 -5
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.ts +1 -7
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.js +1 -1
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.ts +1 -1
- package/plugins/specweave-github/lib/github-client-v2.js +1 -1
- package/plugins/specweave-github/lib/github-client-v2.ts +1 -1
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +1 -7
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.ts +2 -9
- package/plugins/specweave/lib/vendor/utils/project-detection.d.ts +0 -250
- package/plugins/specweave/lib/vendor/utils/project-detection.js +0 -560
- package/plugins/specweave/lib/vendor/utils/project-detection.js.map +0 -1
|
@@ -1,560 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project ID Auto-Detection Utilities
|
|
3
|
-
*
|
|
4
|
-
* Detects project ID from (priority order):
|
|
5
|
-
* 1. sync.defaultProfile (for multi-profile monorepos)
|
|
6
|
-
* 2. Git remote (GitHub repo name)
|
|
7
|
-
* 3. Sync configuration (JIRA project key, ADO project name)
|
|
8
|
-
* 4. User prompt (fallback)
|
|
9
|
-
*
|
|
10
|
-
* NOTE: multiProject.activeProject has been REMOVED!
|
|
11
|
-
* Per-US project targeting replaces global activeProject.
|
|
12
|
-
* See: 0125-cross-project-user-story-targeting
|
|
13
|
-
*
|
|
14
|
-
* Also provides repo name parsing for domain context understanding.
|
|
15
|
-
*/
|
|
16
|
-
import * as fs from '../utils/fs-native.js';
|
|
17
|
-
import path from 'path';
|
|
18
|
-
import { input } from '@inquirer/prompts';
|
|
19
|
-
import { ConfigManager } from '../core/config-manager.js';
|
|
20
|
-
/** Known component suffixes that indicate sub-project type */
|
|
21
|
-
const KNOWN_COMPONENTS = ['be', 'fe', 'backend', 'frontend', 'api', 'web', 'mobile', 'shared', 'common', 'core', 'lib', 'ui', 'app', 'service', 'services'];
|
|
22
|
-
/** Domain detection patterns */
|
|
23
|
-
const DOMAIN_PATTERNS = [
|
|
24
|
-
{ pattern: /qr[-_]?menu|menu[-_]?qr|restaurant|food|dining/i, domain: 'hospitality/restaurant' },
|
|
25
|
-
{ pattern: /e[-_]?commerce|shop|store|cart|checkout/i, domain: 'retail/ecommerce' },
|
|
26
|
-
{ pattern: /health|medical|patient|clinic|hospital/i, domain: 'healthcare' },
|
|
27
|
-
{ pattern: /finance|banking|payment|wallet|money/i, domain: 'fintech' },
|
|
28
|
-
{ pattern: /edu|learn|school|course|student/i, domain: 'education' },
|
|
29
|
-
{ pattern: /social|chat|message|community/i, domain: 'social' },
|
|
30
|
-
{ pattern: /iot|sensor|device|smart[-_]?home/i, domain: 'iot' },
|
|
31
|
-
{ pattern: /ai|ml|model|predict/i, domain: 'ai/ml' },
|
|
32
|
-
{ pattern: /game|play|score/i, domain: 'gaming' },
|
|
33
|
-
{ pattern: /travel|booking|hotel|flight/i, domain: 'travel' },
|
|
34
|
-
];
|
|
35
|
-
/**
|
|
36
|
-
* Parse repo name to extract product, component, and domain context
|
|
37
|
-
*
|
|
38
|
-
* Understands naming conventions like:
|
|
39
|
-
* - `sw-qr-menu-be` → prefix: sw, product: qr-menu, component: be
|
|
40
|
-
* - `my-app-frontend` → prefix: null, product: my-app, component: frontend
|
|
41
|
-
* - `ecommerce-api` → prefix: null, product: ecommerce, component: api
|
|
42
|
-
*
|
|
43
|
-
* @param repoName - Repository name (e.g., "sw-qr-menu-be")
|
|
44
|
-
* @returns Parsed repo name structure
|
|
45
|
-
*/
|
|
46
|
-
export function parseRepoName(repoName) {
|
|
47
|
-
const normalized = repoName.toLowerCase().trim();
|
|
48
|
-
const parts = normalized.split(/[-_]+/);
|
|
49
|
-
let prefix = null;
|
|
50
|
-
let component = null;
|
|
51
|
-
let productParts = parts;
|
|
52
|
-
// Check if last part is a known component
|
|
53
|
-
if (parts.length > 1) {
|
|
54
|
-
const lastPart = parts[parts.length - 1];
|
|
55
|
-
if (KNOWN_COMPONENTS.includes(lastPart)) {
|
|
56
|
-
component = lastPart;
|
|
57
|
-
productParts = parts.slice(0, -1);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
// Check if first part is a short prefix (2-3 chars, likely abbreviation)
|
|
61
|
-
if (productParts.length > 1 && productParts[0].length <= 3) {
|
|
62
|
-
prefix = productParts[0];
|
|
63
|
-
productParts = productParts.slice(1);
|
|
64
|
-
}
|
|
65
|
-
const product = productParts.join('-');
|
|
66
|
-
// Detect domain from product name
|
|
67
|
-
let domain = null;
|
|
68
|
-
for (const { pattern, domain: detectedDomain } of DOMAIN_PATTERNS) {
|
|
69
|
-
if (pattern.test(product) || pattern.test(normalized)) {
|
|
70
|
-
domain = detectedDomain;
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return {
|
|
75
|
-
prefix,
|
|
76
|
-
product,
|
|
77
|
-
component,
|
|
78
|
-
full: normalized,
|
|
79
|
-
domain,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Detect default project ID from configuration
|
|
84
|
-
*
|
|
85
|
-
* NOTE: multiProject.activeProject has been REMOVED!
|
|
86
|
-
* This function now only uses sync.defaultProfile for legacy umbrella repos.
|
|
87
|
-
*
|
|
88
|
-
* Priority:
|
|
89
|
-
* 1. sync.defaultProfile - for umbrella repos where profile maps to folder
|
|
90
|
-
*
|
|
91
|
-
* @param projectRoot - Project root directory
|
|
92
|
-
* @returns Default project ID or null if not configured
|
|
93
|
-
*/
|
|
94
|
-
export function detectDefaultProfileId(projectRoot) {
|
|
95
|
-
try {
|
|
96
|
-
const configManager = new ConfigManager(projectRoot);
|
|
97
|
-
const config = configManager.load();
|
|
98
|
-
// sync.defaultProfile for umbrella repos
|
|
99
|
-
// where profile IS a folder (like "be", "fe", "shared")
|
|
100
|
-
if (config.sync?.defaultProfile && config.sync?.profiles) {
|
|
101
|
-
const defaultProfileId = config.sync.defaultProfile;
|
|
102
|
-
// CRITICAL FIX (2025-11-30, 2026-01-04): Profile IDs are NOT folder names!
|
|
103
|
-
// ProfileIds like "main", "ado-myproject", "jira-webapp" are sync connection identifiers
|
|
104
|
-
// NOT project folders! The actual folder name comes from profile.config.repo/project
|
|
105
|
-
// Bug: "main" was being used as folder name instead of actual repo name
|
|
106
|
-
const profile = config.sync.profiles[defaultProfileId];
|
|
107
|
-
if (profile?.config) {
|
|
108
|
-
const profileConfig = profile.config;
|
|
109
|
-
// GitHub: use repo name from config (MOST COMMON CASE)
|
|
110
|
-
if (profile.provider === 'github' && profileConfig.repo) {
|
|
111
|
-
return String(profileConfig.repo).toLowerCase();
|
|
112
|
-
}
|
|
113
|
-
// ADO: use project name from config
|
|
114
|
-
if (profile.provider === 'ado' && profileConfig.project) {
|
|
115
|
-
return String(profileConfig.project).toLowerCase().replace(/\s+/g, '-');
|
|
116
|
-
}
|
|
117
|
-
// JIRA: use project key from config
|
|
118
|
-
if (profile.provider === 'jira' && profileConfig.projectKey) {
|
|
119
|
-
return String(profileConfig.projectKey).toLowerCase();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// Legacy umbrella repos: profile maps to folder (e.g., "be", "fe", "shared")
|
|
123
|
-
// ONLY use profileId as folder name if it's NOT a generic identifier like "main"
|
|
124
|
-
// and it doesn't look like a provider prefix (ado-, jira-, github-)
|
|
125
|
-
const isGenericProfileId = defaultProfileId === 'main' || defaultProfileId === 'default';
|
|
126
|
-
const isProviderPrefixed = /^(ado|jira|github|gitlab)-/.test(defaultProfileId);
|
|
127
|
-
if (!isGenericProfileId && !isProviderPrefixed && config.sync.profiles[defaultProfileId]) {
|
|
128
|
-
return defaultProfileId.toLowerCase();
|
|
129
|
-
}
|
|
130
|
-
// Profile ID is generic ("main") or provider-prefixed - let git detection handle it
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Auto-detect project ID from git remote URL
|
|
141
|
-
*
|
|
142
|
-
* Extracts repository name from git remote URL
|
|
143
|
-
*
|
|
144
|
-
* @param projectRoot - Project root directory
|
|
145
|
-
* @returns Project ID (repo name) or null if not detected
|
|
146
|
-
*
|
|
147
|
-
* @example
|
|
148
|
-
* // Git remote: https://github.com/anton-abyzov/specweave.git
|
|
149
|
-
* detectProjectIdFromGit('/path/to/project')
|
|
150
|
-
* // Returns: "specweave"
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* // Git remote: git@github.com:my-org/web-app.git
|
|
154
|
-
* detectProjectIdFromGit('/path/to/project')
|
|
155
|
-
* // Returns: "web-app"
|
|
156
|
-
*/
|
|
157
|
-
export function detectProjectIdFromGit(projectRoot) {
|
|
158
|
-
try {
|
|
159
|
-
const gitConfigPath = path.join(projectRoot, '.git', 'config');
|
|
160
|
-
// Check if .git/config exists
|
|
161
|
-
if (!fs.existsSync(gitConfigPath)) {
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
// Read git config
|
|
165
|
-
const gitConfig = fs.readFileSync(gitConfigPath, 'utf8');
|
|
166
|
-
// Extract remote URL (match both HTTPS and SSH formats)
|
|
167
|
-
// HTTPS: https://github.com/owner/repo.git
|
|
168
|
-
// SSH: git@github.com:owner/repo.git
|
|
169
|
-
const httpsMatch = gitConfig.match(/url = https?:\/\/[^\/]+\/[^\/]+\/([^\/\s]+?)(?:\.git)?$/m);
|
|
170
|
-
const sshMatch = gitConfig.match(/url = git@[^:]+:[^\/]+\/([^\/\s]+?)(?:\.git)?$/m);
|
|
171
|
-
const match = httpsMatch || sshMatch;
|
|
172
|
-
if (match && match[1]) {
|
|
173
|
-
const repoName = match[1].trim();
|
|
174
|
-
// Validate repo name (lowercase, alphanumeric, hyphens, underscores)
|
|
175
|
-
if (/^[a-z0-9_-]+$/i.test(repoName)) {
|
|
176
|
-
return repoName.toLowerCase();
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
// Silently fail (not in git repo or permission error)
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Auto-detect project ID from sync configuration
|
|
188
|
-
*
|
|
189
|
-
* Checks existing sync profiles for JIRA project key or ADO project name
|
|
190
|
-
*
|
|
191
|
-
* @param projectRoot - Project root directory
|
|
192
|
-
* @returns Project ID from sync config or null if not detected
|
|
193
|
-
*
|
|
194
|
-
* @example
|
|
195
|
-
* // Config has JIRA: { projectKey: "WEBAPP" }
|
|
196
|
-
* detectProjectIdFromSync('/path/to/project')
|
|
197
|
-
* // Returns: "webapp"
|
|
198
|
-
*/
|
|
199
|
-
export function detectProjectIdFromSync(projectRoot) {
|
|
200
|
-
try {
|
|
201
|
-
const configManager = new ConfigManager(projectRoot);
|
|
202
|
-
const config = configManager.load();
|
|
203
|
-
// Check sync profiles for project identifiers
|
|
204
|
-
if (config.sync?.profiles) {
|
|
205
|
-
const profiles = Object.values(config.sync.profiles);
|
|
206
|
-
for (const profile of profiles) {
|
|
207
|
-
// GitHub profile (extract repo name)
|
|
208
|
-
if (profile.provider === 'github') {
|
|
209
|
-
const githubConfig = profile.config;
|
|
210
|
-
if (githubConfig?.repo) {
|
|
211
|
-
return githubConfig.repo.toLowerCase();
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
// JIRA profile (use project key)
|
|
215
|
-
if (profile.provider === 'jira') {
|
|
216
|
-
const jiraConfig = profile.config;
|
|
217
|
-
if (jiraConfig?.projectKey) {
|
|
218
|
-
return jiraConfig.projectKey.toLowerCase();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
// Azure DevOps profile (use project name)
|
|
222
|
-
if (profile.provider === 'ado') {
|
|
223
|
-
const adoConfig = profile.config;
|
|
224
|
-
if (adoConfig?.project) {
|
|
225
|
-
return adoConfig.project.toLowerCase().replace(/\s+/g, '-');
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
// Legacy: Check old sync config format (pre-profiles)
|
|
231
|
-
if (config.sync?.jira?.projectKey) {
|
|
232
|
-
return config.sync.jira.projectKey.toLowerCase();
|
|
233
|
-
}
|
|
234
|
-
if (config.sync?.ado?.project) {
|
|
235
|
-
return config.sync.ado.project.toLowerCase().replace(/\s+/g, '-');
|
|
236
|
-
}
|
|
237
|
-
if (config.sync?.github?.repo) {
|
|
238
|
-
return config.sync.github.repo.toLowerCase();
|
|
239
|
-
}
|
|
240
|
-
return null;
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
// Config doesn't exist or is invalid
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Prompt user for project ID
|
|
249
|
-
*
|
|
250
|
-
* Interactive prompt with validation and helpful examples
|
|
251
|
-
*
|
|
252
|
-
* @param suggestedId - Optional suggested project ID (from detection)
|
|
253
|
-
* @returns Project ID entered by user
|
|
254
|
-
*
|
|
255
|
-
* @example
|
|
256
|
-
* await promptForProjectId()
|
|
257
|
-
* // User sees:
|
|
258
|
-
* // Project ID (matches GitHub repo, JIRA project, or ADO project): █
|
|
259
|
-
* // User enters: "web-app"
|
|
260
|
-
* // Returns: "web-app"
|
|
261
|
-
*/
|
|
262
|
-
export async function promptForProjectId(suggestedId) {
|
|
263
|
-
const projectId = await input({
|
|
264
|
-
message: 'Project ID (matches GitHub repo, JIRA project, or ADO project):',
|
|
265
|
-
default: suggestedId || 'default',
|
|
266
|
-
validate: (value) => {
|
|
267
|
-
if (!value) {
|
|
268
|
-
return 'Project ID is required';
|
|
269
|
-
}
|
|
270
|
-
if (!/^[a-z0-9_-]+$/.test(value)) {
|
|
271
|
-
return 'Project ID must be lowercase, alphanumeric, with hyphens or underscores';
|
|
272
|
-
}
|
|
273
|
-
if (value.length < 2) {
|
|
274
|
-
return 'Project ID must be at least 2 characters';
|
|
275
|
-
}
|
|
276
|
-
if (value.length > 64) {
|
|
277
|
-
return 'Project ID must be at most 64 characters';
|
|
278
|
-
}
|
|
279
|
-
return true;
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
return projectId;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Auto-detect project ID synchronously (no prompts)
|
|
286
|
-
*
|
|
287
|
-
* Priority:
|
|
288
|
-
* 1. Active sync profile ID (for multi-profile monorepos like sw-qr-menu)
|
|
289
|
-
* 2. Git remote (GitHub repo name) - for single-repo projects
|
|
290
|
-
* 3. Sync configuration (JIRA/ADO project) - legacy fallback
|
|
291
|
-
* 4. "default" (fallback)
|
|
292
|
-
*
|
|
293
|
-
* @param projectRoot - Project root directory
|
|
294
|
-
* @param options - Detection options
|
|
295
|
-
* @returns Detected project ID or "default"
|
|
296
|
-
*
|
|
297
|
-
* @example
|
|
298
|
-
* // Multi-project setup with activeProject: "be"
|
|
299
|
-
* autoDetectProjectIdSync('/path/to/sw-qr-menu')
|
|
300
|
-
* // Returns: "be" (profile ID, NOT "sw-qr-menu-be")
|
|
301
|
-
*
|
|
302
|
-
* @example
|
|
303
|
-
* // Single repo: https://github.com/anton-abyzov/specweave.git
|
|
304
|
-
* autoDetectProjectIdSync('/path/to/project')
|
|
305
|
-
* // Returns: "specweave"
|
|
306
|
-
*
|
|
307
|
-
* @example
|
|
308
|
-
* // No git, no sync
|
|
309
|
-
* autoDetectProjectIdSync('/path/to/project')
|
|
310
|
-
* // Returns: "default"
|
|
311
|
-
*/
|
|
312
|
-
export function autoDetectProjectIdSync(projectRoot, options = {}) {
|
|
313
|
-
const { silent = false } = options;
|
|
314
|
-
// 1. Try default profile ID (highest priority for multi-profile monorepos)
|
|
315
|
-
const defaultProfileId = detectDefaultProfileId(projectRoot);
|
|
316
|
-
if (defaultProfileId) {
|
|
317
|
-
if (!silent) {
|
|
318
|
-
console.log(`✅ Detected default profile: ${defaultProfileId}`);
|
|
319
|
-
}
|
|
320
|
-
return defaultProfileId;
|
|
321
|
-
}
|
|
322
|
-
// 2. Try git remote (for single-repo projects)
|
|
323
|
-
const gitProjectId = detectProjectIdFromGit(projectRoot);
|
|
324
|
-
if (gitProjectId) {
|
|
325
|
-
if (!silent) {
|
|
326
|
-
console.log(`✅ Detected git repository: ${gitProjectId}`);
|
|
327
|
-
}
|
|
328
|
-
return gitProjectId;
|
|
329
|
-
}
|
|
330
|
-
// 3. Try sync config (legacy fallback)
|
|
331
|
-
const syncProjectId = detectProjectIdFromSync(projectRoot);
|
|
332
|
-
if (syncProjectId) {
|
|
333
|
-
if (!silent) {
|
|
334
|
-
console.log(`✅ Detected sync configuration: ${syncProjectId}`);
|
|
335
|
-
}
|
|
336
|
-
return syncProjectId;
|
|
337
|
-
}
|
|
338
|
-
// 4. Fallback to "default"
|
|
339
|
-
return 'default';
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Auto-detect project ID with fallback chain (async version with prompts)
|
|
343
|
-
*
|
|
344
|
-
* Priority:
|
|
345
|
-
* 1. Default sync profile ID (for multi-profile monorepos)
|
|
346
|
-
* 2. Git remote (GitHub repo name)
|
|
347
|
-
* 3. Sync configuration (JIRA/ADO project)
|
|
348
|
-
* 4. User prompt (with detected suggestion)
|
|
349
|
-
* 5. "default" (if user accepts default in prompt)
|
|
350
|
-
*
|
|
351
|
-
* @param projectRoot - Project root directory
|
|
352
|
-
* @param options - Detection options
|
|
353
|
-
* @returns Detected or prompted project ID
|
|
354
|
-
*
|
|
355
|
-
* @example
|
|
356
|
-
* // Multi-project setup with defaultProfile: "be"
|
|
357
|
-
* await autoDetectProjectId('/path/to/sw-qr-menu')
|
|
358
|
-
* // Output: "✅ Detected default profile: be"
|
|
359
|
-
* // Returns: "be"
|
|
360
|
-
*
|
|
361
|
-
* @example
|
|
362
|
-
* // In git repo: https://github.com/anton-abyzov/specweave.git
|
|
363
|
-
* await autoDetectProjectId('/path/to/project')
|
|
364
|
-
* // Output: "✅ Detected git repository: specweave"
|
|
365
|
-
* // Returns: "specweave"
|
|
366
|
-
*
|
|
367
|
-
* @example
|
|
368
|
-
* // No git, no sync, user prompted
|
|
369
|
-
* await autoDetectProjectId('/path/to/project')
|
|
370
|
-
* // Output: "📝 No git repository or sync configuration detected."
|
|
371
|
-
* // Prompts user for project ID
|
|
372
|
-
* // Returns: user input (e.g., "my-project")
|
|
373
|
-
*/
|
|
374
|
-
export async function autoDetectProjectId(projectRoot, options = {}) {
|
|
375
|
-
const { silent = false, promptIfNotDetected = true } = options;
|
|
376
|
-
// 1. Try default profile ID (highest priority for multi-profile monorepos)
|
|
377
|
-
const defaultProfileId = detectDefaultProfileId(projectRoot);
|
|
378
|
-
if (defaultProfileId) {
|
|
379
|
-
if (!silent) {
|
|
380
|
-
console.log(`✅ Detected default profile: ${defaultProfileId}`);
|
|
381
|
-
}
|
|
382
|
-
return defaultProfileId;
|
|
383
|
-
}
|
|
384
|
-
// 2. Try git remote
|
|
385
|
-
const gitProjectId = detectProjectIdFromGit(projectRoot);
|
|
386
|
-
if (gitProjectId) {
|
|
387
|
-
if (!silent) {
|
|
388
|
-
console.log(`✅ Detected git repository: ${gitProjectId}`);
|
|
389
|
-
}
|
|
390
|
-
return gitProjectId;
|
|
391
|
-
}
|
|
392
|
-
// 3. Try sync config
|
|
393
|
-
const syncProjectId = detectProjectIdFromSync(projectRoot);
|
|
394
|
-
if (syncProjectId) {
|
|
395
|
-
if (!silent) {
|
|
396
|
-
console.log(`✅ Detected sync configuration: ${syncProjectId}`);
|
|
397
|
-
}
|
|
398
|
-
return syncProjectId;
|
|
399
|
-
}
|
|
400
|
-
// 4. Prompt user (if enabled)
|
|
401
|
-
if (promptIfNotDetected) {
|
|
402
|
-
if (!silent) {
|
|
403
|
-
console.log('\n📝 No git repository or sync configuration detected.');
|
|
404
|
-
console.log(' Please enter your project identifier.\n');
|
|
405
|
-
console.log(' Examples:');
|
|
406
|
-
console.log(' • GitHub repo "web-app" → enter: web-app');
|
|
407
|
-
console.log(' • JIRA project "WEBAPP" → enter: webapp');
|
|
408
|
-
console.log(' • ADO project "Platform" → enter: platform');
|
|
409
|
-
console.log(' • Generic project → enter: default\n');
|
|
410
|
-
}
|
|
411
|
-
return await promptForProjectId();
|
|
412
|
-
}
|
|
413
|
-
// 5. Fallback to "default" (no prompt)
|
|
414
|
-
return 'default';
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* Format project ID to display name
|
|
418
|
-
*
|
|
419
|
-
* Converts kebab-case/snake_case to Title Case
|
|
420
|
-
*
|
|
421
|
-
* @param projectId - Project ID (e.g., "web-app", "mobile_app")
|
|
422
|
-
* @returns Formatted name (e.g., "Web App", "Mobile App")
|
|
423
|
-
*
|
|
424
|
-
* @example
|
|
425
|
-
* formatProjectName('web-app')
|
|
426
|
-
* // Returns: "Web App"
|
|
427
|
-
*
|
|
428
|
-
* @example
|
|
429
|
-
* formatProjectName('mobile_app')
|
|
430
|
-
* // Returns: "Mobile App"
|
|
431
|
-
*
|
|
432
|
-
* @example
|
|
433
|
-
* formatProjectName('specweave')
|
|
434
|
-
* // Returns: "SpecWeave"
|
|
435
|
-
*/
|
|
436
|
-
export function formatProjectName(projectId) {
|
|
437
|
-
// Special cases (known project names)
|
|
438
|
-
const specialCases = {
|
|
439
|
-
'specweave': 'SpecWeave',
|
|
440
|
-
'webapp': 'WebApp',
|
|
441
|
-
'default': 'Default Project'
|
|
442
|
-
};
|
|
443
|
-
if (specialCases[projectId.toLowerCase()]) {
|
|
444
|
-
return specialCases[projectId.toLowerCase()];
|
|
445
|
-
}
|
|
446
|
-
// Convert kebab-case or snake_case to Title Case
|
|
447
|
-
return projectId
|
|
448
|
-
.replace(/[-_]/g, ' ')
|
|
449
|
-
.split(' ')
|
|
450
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
451
|
-
.join(' ');
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Validate project ID format
|
|
455
|
-
*
|
|
456
|
-
* @param projectId - Project ID to validate
|
|
457
|
-
* @returns True if valid, error message if invalid
|
|
458
|
-
*/
|
|
459
|
-
export function validateProjectId(projectId) {
|
|
460
|
-
if (!projectId) {
|
|
461
|
-
return 'Project ID is required';
|
|
462
|
-
}
|
|
463
|
-
if (!/^[a-z0-9_-]+$/.test(projectId)) {
|
|
464
|
-
return 'Project ID must be lowercase, alphanumeric, with hyphens or underscores';
|
|
465
|
-
}
|
|
466
|
-
if (projectId.length < 2) {
|
|
467
|
-
return 'Project ID must be at least 2 characters';
|
|
468
|
-
}
|
|
469
|
-
if (projectId.length > 64) {
|
|
470
|
-
return 'Project ID must be at most 64 characters';
|
|
471
|
-
}
|
|
472
|
-
return true;
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Get full project context for intelligent routing and domain awareness
|
|
476
|
-
*
|
|
477
|
-
* Use this to understand:
|
|
478
|
-
* - Which project folder to use for specs (projectId)
|
|
479
|
-
* - What domain/product this project is about (repoInfo.domain)
|
|
480
|
-
* - What component type this is (repoInfo.component: be/fe/shared)
|
|
481
|
-
* - What other profiles are available (for cross-project user stories)
|
|
482
|
-
*
|
|
483
|
-
* @param projectRoot - Project root directory
|
|
484
|
-
* @returns Full project context
|
|
485
|
-
*
|
|
486
|
-
* @example
|
|
487
|
-
* // sw-qr-menu monorepo with defaultProfile: "be"
|
|
488
|
-
* getProjectContext('/path/to/sw-qr-menu')
|
|
489
|
-
* // Returns:
|
|
490
|
-
* // {
|
|
491
|
-
* // projectId: 'be',
|
|
492
|
-
* // detectedFrom: 'defaultProfile',
|
|
493
|
-
* // repoInfo: { prefix: 'sw', product: 'qr-menu', component: 'be', domain: 'hospitality/restaurant' },
|
|
494
|
-
* // availableProfiles: ['be', 'fe', 'shared'],
|
|
495
|
-
* // defaultProfile: { id: 'be', displayName: 'sw-qr-menu-be service', provider: 'github', repo: 'sw-qr-menu-be' }
|
|
496
|
-
* // }
|
|
497
|
-
*/
|
|
498
|
-
export function getProjectContext(projectRoot) {
|
|
499
|
-
let projectId = 'default';
|
|
500
|
-
let detectedFrom = 'fallback';
|
|
501
|
-
let repoInfo = null;
|
|
502
|
-
let availableProfiles = [];
|
|
503
|
-
let defaultProfile = null;
|
|
504
|
-
try {
|
|
505
|
-
const configManager = new ConfigManager(projectRoot);
|
|
506
|
-
const config = configManager.load();
|
|
507
|
-
// Collect available profiles
|
|
508
|
-
if (config.sync?.profiles) {
|
|
509
|
-
availableProfiles = Object.keys(config.sync.profiles);
|
|
510
|
-
}
|
|
511
|
-
// 1. Try default profile ID (highest priority)
|
|
512
|
-
if (config.sync?.defaultProfile && config.sync?.profiles) {
|
|
513
|
-
const profileId = config.sync.defaultProfile;
|
|
514
|
-
const profile = config.sync.profiles[profileId];
|
|
515
|
-
if (profile) {
|
|
516
|
-
projectId = profileId.toLowerCase();
|
|
517
|
-
detectedFrom = 'defaultProfile';
|
|
518
|
-
defaultProfile = {
|
|
519
|
-
id: profileId,
|
|
520
|
-
displayName: profile.displayName || profileId,
|
|
521
|
-
provider: profile.provider,
|
|
522
|
-
repo: profile.config?.repo,
|
|
523
|
-
};
|
|
524
|
-
// Parse repo name for domain context
|
|
525
|
-
if (defaultProfile.repo) {
|
|
526
|
-
repoInfo = parseRepoName(defaultProfile.repo);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
catch {
|
|
532
|
-
// Config doesn't exist, continue to git detection
|
|
533
|
-
}
|
|
534
|
-
// 2. Try git remote (if no default profile)
|
|
535
|
-
if (detectedFrom === 'fallback') {
|
|
536
|
-
const gitProjectId = detectProjectIdFromGit(projectRoot);
|
|
537
|
-
if (gitProjectId) {
|
|
538
|
-
projectId = gitProjectId;
|
|
539
|
-
detectedFrom = 'gitRemote';
|
|
540
|
-
repoInfo = parseRepoName(gitProjectId);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
// 3. Try sync config (legacy fallback)
|
|
544
|
-
if (detectedFrom === 'fallback') {
|
|
545
|
-
const syncProjectId = detectProjectIdFromSync(projectRoot);
|
|
546
|
-
if (syncProjectId) {
|
|
547
|
-
projectId = syncProjectId;
|
|
548
|
-
detectedFrom = 'syncConfig';
|
|
549
|
-
repoInfo = parseRepoName(syncProjectId);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
return {
|
|
553
|
-
projectId,
|
|
554
|
-
detectedFrom,
|
|
555
|
-
repoInfo,
|
|
556
|
-
availableProfiles,
|
|
557
|
-
defaultProfile,
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
//# sourceMappingURL=project-detection.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"project-detection.js","sourceRoot":"","sources":["../../../src/utils/project-detection.ts"],"names":[],"mappings":"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"}
|