@diagrammo/dgmo 0.4.0 → 0.4.1
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/skills/dgmo-sequence/SKILL.md +7 -9
- package/.cursorrules +4 -4
- package/.github/copilot-instructions.md +4 -4
- package/.windsurfrules +4 -4
- package/dist/cli.cjs +113 -113
- package/dist/index.cjs +20 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +20 -64
- package/dist/index.js.map +1 -1
- package/docs/language-reference.md +8 -10
- package/package.json +1 -1
- package/src/sequence/parser.ts +8 -37
- package/src/sequence/renderer.ts +0 -22
- package/src/utils/arrows.ts +23 -28
|
@@ -369,8 +369,8 @@ Minimal example:
|
|
|
369
369
|
```
|
|
370
370
|
User -login-> API
|
|
371
371
|
API -findUser-> DB
|
|
372
|
-
|
|
373
|
-
|
|
372
|
+
DB -user-> API
|
|
373
|
+
API -token-> User
|
|
374
374
|
```
|
|
375
375
|
|
|
376
376
|
Full example:
|
|
@@ -387,23 +387,23 @@ NotifyQueue is a queue aka Notifications
|
|
|
387
387
|
|
|
388
388
|
User -Login request-> API
|
|
389
389
|
API -Find user by email-> DB
|
|
390
|
-
|
|
390
|
+
DB -user record-> API
|
|
391
391
|
note on DB:
|
|
392
392
|
Indexed lookup on email column
|
|
393
393
|
|
|
394
394
|
if credentials valid
|
|
395
395
|
API -Create session-> DB
|
|
396
|
-
|
|
396
|
+
DB -session token-> API
|
|
397
397
|
API ~session.created~> NotifyQueue
|
|
398
|
-
|
|
398
|
+
API -200 OK + token-> User
|
|
399
399
|
else
|
|
400
|
-
|
|
400
|
+
API -401 Unauthorized-> User
|
|
401
401
|
|
|
402
402
|
== Logout ==
|
|
403
403
|
|
|
404
404
|
User -Logout-> API
|
|
405
405
|
API -Delete session-> DB
|
|
406
|
-
|
|
406
|
+
API -200 OK-> User
|
|
407
407
|
```
|
|
408
408
|
|
|
409
409
|
**Participants**: Auto-inferred from message names. Declare explicitly for type/positioning:
|
|
@@ -412,10 +412,8 @@ User <-200 OK- API
|
|
|
412
412
|
- `Name at position 2` — manual left-to-right ordering (0-based; negative from right)
|
|
413
413
|
|
|
414
414
|
**Messages**:
|
|
415
|
-
- Sync call: `A -label-> B` or `A -> B` (unlabeled)
|
|
415
|
+
- Sync call: `A -label-> B` or `A -> B` (unlabeled) — always left-to-right
|
|
416
416
|
- Async call: `A ~label~> B` or `A ~> B` (unlabeled)
|
|
417
|
-
- Sync return: `A <-label- B` or `A <- B` (unlabeled) — dashed arrow from B to A
|
|
418
|
-
- Async return: `A <~label~ B` or `A <~ B` (unlabeled)
|
|
419
417
|
|
|
420
418
|
**Blocks** (indentation-scoped):
|
|
421
419
|
- `if condition` ... `else` ... (no explicit `end` needed — indentation closes blocks)
|
package/package.json
CHANGED
package/src/sequence/parser.ts
CHANGED
|
@@ -60,8 +60,6 @@ export interface SequenceMessage {
|
|
|
60
60
|
label: string;
|
|
61
61
|
lineNumber: number;
|
|
62
62
|
async?: boolean;
|
|
63
|
-
/** Standalone return — the message itself IS a return (dashed arrow, no call). */
|
|
64
|
-
standaloneReturn?: boolean;
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
/**
|
|
@@ -462,7 +460,7 @@ export function parseSequenceDgmo(content: string): ParsedSequenceDgmo {
|
|
|
462
460
|
continue;
|
|
463
461
|
}
|
|
464
462
|
|
|
465
|
-
// ---- Labeled arrows: -label->, ~label
|
|
463
|
+
// ---- Labeled arrows: -label->, ~label~> ----
|
|
466
464
|
// Must be checked BEFORE plain arrow patterns to avoid partial matches
|
|
467
465
|
const labeledArrow = parseArrow(trimmed);
|
|
468
466
|
if (labeledArrow && 'error' in labeledArrow) {
|
|
@@ -471,7 +469,7 @@ export function parseSequenceDgmo(content: string): ParsedSequenceDgmo {
|
|
|
471
469
|
}
|
|
472
470
|
if (labeledArrow) {
|
|
473
471
|
contentStarted = true;
|
|
474
|
-
const { from, to, label, async: isAsync
|
|
472
|
+
const { from, to, label, async: isAsync } = labeledArrow;
|
|
475
473
|
lastMsgFrom = from;
|
|
476
474
|
|
|
477
475
|
const msg: SequenceMessage = {
|
|
@@ -480,7 +478,6 @@ export function parseSequenceDgmo(content: string): ParsedSequenceDgmo {
|
|
|
480
478
|
label,
|
|
481
479
|
lineNumber,
|
|
482
480
|
...(isAsync ? { async: true } : {}),
|
|
483
|
-
...(isReturn ? { standaloneReturn: true } : {}),
|
|
484
481
|
};
|
|
485
482
|
result.messages.push(msg);
|
|
486
483
|
currentContainer().push(msg);
|
|
@@ -538,43 +535,17 @@ export function parseSequenceDgmo(content: string): ParsedSequenceDgmo {
|
|
|
538
535
|
continue;
|
|
539
536
|
}
|
|
540
537
|
|
|
541
|
-
// ----
|
|
538
|
+
// ---- Deprecated bare return arrows: A <- B, A <~ B ----
|
|
542
539
|
const bareReturnSync = trimmed.match(/^(\S+)\s+<-\s+(\S+)$/);
|
|
543
540
|
const bareReturnAsync = trimmed.match(/^(\S+)\s+<~\s+(\S+)$/);
|
|
544
541
|
const bareReturn = bareReturnSync || bareReturnAsync;
|
|
545
542
|
if (bareReturn) {
|
|
546
|
-
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
lastMsgFrom = from;
|
|
550
|
-
|
|
551
|
-
const msg: SequenceMessage = {
|
|
552
|
-
from,
|
|
553
|
-
to,
|
|
554
|
-
label: '',
|
|
543
|
+
const to = bareReturn[1];
|
|
544
|
+
const from = bareReturn[2];
|
|
545
|
+
pushError(
|
|
555
546
|
lineNumber,
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
};
|
|
559
|
-
result.messages.push(msg);
|
|
560
|
-
currentContainer().push(msg);
|
|
561
|
-
|
|
562
|
-
if (!result.participants.some((p) => p.id === from)) {
|
|
563
|
-
result.participants.push({
|
|
564
|
-
id: from,
|
|
565
|
-
label: from,
|
|
566
|
-
type: inferParticipantType(from),
|
|
567
|
-
lineNumber,
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
if (!result.participants.some((p) => p.id === to)) {
|
|
571
|
-
result.participants.push({
|
|
572
|
-
id: to,
|
|
573
|
-
label: to,
|
|
574
|
-
type: inferParticipantType(to),
|
|
575
|
-
lineNumber,
|
|
576
|
-
});
|
|
577
|
-
}
|
|
547
|
+
`Left-pointing arrows are no longer supported. Write '${from} -> ${to}' instead`
|
|
548
|
+
);
|
|
578
549
|
continue;
|
|
579
550
|
}
|
|
580
551
|
|
package/src/sequence/renderer.ts
CHANGED
|
@@ -569,28 +569,6 @@ export function buildRenderSequence(messages: SequenceMessage[]): RenderStep[] {
|
|
|
569
569
|
});
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
-
// Standalone return: emit as a return step directly (no call, no stack).
|
|
573
|
-
// Also pop the matching pending call from the stack so it doesn't
|
|
574
|
-
// generate a duplicate empty return later.
|
|
575
|
-
if (msg.standaloneReturn) {
|
|
576
|
-
// Find and remove the stack entry this return satisfies
|
|
577
|
-
// (the pending call where from→to matches to→from of this return)
|
|
578
|
-
for (let si = stack.length - 1; si >= 0; si--) {
|
|
579
|
-
if (stack[si].from === msg.to && stack[si].to === msg.from) {
|
|
580
|
-
stack.splice(si, 1);
|
|
581
|
-
break;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
steps.push({
|
|
585
|
-
type: 'return',
|
|
586
|
-
from: msg.from,
|
|
587
|
-
to: msg.to,
|
|
588
|
-
label: msg.label,
|
|
589
|
-
messageIndex: mi,
|
|
590
|
-
});
|
|
591
|
-
continue;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
572
|
// Emit call
|
|
595
573
|
steps.push({
|
|
596
574
|
type: 'call',
|
package/src/utils/arrows.ts
CHANGED
|
@@ -2,38 +2,35 @@
|
|
|
2
2
|
// Shared Arrow Parsing Utility
|
|
3
3
|
// ============================================================
|
|
4
4
|
//
|
|
5
|
-
// Labeled arrow syntax:
|
|
6
|
-
//
|
|
7
|
-
//
|
|
5
|
+
// Labeled arrow syntax (always left-to-right):
|
|
6
|
+
// Sync: `-label->`
|
|
7
|
+
// Async: `~label~>`
|
|
8
8
|
|
|
9
9
|
export interface ParsedArrow {
|
|
10
10
|
from: string;
|
|
11
11
|
to: string;
|
|
12
12
|
label: string;
|
|
13
13
|
async: boolean;
|
|
14
|
-
isReturn: boolean;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
// Forward (call) patterns
|
|
18
17
|
const SYNC_LABELED_RE = /^(\S+)\s+-(.+)->\s+(\S+)$/;
|
|
19
18
|
const ASYNC_LABELED_RE = /^(\S+)\s+~(.+)~>\s+(\S+)$/;
|
|
20
19
|
|
|
21
|
-
//
|
|
20
|
+
// Deprecated patterns — produce errors
|
|
22
21
|
const RETURN_SYNC_LABELED_RE = /^(\S+)\s+<-(.+)-\s+(\S+)$/;
|
|
23
22
|
const RETURN_ASYNC_LABELED_RE = /^(\S+)\s+<~(.+)~\s+(\S+)$/;
|
|
24
|
-
|
|
25
|
-
// Bidi detection (for error messages only)
|
|
26
23
|
const BIDI_SYNC_RE = /^(\S+)\s+<-(.+)->\s+(\S+)$/;
|
|
27
24
|
const BIDI_ASYNC_RE = /^(\S+)\s+<~(.+)~>\s+(\S+)$/;
|
|
28
25
|
|
|
29
|
-
const ARROW_CHARS = ['->', '~>'
|
|
26
|
+
const ARROW_CHARS = ['->', '~>'];
|
|
30
27
|
|
|
31
28
|
/**
|
|
32
29
|
* Try to parse a labeled arrow from a trimmed line.
|
|
33
30
|
*
|
|
34
31
|
* Returns:
|
|
35
32
|
* - `ParsedArrow` if matched and valid
|
|
36
|
-
* - `{ error: string }` if matched but invalid (
|
|
33
|
+
* - `{ error: string }` if matched but invalid (deprecated syntax)
|
|
37
34
|
* - `null` if not a labeled arrow (caller should fall through to bare patterns)
|
|
38
35
|
*/
|
|
39
36
|
export function parseArrow(
|
|
@@ -47,18 +44,28 @@ export function parseArrow(
|
|
|
47
44
|
};
|
|
48
45
|
}
|
|
49
46
|
|
|
47
|
+
// Check deprecated return arrow patterns — return error
|
|
48
|
+
if (RETURN_SYNC_LABELED_RE.test(line) || RETURN_ASYNC_LABELED_RE.test(line)) {
|
|
49
|
+
const m =
|
|
50
|
+
line.match(RETURN_SYNC_LABELED_RE) ??
|
|
51
|
+
line.match(RETURN_ASYNC_LABELED_RE);
|
|
52
|
+
const from = m![3];
|
|
53
|
+
const to = m![1];
|
|
54
|
+
const label = m![2].trim();
|
|
55
|
+
return {
|
|
56
|
+
error: `Left-pointing arrows are no longer supported. Write '${from} -${label}-> ${to}' instead`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
const patterns: {
|
|
51
61
|
re: RegExp;
|
|
52
62
|
async: boolean;
|
|
53
|
-
isReturn: boolean;
|
|
54
63
|
}[] = [
|
|
55
|
-
{ re:
|
|
56
|
-
{ re:
|
|
57
|
-
{ re: SYNC_LABELED_RE, async: false, isReturn: false },
|
|
58
|
-
{ re: ASYNC_LABELED_RE, async: true, isReturn: false },
|
|
64
|
+
{ re: SYNC_LABELED_RE, async: false },
|
|
65
|
+
{ re: ASYNC_LABELED_RE, async: true },
|
|
59
66
|
];
|
|
60
67
|
|
|
61
|
-
for (const { re, async: isAsync
|
|
68
|
+
for (const { re, async: isAsync } of patterns) {
|
|
62
69
|
const m = line.match(re);
|
|
63
70
|
if (!m) continue;
|
|
64
71
|
|
|
@@ -71,28 +78,16 @@ export function parseArrow(
|
|
|
71
78
|
for (const arrow of ARROW_CHARS) {
|
|
72
79
|
if (label.includes(arrow)) {
|
|
73
80
|
return {
|
|
74
|
-
error: 'Arrow characters (->,
|
|
81
|
+
error: 'Arrow characters (->, ~>) are not allowed inside labels',
|
|
75
82
|
};
|
|
76
83
|
}
|
|
77
84
|
}
|
|
78
85
|
|
|
79
|
-
if (isReturn) {
|
|
80
|
-
// Return arrow: A <-msg- B → from=B (source), to=A (destination)
|
|
81
|
-
return {
|
|
82
|
-
from: m[3],
|
|
83
|
-
to: m[1],
|
|
84
|
-
label,
|
|
85
|
-
async: isAsync,
|
|
86
|
-
isReturn: true,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
86
|
return {
|
|
91
87
|
from: m[1],
|
|
92
88
|
to: m[3],
|
|
93
89
|
label,
|
|
94
90
|
async: isAsync,
|
|
95
|
-
isReturn: false,
|
|
96
91
|
};
|
|
97
92
|
}
|
|
98
93
|
|