Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event Model Diagram #5861

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions packages/mermaid/src/config.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ export interface MermaidConfig {
*
*/
cycleBreakingStrategy?:
| 'GREEDY'
| 'DEPTH_FIRST'
| 'INTERACTIVE'
| 'MODEL_ORDER'
| 'GREEDY_MODEL_ORDER';
| 'GREEDY'
| 'DEPTH_FIRST'
| 'INTERACTIVE'
| 'MODEL_ORDER'
| 'GREEDY_MODEL_ORDER';
};
darkMode?: boolean;
htmlLabels?: boolean;
Expand Down Expand Up @@ -197,6 +197,7 @@ export interface MermaidConfig {
c4?: C4DiagramConfig;
sankey?: SankeyDiagramConfig;
packet?: PacketDiagramConfig;
eventModel?: EventModelDiagramConfig;
block?: BlockDiagramConfig;
dompurifyConfig?: DOMPurifyConfiguration;
wrap?: boolean;
Expand Down Expand Up @@ -1511,6 +1512,15 @@ export interface PacketDiagramConfig extends BaseDiagramConfig {
export interface BlockDiagramConfig extends BaseDiagramConfig {
padding?: number;
}
/**
* The object containing configurations specific for gantt diagrams
*
*
* This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "EventModelDiagramConfig".
*/
export interface EventModelDiagramConfig extends BaseDiagramConfig {
}
/**
* This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "FontConfig".
Expand Down
3 changes: 3 additions & 0 deletions packages/mermaid/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ const config: RequiredDeep<MermaidConfig> = {
packet: {
...defaultConfigJson.packet,
},
eventModel: {
...defaultConfigJson.eventModel,
}
};

const keyify = (obj: any, prefix = ''): string[] =>
Expand Down
74 changes: 74 additions & 0 deletions packages/mermaid/src/diagrams/eventmodel/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { block } from 'marked';
import { getConfig as commonGetConfig } from '../../config.js';
import DEFAULT_CONFIG from '../../defaultConfig.js';
import { ImperativeState } from '../../utils/imperativeState.js';
import {
clear as commonClear,
getAccDescription,
getAccTitle,
getDiagramTitle,
setAccDescription,
setAccTitle,
setDiagramTitle,
} from '../common/commonDb.js';
import { eventModel } from './detector.js';
import type { EventModelData, EventModelDB } from './types.js';
import type { EdgeSet, System, Pattern } from '@mermaid-js/parser';


type Edge = EventModelData['edges'][number];
type Node = EventModelData['nodes'][string];

const data = new ImperativeState((): EventModelData => ({
nodes: {},
edges: [],
}));

const getEdges = (block: EdgeSet): Edge[] => {
const sources = block.from.flatMap(({ targets }) => targets);
const destinations = block.to.flatMap(({ targets }) => targets);
return sources.flatMap(from => destinations.map(to => ({ from, to })));
}

const getSystemNodes = (block: System): Record<string, Node> => {

}


export const db: EventModelDB = {
clear() {
data.reset();
commonClear();
},
getConfig() {
return { ...DEFAULT_CONFIG.eventModel, ...commonGetConfig() }
},
addBlock(block) {
switch (block.$type) {
case 'Query':
case 'Command':
case 'Trigger':
data.records.nodes[block.name.name] = {
type: block.$type === 'Trigger' ? 'AutomatedTrigger' : block.$type,
name: block.name.name,
displayName: block.name.displayName,
}
return true;
case 'Pattern':
data.records.nodes = { ...data.records.nodes, ...getPatternNodes(block) };
return true;
case 'System':
data.records.nodes = { ...data.records.nodes, ...getSystemNodes(block) };
return true;
case 'EdgeSet':
data.records.edges = [...data.records.edges, ...getEdges(block)];
return true;
}
},
setAccTitle,
getAccTitle,
setDiagramTitle,
getDiagramTitle,
getAccDescription,
setAccDescription,
};
22 changes: 22 additions & 0 deletions packages/mermaid/src/diagrams/eventmodel/detector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type {
DiagramDetector,
DiagramLoader,
ExternalDiagramDefinition,
} from '../../diagram-api/types.js';

const id = 'eventModel';

const detector: DiagramDetector = (txt) => {
return /^\s*eventModel-beta/.test(txt);
};

const loader: DiagramLoader = async () => {
const { diagram } = await import('./diagram.js');
return { id, diagram };
};

export const eventModel: ExternalDiagramDefinition = {
id,
detector,
loader,
};
12 changes: 12 additions & 0 deletions packages/mermaid/src/diagrams/eventmodel/diagram.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { DiagramDefinition } from '../../diagram-api/types.js';
import { db } from './db.js';
import { parser } from './parser.js';
import { renderer } from './renderer.js';
import { styles } from './styles.js';

export const diagram: DiagramDefinition = {
parser,
db,
renderer,
styles,
};
175 changes: 175 additions & 0 deletions packages/mermaid/src/diagrams/eventmodel/packet.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import { it, describe, expect } from 'vitest';
import { db } from './db.js';
import { parser } from './parser.js';

const { clear, getPacket, getDiagramTitle, getAccTitle, getAccDescription } = db;

describe('packet diagrams', () => {
beforeEach(() => {
clear();
});

it('should handle a packet-beta definition', async () => {
const str = `packet-beta`;
await expect(parser.parse(str)).resolves.not.toThrow();
expect(getPacket()).toMatchInlineSnapshot('[]');
});

it('should handle diagram with data and title', async () => {
const str = `packet-beta
title Packet diagram
accTitle: Packet accTitle
accDescr: Packet accDescription
0-10: "test"
`;
await expect(parser.parse(str)).resolves.not.toThrow();
expect(getDiagramTitle()).toMatchInlineSnapshot('"Packet diagram"');
expect(getAccTitle()).toMatchInlineSnapshot('"Packet accTitle"');
expect(getAccDescription()).toMatchInlineSnapshot('"Packet accDescription"');
expect(getPacket()).toMatchInlineSnapshot(`
[
[
{
"end": 10,
"label": "test",
"start": 0,
},
],
]
`);
});

it('should handle single bits', async () => {
const str = `packet-beta
0-10: "test"
11: "single"
`;
await expect(parser.parse(str)).resolves.not.toThrow();
expect(getPacket()).toMatchInlineSnapshot(`
[
[
{
"end": 10,
"label": "test",
"start": 0,
},
{
"end": 11,
"label": "single",
"start": 11,
},
],
]
`);
});

it('should split into multiple rows', async () => {
const str = `packet-beta
0-10: "test"
11-90: "multiple"
`;
await expect(parser.parse(str)).resolves.not.toThrow();
expect(getPacket()).toMatchInlineSnapshot(`
[
[
{
"end": 10,
"label": "test",
"start": 0,
},
{
"end": 31,
"label": "multiple",
"start": 11,
},
],
[
{
"end": 63,
"label": "multiple",
"start": 32,
},
],
[
{
"end": 90,
"label": "multiple",
"start": 64,
},
],
]
`);
});

it('should split into multiple rows when cut at exact length', async () => {
const str = `packet-beta
0-16: "test"
17-63: "multiple"
`;
await expect(parser.parse(str)).resolves.not.toThrow();
expect(getPacket()).toMatchInlineSnapshot(`
[
[
{
"end": 16,
"label": "test",
"start": 0,
},
{
"end": 31,
"label": "multiple",
"start": 17,
},
],
[
{
"end": 63,
"label": "multiple",
"start": 32,
},
],
]
`);
});

it('should throw error if numbers are not continuous', async () => {
const str = `packet-beta
0-16: "test"
18-20: "error"
`;
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Packet block 18 - 20 is not contiguous. It should start from 17.]`
);
});

it('should throw error if numbers are not continuous for single packets', async () => {
const str = `packet-beta
0-16: "test"
18: "error"
`;
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Packet block 18 - 18 is not contiguous. It should start from 17.]`
);
});

it('should throw error if numbers are not continuous for single packets - 2', async () => {
const str = `packet-beta
0-16: "test"
17: "good"
19: "error"
`;
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Packet block 19 - 19 is not contiguous. It should start from 18.]`
);
});

it('should throw error if end is less than start', async () => {
const str = `packet-beta
0-16: "test"
25-20: "error"
`;
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Packet block 25 - 20 is invalid. End must be greater than start.]`
);
});
});
20 changes: 20 additions & 0 deletions packages/mermaid/src/diagrams/eventmodel/parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { EventModel } from '@mermaid-js/parser';
import { parse } from '@mermaid-js/parser';
import type { ParserDefinition } from '../../diagram-api/types.js';
import { log } from '../../logger.js';
import { populateCommonDb } from '../common/populateCommonDb.js';
import { db } from './db.js';


const populate = (ast: EventModel) => {
populateCommonDb(ast, db);
// TODO finish populate appropriately
};

export const parser: ParserDefinition = {
parse: async (input: string): Promise<void> => {
const ast: EventModel = await parse('eventModel', input);
log.debug(ast);
populate(ast);
},
};
Loading
Loading