docguard-cli 0.9.3 → 0.9.4
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/cli/commands/diagnose.mjs +2 -2
- package/cli/commands/generate.mjs +49 -10
- package/package.json +1 -1
|
@@ -120,10 +120,10 @@ export function runDiagnose(projectDir, config, flags) {
|
|
|
120
120
|
});
|
|
121
121
|
} catch { /* init may partially succeed */ }
|
|
122
122
|
|
|
123
|
-
// Run generate to fill in content
|
|
123
|
+
// Run generate to fill in MISSING content only (never --force, which would overwrite existing docs)
|
|
124
124
|
try {
|
|
125
125
|
const cliPath = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'docguard.mjs');
|
|
126
|
-
execSync(`node "${cliPath}" generate --dir "${projectDir}"
|
|
126
|
+
execSync(`node "${cliPath}" generate --dir "${projectDir}"`, {
|
|
127
127
|
encoding: 'utf-8',
|
|
128
128
|
stdio: 'pipe',
|
|
129
129
|
});
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* This is the "killer feature" — take any project and auto-generate CDD docs.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, mkdirSync } from 'node:fs';
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, mkdirSync, copyFileSync } from 'node:fs';
|
|
9
9
|
import { resolve, join, extname, basename, relative, dirname } from 'node:path';
|
|
10
10
|
import { c } from '../shared.mjs';
|
|
11
11
|
import { detectDocTools } from '../scanners/doc-tools.mjs';
|
|
@@ -18,6 +18,30 @@ const IGNORE_DIRS = new Set([
|
|
|
18
18
|
'.amplify-hosting', '.serverless',
|
|
19
19
|
]);
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Create a .bak backup of an existing file before --force overwrites it.
|
|
23
|
+
* Only backs up if the file exists and has content.
|
|
24
|
+
*/
|
|
25
|
+
function backupFile(filePath) {
|
|
26
|
+
if (existsSync(filePath)) {
|
|
27
|
+
try {
|
|
28
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
29
|
+
if (content.trim().length > 0) {
|
|
30
|
+
copyFileSync(filePath, filePath + '.bak');
|
|
31
|
+
}
|
|
32
|
+
} catch { /* backup failure is non-fatal */ }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Safe write — creates a .bak backup before overwriting existing files.
|
|
38
|
+
* Call this instead of raw writeFileSync when generating docs.
|
|
39
|
+
*/
|
|
40
|
+
function safeWrite(filePath, content) {
|
|
41
|
+
backupFile(filePath);
|
|
42
|
+
writeFileSync(filePath, content, 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
|
|
21
45
|
const CODE_EXTENSIONS = new Set([
|
|
22
46
|
'.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx',
|
|
23
47
|
'.py', '.java', '.go', '.rs', '.rb', '.php', '.cs',
|
|
@@ -137,6 +161,21 @@ export function runGenerate(projectDir, config, flags) {
|
|
|
137
161
|
mkdirSync(docsDir, { recursive: true });
|
|
138
162
|
}
|
|
139
163
|
|
|
164
|
+
// ── Safety: warn if --force will overwrite existing files ──
|
|
165
|
+
if (flags.force) {
|
|
166
|
+
const targetFiles = [
|
|
167
|
+
'docs-canonical/ARCHITECTURE.md', 'docs-canonical/API-REFERENCE.md',
|
|
168
|
+
'docs-canonical/DATA-MODEL.md', 'docs-canonical/ENVIRONMENT.md',
|
|
169
|
+
'docs-canonical/TEST-SPEC.md', 'docs-canonical/SECURITY.md',
|
|
170
|
+
'AGENTS.md', 'CHANGELOG.md', 'DRIFT-LOG.md',
|
|
171
|
+
];
|
|
172
|
+
const existing = targetFiles.filter(f => existsSync(resolve(projectDir, f)));
|
|
173
|
+
if (existing.length > 0) {
|
|
174
|
+
console.log(` ${c.yellow}⚠️ --force: ${existing.length} existing file(s) will be overwritten.${c.reset}`);
|
|
175
|
+
console.log(` ${c.dim} Backups saved as .bak files.${c.reset}\n`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
140
179
|
let created = 0;
|
|
141
180
|
let skipped = 0;
|
|
142
181
|
|
|
@@ -633,7 +672,7 @@ See \\\`docs-canonical/KNOWN-GOTCHAS.md\\\` for known issues.
|
|
|
633
672
|
| 0.1.0 | ${new Date().toISOString().split('T')[0]} | DocGuard Generate | Auto-generated (arc42 + C4 aligned) |
|
|
634
673
|
`;
|
|
635
674
|
|
|
636
|
-
|
|
675
|
+
safeWrite(path, appendStandardsCitation(content, 'ARCHITECTURE.md'), 'utf-8');
|
|
637
676
|
console.log(` ${c.green}✅ ARCHITECTURE.md${c.reset} (arc42 §1-§12, ${componentRows.length} components, ${Object.values(stack).filter(Boolean).length} tech)`);
|
|
638
677
|
return true;
|
|
639
678
|
}
|
|
@@ -730,7 +769,7 @@ ${resourceSections}
|
|
|
730
769
|
| 0.1.0 | ${new Date().toISOString().split('T')[0]} | DocGuard Generate | Auto-generated (${deepRoutes.length} endpoints from ${deepRoutes[0]?.source || 'code'}) |
|
|
731
770
|
`;
|
|
732
771
|
|
|
733
|
-
|
|
772
|
+
safeWrite(path, appendStandardsCitation(content, 'API-REFERENCE.md'), 'utf-8');
|
|
734
773
|
console.log(` ${c.green}✅ API-REFERENCE.md${c.reset} (${deepRoutes.length} endpoints, ${Object.keys(groups).length} resources)`);
|
|
735
774
|
return true;
|
|
736
775
|
}
|
|
@@ -885,7 +924,7 @@ ${erDiagram}
|
|
|
885
924
|
| 0.1.0 | ${new Date().toISOString().split('T')[0]} | DocGuard Generate | Auto-generated (${entities.length} entities, ${relationships.length} relationships from ${schemaSource}) |
|
|
886
925
|
`;
|
|
887
926
|
|
|
888
|
-
|
|
927
|
+
safeWrite(path, appendStandardsCitation(content, 'DATA-MODEL.md'), 'utf-8');
|
|
889
928
|
console.log(` ${c.green}✅ DATA-MODEL.md${c.reset} (${entities.length} entities, ${relationships.length} relationships from ${schemaSource})`);
|
|
890
929
|
return true;
|
|
891
930
|
}
|
|
@@ -948,7 +987,7 @@ ${envVarRows || '| <!-- No .env.example found --> | | | | |'}
|
|
|
948
987
|
| 0.1.0 | ${new Date().toISOString().split('T')[0]} | DocGuard Generate | Auto-generated (${scan.envVars.length} env vars found) |
|
|
949
988
|
`;
|
|
950
989
|
|
|
951
|
-
|
|
990
|
+
safeWrite(path, appendStandardsCitation(content, 'ENVIRONMENT.md'), 'utf-8');
|
|
952
991
|
console.log(` ${c.green}✅ ENVIRONMENT.md${c.reset} (${scan.envVars.length} env vars detected)`);
|
|
953
992
|
return true;
|
|
954
993
|
}
|
|
@@ -1033,7 +1072,7 @@ ${serviceRows || '| <!-- No services found --> | | | |'}
|
|
|
1033
1072
|
| 0.1.0 | ${new Date().toISOString().split('T')[0]} | DocGuard Generate | Auto-generated (${scan.tests.length} test files, ${serviceMap.filter(s => s.status === '✅').length}/${serviceMap.length} mapped) |
|
|
1034
1073
|
`;
|
|
1035
1074
|
|
|
1036
|
-
|
|
1075
|
+
safeWrite(path, appendStandardsCitation(content, 'TEST-SPEC.md'), 'utf-8');
|
|
1037
1076
|
console.log(` ${c.green}✅ TEST-SPEC.md${c.reset} (${scan.tests.length} tests, ${serviceMap.filter(s => s.status === '✅').length}/${serviceMap.length} services mapped)`);
|
|
1038
1077
|
return true;
|
|
1039
1078
|
}
|
|
@@ -1099,7 +1138,7 @@ ${scan.envVars.filter(v => isSecretVar(v.name)).map(v =>
|
|
|
1099
1138
|
| 0.1.0 | ${new Date().toISOString().split('T')[0]} | DocGuard Generate | Auto-generated |
|
|
1100
1139
|
`;
|
|
1101
1140
|
|
|
1102
|
-
|
|
1141
|
+
safeWrite(path, appendStandardsCitation(content, 'SECURITY.md'), 'utf-8');
|
|
1103
1142
|
console.log(` ${c.green}✅ SECURITY.md${c.reset} (auth: ${stack.auth || 'not detected'})`);
|
|
1104
1143
|
return true;
|
|
1105
1144
|
}
|
|
@@ -1209,7 +1248,7 @@ npx docguard-cli generate # Generate docs from code
|
|
|
1209
1248
|
- Test requirements in TEST-SPEC.md must be met
|
|
1210
1249
|
- Documentation changes must pass \`docguard guard\`
|
|
1211
1250
|
`;
|
|
1212
|
-
|
|
1251
|
+
safeWrite(agentsPath, content);
|
|
1213
1252
|
console.log(` ${c.green}✅ AGENTS.md${c.reset} (AGENTS.md standard compliant)`);
|
|
1214
1253
|
created++;
|
|
1215
1254
|
} else {
|
|
@@ -1231,7 +1270,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
1231
1270
|
### Added
|
|
1232
1271
|
- CDD documentation via DocGuard generate
|
|
1233
1272
|
`;
|
|
1234
|
-
|
|
1273
|
+
safeWrite(changelogPath, content);
|
|
1235
1274
|
console.log(` ${c.green}✅ CHANGELOG.md${c.reset}`);
|
|
1236
1275
|
created++;
|
|
1237
1276
|
} else {
|
|
@@ -1251,7 +1290,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
1251
1290
|
|------|------|---------------|-------------------|----------|------------|
|
|
1252
1291
|
| | | | | | |
|
|
1253
1292
|
`;
|
|
1254
|
-
|
|
1293
|
+
safeWrite(driftPath, content);
|
|
1255
1294
|
console.log(` ${c.green}✅ DRIFT-LOG.md${c.reset}`);
|
|
1256
1295
|
created++;
|
|
1257
1296
|
} else {
|