speccrew 0.6.67 → 0.6.68
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/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js
CHANGED
|
@@ -295,6 +295,37 @@ function loadTechStackConfig(platformType, framework, projectRoot) {
|
|
|
295
295
|
return { extensions: [], exclude_file_suffixes: [], exclude_file_names: [] };
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Validate entry-dirs JSON schema
|
|
300
|
+
* @param {object} data - Parsed entry-dirs JSON data
|
|
301
|
+
* @returns {string[]|null} Array of error messages or null if valid
|
|
302
|
+
*/
|
|
303
|
+
function validateEntryDirsSchema(data) {
|
|
304
|
+
const errors = [];
|
|
305
|
+
if (!data.platformId || typeof data.platformId !== 'string') {
|
|
306
|
+
errors.push('platformId must be a non-empty string');
|
|
307
|
+
} else if (!/^[a-zA-Z0-9_-]+$/.test(data.platformId)) {
|
|
308
|
+
errors.push(`platformId format invalid: "${data.platformId}" (only alphanumeric, hyphen, underscore allowed)`);
|
|
309
|
+
}
|
|
310
|
+
if (!data.sourcePath || typeof data.sourcePath !== 'string') {
|
|
311
|
+
errors.push('sourcePath must be a non-empty string');
|
|
312
|
+
}
|
|
313
|
+
if (!Array.isArray(data.modules) || data.modules.length === 0) {
|
|
314
|
+
errors.push('modules must be a non-empty array');
|
|
315
|
+
} else {
|
|
316
|
+
for (let i = 0; i < data.modules.length; i++) {
|
|
317
|
+
const mod = data.modules[i];
|
|
318
|
+
if (!mod.name || typeof mod.name !== 'string') {
|
|
319
|
+
errors.push(`modules[${i}].name must be a non-empty string`);
|
|
320
|
+
}
|
|
321
|
+
if (!Array.isArray(mod.entryDirs) || mod.entryDirs.length === 0) {
|
|
322
|
+
errors.push(`modules[${i}].entryDirs must be a non-empty array`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return errors.length > 0 ? errors : null;
|
|
327
|
+
}
|
|
328
|
+
|
|
298
329
|
/**
|
|
299
330
|
* Infer platform info from platformId
|
|
300
331
|
* @param {string} platformId - Platform ID like "backend-ai", "web-vue", "mobile-uniapp"
|
|
@@ -533,7 +564,7 @@ function generateFromEntryDirs(entryDirsData, platformConfig, projectRoot, outpu
|
|
|
533
564
|
platformName: platformConfig.platformName,
|
|
534
565
|
platformType: platformType,
|
|
535
566
|
sourcePath: sourcePath,
|
|
536
|
-
techStack: [framework],
|
|
567
|
+
techStack: entryDirsData.techStack || [framework],
|
|
537
568
|
modules: [...new Set(moduleNames)].sort(),
|
|
538
569
|
totalFiles: features.length,
|
|
539
570
|
analyzedCount: 0,
|
|
@@ -667,7 +698,15 @@ function main() {
|
|
|
667
698
|
console.error(`Found top-level keys: ${foundKeys}`);
|
|
668
699
|
process.exit(1);
|
|
669
700
|
}
|
|
670
|
-
|
|
701
|
+
|
|
702
|
+
// Validate entry-dirs JSON schema
|
|
703
|
+
const schemaErrors = validateEntryDirsSchema(entryDirsData);
|
|
704
|
+
if (schemaErrors) {
|
|
705
|
+
console.error('Error: entry-dirs JSON schema validation failed:');
|
|
706
|
+
schemaErrors.forEach(err => console.error(` - ${err}`));
|
|
707
|
+
process.exit(1);
|
|
708
|
+
}
|
|
709
|
+
|
|
671
710
|
// Find project root (use current directory or entryDirsFile directory)
|
|
672
711
|
const projectRoot = findProjectRoot(path.dirname(entryDirsFilePath));
|
|
673
712
|
|
|
@@ -718,7 +757,10 @@ function main() {
|
|
|
718
757
|
outputDir = path.resolve(params.outputDir);
|
|
719
758
|
console.log(`Using outputDir from parameter: ${outputDir}`);
|
|
720
759
|
} else {
|
|
760
|
+
console.warn('WARNING: --outputDir not specified, falling back to default path.');
|
|
761
|
+
console.warn(' Recommended: explicitly pass --outputDir to avoid incorrect output location.');
|
|
721
762
|
outputDir = path.join(projectRoot, 'speccrew-workspace', 'knowledges', 'base', 'sync-state', 'knowledge-bizs');
|
|
763
|
+
console.warn(` Using fallback outputDir: ${outputDir}`);
|
|
722
764
|
}
|
|
723
765
|
|
|
724
766
|
// Generate features from entry dirs
|
|
@@ -840,7 +882,10 @@ function main() {
|
|
|
840
882
|
syncStateDir = path.resolve(params.outputDir);
|
|
841
883
|
console.log(`Using outputDir from parameter: ${syncStateDir}`);
|
|
842
884
|
} else {
|
|
885
|
+
console.warn('WARNING: --outputDir not specified, falling back to default path.');
|
|
886
|
+
console.warn(' Recommended: explicitly pass --outputDir to avoid incorrect output location.');
|
|
843
887
|
syncStateDir = path.join(projectRoot, 'speccrew-workspace', 'knowledges', 'base', 'sync-state', 'knowledge-bizs');
|
|
888
|
+
console.warn(` Using fallback outputDir: ${syncStateDir}`);
|
|
844
889
|
}
|
|
845
890
|
const outputPath = path.join(syncStateDir, outputFileName);
|
|
846
891
|
|