@diagrammo/dgmo 0.8.2 → 0.8.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/.claude/commands/dgmo-diagram-this.md +60 -0
- package/.claude/commands/dgmo-document-project.md +128 -0
- package/.claude/commands/dgmo.md +185 -50
- package/.cursorrules +32 -37
- package/.github/copilot-instructions.md +35 -44
- package/.windsurfrules +32 -37
- package/README.md +4 -4
- package/dist/cli.cjs +189 -194
- package/dist/editor.cjs +336 -0
- package/dist/editor.cjs.map +1 -0
- package/dist/editor.d.cts +27 -0
- package/dist/editor.d.ts +27 -0
- package/dist/editor.js +305 -0
- package/dist/editor.js.map +1 -0
- package/dist/index.cjs +3699 -1564
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +3699 -1564
- package/dist/index.js.map +1 -1
- package/docs/language-reference.md +822 -1060
- package/gallery/fixtures/arc.dgmo +18 -0
- package/gallery/fixtures/area.dgmo +19 -0
- package/gallery/fixtures/bar-stacked.dgmo +10 -0
- package/gallery/fixtures/bar.dgmo +10 -0
- package/gallery/fixtures/c4-full.dgmo +52 -0
- package/gallery/fixtures/c4.dgmo +17 -0
- package/gallery/fixtures/chord.dgmo +12 -0
- package/gallery/fixtures/class-basic.dgmo +14 -0
- package/gallery/fixtures/class-full.dgmo +43 -0
- package/gallery/fixtures/doughnut.dgmo +8 -0
- package/gallery/fixtures/flowchart-basic.dgmo +3 -0
- package/gallery/fixtures/flowchart-colors.dgmo +5 -0
- package/gallery/fixtures/flowchart-complex.dgmo +17 -0
- package/gallery/fixtures/flowchart-decision.dgmo +5 -0
- package/gallery/fixtures/flowchart-full.dgmo +13 -0
- package/gallery/fixtures/flowchart-groups.dgmo +10 -0
- package/gallery/fixtures/flowchart-loop.dgmo +7 -0
- package/gallery/fixtures/flowchart-nested.dgmo +7 -0
- package/gallery/fixtures/flowchart-shapes.dgmo +5 -0
- package/gallery/fixtures/function.dgmo +8 -0
- package/gallery/fixtures/funnel.dgmo +7 -0
- package/gallery/fixtures/gantt-full.dgmo +49 -0
- package/gallery/fixtures/gantt.dgmo +42 -0
- package/gallery/fixtures/heatmap.dgmo +8 -0
- package/gallery/fixtures/infra-full.dgmo +78 -0
- package/gallery/fixtures/infra-overload.dgmo +25 -0
- package/gallery/fixtures/infra.dgmo +47 -0
- package/gallery/fixtures/initiative-status-full.dgmo +46 -0
- package/gallery/fixtures/initiative-status-phases.dgmo +29 -0
- package/gallery/fixtures/initiative-status.dgmo +9 -0
- package/gallery/fixtures/line.dgmo +19 -0
- package/gallery/fixtures/multi-line.dgmo +11 -0
- package/gallery/fixtures/org-basic.dgmo +16 -0
- package/gallery/fixtures/org-full.dgmo +69 -0
- package/gallery/fixtures/org-teams.dgmo +25 -0
- package/gallery/fixtures/pie.dgmo +9 -0
- package/gallery/fixtures/polar-area.dgmo +8 -0
- package/gallery/fixtures/quadrant.dgmo +18 -0
- package/gallery/fixtures/radar.dgmo +8 -0
- package/gallery/fixtures/sankey.dgmo +31 -0
- package/gallery/fixtures/scatter.dgmo +21 -0
- package/gallery/fixtures/sequence-tags-protocols.dgmo +45 -0
- package/gallery/fixtures/sequence-tags.dgmo +41 -0
- package/gallery/fixtures/sequence.dgmo +35 -0
- package/gallery/fixtures/sitemap-basic.dgmo +12 -0
- package/gallery/fixtures/sitemap-full.dgmo +156 -0
- package/gallery/fixtures/slope.dgmo +8 -0
- package/gallery/fixtures/spr-eras.dgmo +62 -0
- package/gallery/fixtures/state.dgmo +30 -0
- package/gallery/fixtures/timeline-intraday.dgmo +14 -0
- package/gallery/fixtures/timeline.dgmo +32 -0
- package/gallery/fixtures/venn.dgmo +10 -0
- package/gallery/fixtures/wordcloud.dgmo +24 -0
- package/package.json +51 -2
- package/src/c4/layout.ts +372 -90
- package/src/c4/parser.ts +113 -62
- package/src/chart.ts +149 -64
- package/src/class/parser.ts +84 -28
- package/src/class/renderer.ts +2 -2
- package/src/cli.ts +179 -77
- package/src/completion.ts +381 -182
- package/src/d3.ts +1026 -428
- package/src/dgmo-mermaid.ts +16 -13
- package/src/dgmo-router.ts +70 -24
- package/src/echarts.ts +682 -169
- package/src/editor/dgmo.grammar +69 -0
- package/src/editor/dgmo.grammar.d.ts +2 -0
- package/src/editor/dgmo.grammar.js +18 -0
- package/src/editor/dgmo.grammar.terms.d.ts +5 -0
- package/src/editor/dgmo.grammar.terms.js +35 -0
- package/src/editor/highlight.ts +36 -0
- package/src/editor/index.ts +28 -0
- package/src/editor/keywords.ts +220 -0
- package/src/editor/tokens.ts +30 -0
- package/src/er/parser.ts +55 -29
- package/src/er/renderer.ts +112 -53
- package/src/gantt/calculator.ts +91 -29
- package/src/gantt/parser.ts +291 -97
- package/src/gantt/renderer.ts +1120 -350
- package/src/graph/flowchart-parser.ts +48 -75
- package/src/graph/state-parser.ts +54 -27
- package/src/infra/parser.ts +161 -177
- package/src/infra/renderer.ts +723 -271
- package/src/infra/types.ts +0 -1
- package/src/initiative-status/parser.ts +144 -56
- package/src/kanban/parser.ts +27 -19
- package/src/org/layout.ts +111 -44
- package/src/org/parser.ts +71 -27
- package/src/org/resolver.ts +3 -3
- package/src/palettes/index.ts +3 -2
- package/src/render.ts +1 -2
- package/src/sequence/parser.ts +209 -100
- package/src/sitemap/parser.ts +73 -44
- package/src/utils/arrows.ts +2 -22
- package/src/utils/duration.ts +39 -21
- package/src/utils/legend-constants.ts +0 -2
- package/src/utils/parsing.ts +82 -72
- package/src/utils/tag-groups.ts +4 -41
- package/src/infra/serialize.ts +0 -67
package/src/cli.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
3
|
import { execSync } from 'node:child_process';
|
|
3
4
|
import { homedir } from 'node:os';
|
|
@@ -47,7 +48,8 @@ const CHART_TYPE_DESCRIPTIONS: Record<string, string> = {
|
|
|
47
48
|
org: 'Org chart — hierarchical tree structures',
|
|
48
49
|
kanban: 'Kanban board — task/workflow columns',
|
|
49
50
|
c4: 'C4 diagram — system architecture (context, container, component, deployment)',
|
|
50
|
-
'initiative-status':
|
|
51
|
+
'initiative-status':
|
|
52
|
+
'Initiative status — project roadmap with dependency tracking',
|
|
51
53
|
infra: 'Infra chart — infrastructure traffic flow with rps computation',
|
|
52
54
|
};
|
|
53
55
|
|
|
@@ -199,7 +201,7 @@ Key options:
|
|
|
199
201
|
### Common to all diagrams
|
|
200
202
|
|
|
201
203
|
\`\`\`
|
|
202
|
-
|
|
204
|
+
sequence // explicit type (optional — auto-detected)
|
|
203
205
|
title: My Diagram
|
|
204
206
|
palette: catppuccin // override palette
|
|
205
207
|
|
|
@@ -372,8 +374,7 @@ When the \`dgmo\` MCP server is configured, use these tools directly:
|
|
|
372
374
|
|
|
373
375
|
### Sequence diagram
|
|
374
376
|
\`\`\`
|
|
375
|
-
|
|
376
|
-
title: Auth Flow
|
|
377
|
+
sequence Auth Flow
|
|
377
378
|
|
|
378
379
|
User -Login-> API
|
|
379
380
|
API -Find user-> DB
|
|
@@ -386,8 +387,7 @@ DB -user-> API
|
|
|
386
387
|
|
|
387
388
|
### Flowchart
|
|
388
389
|
\`\`\`
|
|
389
|
-
|
|
390
|
-
title: Process
|
|
390
|
+
flowchart Process
|
|
391
391
|
|
|
392
392
|
(Start) -> <Valid?>
|
|
393
393
|
-yes-> [Process] -> (Done)
|
|
@@ -396,8 +396,7 @@ title: Process
|
|
|
396
396
|
|
|
397
397
|
### Bar chart
|
|
398
398
|
\`\`\`
|
|
399
|
-
|
|
400
|
-
title: Revenue
|
|
399
|
+
bar Revenue
|
|
401
400
|
series: USD
|
|
402
401
|
|
|
403
402
|
North: 850
|
|
@@ -407,8 +406,7 @@ East: 1100
|
|
|
407
406
|
|
|
408
407
|
### ER diagram
|
|
409
408
|
\`\`\`
|
|
410
|
-
|
|
411
|
-
title: Schema
|
|
409
|
+
er Schema
|
|
412
410
|
|
|
413
411
|
users
|
|
414
412
|
id: int [pk]
|
|
@@ -423,7 +421,7 @@ users 1--* posts : writes
|
|
|
423
421
|
|
|
424
422
|
### Org chart
|
|
425
423
|
\`\`\`
|
|
426
|
-
|
|
424
|
+
org
|
|
427
425
|
|
|
428
426
|
CEO
|
|
429
427
|
VP Engineering
|
|
@@ -434,8 +432,7 @@ CEO
|
|
|
434
432
|
|
|
435
433
|
### Infra chart
|
|
436
434
|
\`\`\`
|
|
437
|
-
|
|
438
|
-
direction: LR
|
|
435
|
+
infra
|
|
439
436
|
|
|
440
437
|
edge
|
|
441
438
|
rps: 10000
|
|
@@ -461,7 +458,7 @@ bar, line, multi-line, area, pie, doughnut, radar, polar-area, bar-stacked, scat
|
|
|
461
458
|
|
|
462
459
|
## Common patterns
|
|
463
460
|
|
|
464
|
-
-
|
|
461
|
+
- First line: chart type keyword (e.g. \`sequence\`, \`flowchart\`, \`bar\`) — auto-detected if unambiguous
|
|
465
462
|
- \`title: text\` — diagram title
|
|
466
463
|
- \`// comment\` — only \`//\` comments (not \`#\`)
|
|
467
464
|
- \`(colorname)\` — inline colors: \`Label(red): 100\`
|
|
@@ -480,7 +477,7 @@ dgmo file.dgmo --json # structured JSON output
|
|
|
480
477
|
- Don't use \`#\` for comments — use \`//\`
|
|
481
478
|
- Don't use \`end\` to close sequence blocks — indentation closes them
|
|
482
479
|
- Don't use hex colors in section headers — use named colors
|
|
483
|
-
-
|
|
480
|
+
- Start the file with the chart type keyword when content is ambiguous
|
|
484
481
|
- Sequence arrows: \`->\` (sync), \`~>\` (async) — always left-to-right
|
|
485
482
|
|
|
486
483
|
Full reference: call \`get_language_reference\` MCP tool or visit diagrammo.app/docs
|
|
@@ -559,7 +556,11 @@ function parseArgs(argv: string[]): {
|
|
|
559
556
|
installClaudeSkill: false,
|
|
560
557
|
installClaudeCodeIntegration: false,
|
|
561
558
|
installCodexIntegration: false,
|
|
562
|
-
c4Level: 'context' as
|
|
559
|
+
c4Level: 'context' as
|
|
560
|
+
| 'context'
|
|
561
|
+
| 'containers'
|
|
562
|
+
| 'components'
|
|
563
|
+
| 'deployment',
|
|
563
564
|
c4System: undefined as string | undefined,
|
|
564
565
|
c4Container: undefined as string | undefined,
|
|
565
566
|
tagGroup: undefined as string | undefined,
|
|
@@ -602,7 +603,12 @@ function parseArgs(argv: string[]): {
|
|
|
602
603
|
i++;
|
|
603
604
|
} else if (arg === '--c4-level') {
|
|
604
605
|
const val = args[++i];
|
|
605
|
-
if (
|
|
606
|
+
if (
|
|
607
|
+
val !== 'context' &&
|
|
608
|
+
val !== 'containers' &&
|
|
609
|
+
val !== 'components' &&
|
|
610
|
+
val !== 'deployment'
|
|
611
|
+
) {
|
|
606
612
|
console.error(
|
|
607
613
|
`Error: Invalid C4 level "${val}". Valid levels: context, containers, components, deployment`
|
|
608
614
|
);
|
|
@@ -686,8 +692,8 @@ function noInput(): never {
|
|
|
686
692
|
writeFileSync(
|
|
687
693
|
samplePath,
|
|
688
694
|
[
|
|
689
|
-
'
|
|
690
|
-
'activations
|
|
695
|
+
'sequence',
|
|
696
|
+
'activations off',
|
|
691
697
|
'',
|
|
692
698
|
'Client -POST /login-> API',
|
|
693
699
|
' API -validate credentials-> Auth',
|
|
@@ -750,8 +756,14 @@ async function main(): Promise<void> {
|
|
|
750
756
|
|
|
751
757
|
function ask(prompt: string): Promise<string> {
|
|
752
758
|
return new Promise((resolve) => {
|
|
753
|
-
const rl = createInterface({
|
|
754
|
-
|
|
759
|
+
const rl = createInterface({
|
|
760
|
+
input: process.stdin,
|
|
761
|
+
output: process.stdout,
|
|
762
|
+
});
|
|
763
|
+
rl.question(prompt, (answer) => {
|
|
764
|
+
rl.close();
|
|
765
|
+
resolve(answer);
|
|
766
|
+
});
|
|
755
767
|
});
|
|
756
768
|
}
|
|
757
769
|
|
|
@@ -761,7 +773,9 @@ async function main(): Promise<void> {
|
|
|
761
773
|
const skillExists = existsSync(skillPath);
|
|
762
774
|
let installSkill = true;
|
|
763
775
|
if (skillExists) {
|
|
764
|
-
const ans = await ask(
|
|
776
|
+
const ans = await ask(
|
|
777
|
+
'~/.claude/commands/dgmo.md already exists. Overwrite? [y/N] '
|
|
778
|
+
);
|
|
765
779
|
installSkill = ans.toLowerCase() === 'y' || ans.toLowerCase() === 'yes';
|
|
766
780
|
}
|
|
767
781
|
if (installSkill) {
|
|
@@ -774,16 +788,26 @@ async function main(): Promise<void> {
|
|
|
774
788
|
|
|
775
789
|
// --- Step 2: Check / install dgmo-mcp binary ---
|
|
776
790
|
let dgmoMcpInstalled = false;
|
|
777
|
-
try {
|
|
791
|
+
try {
|
|
792
|
+
execSync('which dgmo-mcp', { stdio: 'pipe' });
|
|
793
|
+
dgmoMcpInstalled = true;
|
|
794
|
+
} catch {
|
|
795
|
+
/* not found */
|
|
796
|
+
}
|
|
778
797
|
if (!dgmoMcpInstalled) {
|
|
779
|
-
const ans = await ask(
|
|
780
|
-
|
|
798
|
+
const ans = await ask(
|
|
799
|
+
'\ndgmo-mcp not found. Install @diagrammo/dgmo-mcp globally now? [Y/n] '
|
|
800
|
+
);
|
|
801
|
+
const yes =
|
|
802
|
+
ans === '' || ans.toLowerCase() === 'y' || ans.toLowerCase() === 'yes';
|
|
781
803
|
if (yes) {
|
|
782
804
|
console.log('Installing @diagrammo/dgmo-mcp...');
|
|
783
805
|
execSync('npm install -g @diagrammo/dgmo-mcp', { stdio: 'inherit' });
|
|
784
806
|
console.log('✓ @diagrammo/dgmo-mcp installed');
|
|
785
807
|
} else {
|
|
786
|
-
console.log(
|
|
808
|
+
console.log(
|
|
809
|
+
' Skipped. Install later with: npm install -g @diagrammo/dgmo-mcp'
|
|
810
|
+
);
|
|
787
811
|
}
|
|
788
812
|
} else {
|
|
789
813
|
console.log('✓ dgmo-mcp already installed');
|
|
@@ -792,7 +816,9 @@ async function main(): Promise<void> {
|
|
|
792
816
|
// --- Step 3: Configure MCP server ---
|
|
793
817
|
console.log('\nWhere should the MCP server be configured?');
|
|
794
818
|
console.log(' 1) This project only — write .mcp.json here [default]');
|
|
795
|
-
console.log(
|
|
819
|
+
console.log(
|
|
820
|
+
' 2) Globally — add to ~/.claude/settings.json (works in all projects)'
|
|
821
|
+
);
|
|
796
822
|
const scopeAns = await ask('\nChoice [1]: ');
|
|
797
823
|
const useGlobal = scopeAns.trim() === '2';
|
|
798
824
|
const mcpEntry = { command: 'dgmo-mcp' };
|
|
@@ -801,24 +827,40 @@ async function main(): Promise<void> {
|
|
|
801
827
|
const settingsPath = join(claudeDir, 'settings.json');
|
|
802
828
|
let settings: Record<string, unknown> = {};
|
|
803
829
|
if (existsSync(settingsPath)) {
|
|
804
|
-
try {
|
|
830
|
+
try {
|
|
831
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
832
|
+
} catch {
|
|
833
|
+
/* use empty */
|
|
834
|
+
}
|
|
805
835
|
}
|
|
806
|
-
const mcpServers =
|
|
836
|
+
const mcpServers =
|
|
837
|
+
(settings.mcpServers as Record<string, unknown> | undefined) ?? {};
|
|
807
838
|
mcpServers['dgmo'] = mcpEntry;
|
|
808
839
|
settings.mcpServers = mcpServers;
|
|
809
|
-
writeFileSync(
|
|
840
|
+
writeFileSync(
|
|
841
|
+
settingsPath,
|
|
842
|
+
JSON.stringify(settings, null, 2) + '\n',
|
|
843
|
+
'utf-8'
|
|
844
|
+
);
|
|
810
845
|
console.log('✓ MCP server added to ~/.claude/settings.json');
|
|
811
846
|
} else {
|
|
812
847
|
const mcpPath = join(process.cwd(), '.mcp.json');
|
|
813
848
|
let mcp: Record<string, unknown> = {};
|
|
814
849
|
if (existsSync(mcpPath)) {
|
|
815
|
-
try {
|
|
850
|
+
try {
|
|
851
|
+
mcp = JSON.parse(readFileSync(mcpPath, 'utf-8'));
|
|
852
|
+
} catch {
|
|
853
|
+
/* use empty */
|
|
854
|
+
}
|
|
816
855
|
}
|
|
817
|
-
const mcpServers =
|
|
856
|
+
const mcpServers =
|
|
857
|
+
(mcp.mcpServers as Record<string, unknown> | undefined) ?? {};
|
|
818
858
|
mcpServers['dgmo'] = mcpEntry;
|
|
819
859
|
mcp.mcpServers = mcpServers;
|
|
820
860
|
writeFileSync(mcpPath, JSON.stringify(mcp, null, 2) + '\n', 'utf-8');
|
|
821
|
-
console.log(
|
|
861
|
+
console.log(
|
|
862
|
+
`✓ MCP server configured: ${join(process.cwd(), '.mcp.json')}`
|
|
863
|
+
);
|
|
822
864
|
}
|
|
823
865
|
|
|
824
866
|
console.log('\nRestart Claude Code to activate the MCP server.');
|
|
@@ -840,12 +882,17 @@ async function main(): Promise<void> {
|
|
|
840
882
|
? `~/.claude/commands/dgmo.md already exists. Overwrite? [y/N] `
|
|
841
883
|
: `Install dgmo Claude Code skill to ~/.claude/commands/dgmo.md? [Y/n] `;
|
|
842
884
|
await new Promise<void>((done) => {
|
|
843
|
-
const rl = createInterface({
|
|
885
|
+
const rl = createInterface({
|
|
886
|
+
input: process.stdin,
|
|
887
|
+
output: process.stdout,
|
|
888
|
+
});
|
|
844
889
|
rl.question(prompt, (answer) => {
|
|
845
890
|
rl.close();
|
|
846
891
|
const yes = alreadyExists
|
|
847
892
|
? answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes'
|
|
848
|
-
: answer === '' ||
|
|
893
|
+
: answer === '' ||
|
|
894
|
+
answer.toLowerCase() === 'y' ||
|
|
895
|
+
answer.toLowerCase() === 'yes';
|
|
849
896
|
if (!yes) {
|
|
850
897
|
console.error('Aborted.');
|
|
851
898
|
process.exit(0);
|
|
@@ -864,23 +911,41 @@ async function main(): Promise<void> {
|
|
|
864
911
|
|
|
865
912
|
if (opts.installCodexIntegration) {
|
|
866
913
|
// Validate Codex CLI is installed
|
|
867
|
-
try {
|
|
868
|
-
|
|
914
|
+
try {
|
|
915
|
+
execSync('which codex', { stdio: 'pipe' });
|
|
916
|
+
} catch {
|
|
917
|
+
console.error(
|
|
918
|
+
'codex not found. Install Codex CLI first: https://openai.com/codex'
|
|
919
|
+
);
|
|
869
920
|
process.exit(1);
|
|
870
921
|
}
|
|
871
922
|
|
|
872
923
|
const ask = (prompt: string): Promise<string> =>
|
|
873
924
|
new Promise((resolve) => {
|
|
874
|
-
const rl = createInterface({
|
|
875
|
-
|
|
925
|
+
const rl = createInterface({
|
|
926
|
+
input: process.stdin,
|
|
927
|
+
output: process.stdout,
|
|
928
|
+
});
|
|
929
|
+
rl.question(prompt, (answer) => {
|
|
930
|
+
rl.close();
|
|
931
|
+
resolve(answer);
|
|
932
|
+
});
|
|
876
933
|
});
|
|
877
934
|
|
|
878
935
|
// Check / install dgmo-mcp binary
|
|
879
936
|
let dgmoMcpInstalled = false;
|
|
880
|
-
try {
|
|
937
|
+
try {
|
|
938
|
+
execSync('which dgmo-mcp', { stdio: 'pipe' });
|
|
939
|
+
dgmoMcpInstalled = true;
|
|
940
|
+
} catch {
|
|
941
|
+
/* not found */
|
|
942
|
+
}
|
|
881
943
|
if (!dgmoMcpInstalled) {
|
|
882
|
-
const ans = await ask(
|
|
883
|
-
|
|
944
|
+
const ans = await ask(
|
|
945
|
+
'\ndgmo-mcp not found. Install @diagrammo/dgmo-mcp globally now? [Y/n] '
|
|
946
|
+
);
|
|
947
|
+
const yes =
|
|
948
|
+
ans === '' || ans.toLowerCase() === 'y' || ans.toLowerCase() === 'yes';
|
|
884
949
|
if (yes) {
|
|
885
950
|
console.log('Installing @diagrammo/dgmo-mcp...');
|
|
886
951
|
try {
|
|
@@ -891,7 +956,9 @@ async function main(): Promise<void> {
|
|
|
891
956
|
console.error('Try manually: npm install -g @diagrammo/dgmo-mcp');
|
|
892
957
|
}
|
|
893
958
|
} else {
|
|
894
|
-
console.log(
|
|
959
|
+
console.log(
|
|
960
|
+
' Skipped. Install later with: npm install -g @diagrammo/dgmo-mcp'
|
|
961
|
+
);
|
|
895
962
|
}
|
|
896
963
|
} else {
|
|
897
964
|
console.log('✓ dgmo-mcp already installed');
|
|
@@ -899,11 +966,21 @@ async function main(): Promise<void> {
|
|
|
899
966
|
|
|
900
967
|
// Configure MCP server
|
|
901
968
|
console.log('\nWhere should the MCP server be configured?');
|
|
902
|
-
console.log(
|
|
903
|
-
|
|
969
|
+
console.log(
|
|
970
|
+
' 1) This project only — write .codex/config.toml here [default]'
|
|
971
|
+
);
|
|
972
|
+
console.log(
|
|
973
|
+
' 2) Globally — add to ~/.codex/config.toml (works in all projects)'
|
|
974
|
+
);
|
|
904
975
|
const scopeAns = await ask('\nChoice [1]: ');
|
|
905
|
-
if (
|
|
906
|
-
|
|
976
|
+
if (
|
|
977
|
+
scopeAns.trim() !== '' &&
|
|
978
|
+
scopeAns.trim() !== '1' &&
|
|
979
|
+
scopeAns.trim() !== '2'
|
|
980
|
+
) {
|
|
981
|
+
console.log(
|
|
982
|
+
` Unrecognized input "${scopeAns.trim()}", defaulting to option 1.`
|
|
983
|
+
);
|
|
907
984
|
}
|
|
908
985
|
const useGlobal = scopeAns.trim() === '2';
|
|
909
986
|
const tomlEntry = '[mcp_servers.dgmo]\ncommand = ["dgmo-mcp"]\n';
|
|
@@ -911,7 +988,9 @@ async function main(): Promise<void> {
|
|
|
911
988
|
if (useGlobal) {
|
|
912
989
|
const configPath = join(homedir(), '.codex', 'config.toml');
|
|
913
990
|
mkdirSync(join(homedir(), '.codex'), { recursive: true });
|
|
914
|
-
const existing = existsSync(configPath)
|
|
991
|
+
const existing = existsSync(configPath)
|
|
992
|
+
? readFileSync(configPath, 'utf-8')
|
|
993
|
+
: '';
|
|
915
994
|
if (existing.includes('[mcp_servers.dgmo]')) {
|
|
916
995
|
console.log('✓ MCP server already configured in ~/.codex/config.toml');
|
|
917
996
|
} else {
|
|
@@ -923,7 +1002,9 @@ async function main(): Promise<void> {
|
|
|
923
1002
|
const codexDir = join(process.cwd(), '.codex');
|
|
924
1003
|
const configPath = join(codexDir, 'config.toml');
|
|
925
1004
|
mkdirSync(codexDir, { recursive: true });
|
|
926
|
-
const existing = existsSync(configPath)
|
|
1005
|
+
const existing = existsSync(configPath)
|
|
1006
|
+
? readFileSync(configPath, 'utf-8')
|
|
1007
|
+
: '';
|
|
927
1008
|
if (existing.includes('[mcp_servers.dgmo]')) {
|
|
928
1009
|
console.log(`✓ MCP server already configured in .codex/config.toml`);
|
|
929
1010
|
} else {
|
|
@@ -988,10 +1069,8 @@ async function main(): Promise<void> {
|
|
|
988
1069
|
// Resolve org chart imports (tags and import directives)
|
|
989
1070
|
if (opts.input && parseDgmoChartType(content) === 'org') {
|
|
990
1071
|
const inputPath = resolve(opts.input);
|
|
991
|
-
const resolved = await resolveOrgImports(
|
|
992
|
-
|
|
993
|
-
inputPath,
|
|
994
|
-
(p) => readFileSync(p, 'utf-8'),
|
|
1072
|
+
const resolved = await resolveOrgImports(content, inputPath, (p) =>
|
|
1073
|
+
readFileSync(p, 'utf-8')
|
|
995
1074
|
);
|
|
996
1075
|
for (const diag of resolved.diagnostics) {
|
|
997
1076
|
console.error(formatDgmoError(diag));
|
|
@@ -1013,12 +1092,18 @@ async function main(): Promise<void> {
|
|
|
1013
1092
|
// Helper for JSON error output
|
|
1014
1093
|
function exitWithJsonError(error: string, line?: number): never {
|
|
1015
1094
|
if (opts.json) {
|
|
1016
|
-
process.stdout.write(
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1095
|
+
process.stdout.write(
|
|
1096
|
+
JSON.stringify(
|
|
1097
|
+
{
|
|
1098
|
+
success: false,
|
|
1099
|
+
error,
|
|
1100
|
+
...(line != null ? { line } : {}),
|
|
1101
|
+
...(chartType ? { chartType } : {}),
|
|
1102
|
+
},
|
|
1103
|
+
null,
|
|
1104
|
+
2
|
|
1105
|
+
) + '\n'
|
|
1106
|
+
);
|
|
1022
1107
|
} else {
|
|
1023
1108
|
console.error(error);
|
|
1024
1109
|
}
|
|
@@ -1051,18 +1136,26 @@ async function main(): Promise<void> {
|
|
|
1051
1136
|
}
|
|
1052
1137
|
|
|
1053
1138
|
if (opts.json) {
|
|
1054
|
-
process.stdout.write(
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1139
|
+
process.stdout.write(
|
|
1140
|
+
JSON.stringify(
|
|
1141
|
+
{
|
|
1142
|
+
success: true,
|
|
1143
|
+
url: result.url,
|
|
1144
|
+
...(chartType ? { chartType } : {}),
|
|
1145
|
+
},
|
|
1146
|
+
null,
|
|
1147
|
+
2
|
|
1148
|
+
) + '\n'
|
|
1149
|
+
);
|
|
1059
1150
|
} else {
|
|
1060
1151
|
process.stdout.write(result.url + '\n');
|
|
1061
1152
|
}
|
|
1062
1153
|
return;
|
|
1063
1154
|
}
|
|
1064
1155
|
|
|
1065
|
-
const paletteColors = getPalette(opts.palette)[
|
|
1156
|
+
const paletteColors = getPalette(opts.palette)[
|
|
1157
|
+
opts.theme === 'dark' ? 'dark' : 'light'
|
|
1158
|
+
];
|
|
1066
1159
|
|
|
1067
1160
|
// Word clouds require Canvas APIs (HTMLCanvasElement.getContext('2d'))
|
|
1068
1161
|
// which are unavailable in Node.js — check before attempting render.
|
|
@@ -1089,10 +1182,7 @@ async function main(): Promise<void> {
|
|
|
1089
1182
|
if (errors.length > 0) {
|
|
1090
1183
|
if (opts.json) {
|
|
1091
1184
|
const firstError = errors[0];
|
|
1092
|
-
exitWithJsonError(
|
|
1093
|
-
formatDgmoError(firstError),
|
|
1094
|
-
firstError.line,
|
|
1095
|
-
);
|
|
1185
|
+
exitWithJsonError(formatDgmoError(firstError), firstError.line);
|
|
1096
1186
|
}
|
|
1097
1187
|
for (const e of errors) {
|
|
1098
1188
|
console.error(`\u2716 ${formatDgmoError(e)}`);
|
|
@@ -1101,14 +1191,20 @@ async function main(): Promise<void> {
|
|
|
1101
1191
|
|
|
1102
1192
|
// Validate C4 options
|
|
1103
1193
|
if (opts.c4Level === 'containers' && !opts.c4System) {
|
|
1104
|
-
exitWithJsonError(
|
|
1194
|
+
exitWithJsonError(
|
|
1195
|
+
'Error: --c4-system is required when --c4-level is containers'
|
|
1196
|
+
);
|
|
1105
1197
|
}
|
|
1106
1198
|
if (opts.c4Level === 'components') {
|
|
1107
1199
|
if (!opts.c4System) {
|
|
1108
|
-
exitWithJsonError(
|
|
1200
|
+
exitWithJsonError(
|
|
1201
|
+
'Error: --c4-system is required when --c4-level is components'
|
|
1202
|
+
);
|
|
1109
1203
|
}
|
|
1110
1204
|
if (!opts.c4Container) {
|
|
1111
|
-
exitWithJsonError(
|
|
1205
|
+
exitWithJsonError(
|
|
1206
|
+
'Error: --c4-container is required when --c4-level is components'
|
|
1207
|
+
);
|
|
1112
1208
|
}
|
|
1113
1209
|
}
|
|
1114
1210
|
|
|
@@ -1148,11 +1244,17 @@ async function main(): Promise<void> {
|
|
|
1148
1244
|
outputPath = resolve(`${inputBasename}.png`);
|
|
1149
1245
|
writeFileSync(outputPath, svgToPng(svg, pngBg));
|
|
1150
1246
|
}
|
|
1151
|
-
process.stdout.write(
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1247
|
+
process.stdout.write(
|
|
1248
|
+
JSON.stringify(
|
|
1249
|
+
{
|
|
1250
|
+
success: true,
|
|
1251
|
+
...(outputPath ? { output: outputPath } : {}),
|
|
1252
|
+
...(chartType ? { chartType } : {}),
|
|
1253
|
+
},
|
|
1254
|
+
null,
|
|
1255
|
+
2
|
|
1256
|
+
) + '\n'
|
|
1257
|
+
);
|
|
1156
1258
|
} else if (opts.output) {
|
|
1157
1259
|
// Explicit output path
|
|
1158
1260
|
const outputPath = resolve(opts.output);
|