Ship the three C4 examples and model:scaffold --example

- examples/: c4-standard-web-app, c4-e-shop (was online-shop),
  c4-event-based-integration; the same models the extension offers
  under Archify | New Model…
- model-scaffold --example <name> copies one and renames id, name,
  description and the overview title; never overwrites
- tests cover every example and the copy; docs updated
This commit is contained in:
root-at-skic committed 2026-10-19 12:30:07 +03:00
1 parent b6b5e57922
commit 55894fbade
27 files changed
+538 -17

No files matched your search

+32 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env node
// The skill's own checks. Runs every action against examples/online-shop and
// The skill's own checks. Runs every action against examples/c4-e-shop and
// a scaffolded temp model. Prints YAML (success first); exit 1 on any failure.
import fs from 'node:fs';
@@ -11,7 +11,7 @@ import { toYaml } from '../services/yaml.mjs';
const scripts = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
const skill = path.resolve(scripts, '..');
const example = path.join(skill, 'examples', 'online-shop');
const example = path.join(skill, 'examples', 'c4-e-shop');
const cli = path.join(scripts, 'src', 'cli', 'commands.mjs');
const checks = [];
@@ -168,6 +168,36 @@ try {
check('plain model validates (model block only)', ['--action', 'model-validate', '--dir', plain], (r) => {
assert(r.status === 0, `exit ${r.status}`);
});
// The shipped examples: the same three the extension offers under "Archify | New Model…".
const examplesDir = path.join(skill, 'examples');
const exampleNames = fs.readdirSync(examplesDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
check('examples/ holds exactly the three C4 examples', [], () => {
assert(exampleNames.join(',') === 'c4-e-shop,c4-event-based-integration,c4-standard-web-app', `unexpected examples: ${exampleNames.join(',')}`);
});
for (const name of exampleNames) {
check(`example ${name} validates with 0 problems`, ['--action', 'model-validate', '--dir', path.join(examplesDir, name)], (r) => {
assert(r.status === 0, `exit ${r.status}`);
assert(yamlValue(r.stdout, ' errors') === '0' && yamlValue(r.stdout, ' warnings') === '0', 'example has problems');
assert(yamlValue(r.stdout, ' diagrams') === '4', 'expected 4 diagrams');
});
}
const fromExample = path.join(tmp, 'from-example');
check('model-scaffold --example copies and renames an example', ['--action', 'model-scaffold', '--dir', fromExample, '--example', 'c4-event-based-integration', '--id', 'hub', '--name', 'Integration Hub', '--description', 'Our hub: events between systems'], (r) => {
assert(r.status === 0, `exit ${r.status}`);
const main = fs.readFileSync(path.join(fromExample, 'main.archify'), 'utf8');
assert(/^ id: hub$/m.test(main) && /^ name: "Integration Hub"$/m.test(main) && /Our hub: events between systems/.test(main) && /Integration Hub — overview/.test(main), `main.archify not renamed:\n${main}`);
assert(fs.existsSync(path.join(fromExample, 'registry', 'containers.archify-registry')) && fs.existsSync(path.join(fromExample, '0300-components', 'router.archify')), 'example files missing');
});
check('copied example validates', ['--action', 'model-validate', '--dir', fromExample], (r) => {
assert(r.status === 0, `exit ${r.status}`);
assert(yamlValue(r.stdout, ' errors') === '0' && yamlValue(r.stdout, ' warnings') === '0', 'copied example has problems');
});
check('model-scaffold --example refuses to overwrite and rejects unknown names', ['--action', 'model-scaffold', '--dir', fromExample, '--example', 'c4-e-shop'], (r) => {
assert(r.status === 1 && /Refusing to overwrite/.test(r.stdout), 'no refusal');
const unknown = cliRun(['--action', 'model-scaffold', '--dir', path.join(tmp, 'x'), '--example', 'nope']);
assert(unknown.status === 1 && /Unknown example/.test(unknown.stdout), 'unknown example accepted');
});
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
}