convert sequenceDb to class.

This commit is contained in:
saurabhg772244
2025-01-15 15:37:33 +05:30
parent bc2cc61240
commit 5d3d1047a4
3 changed files with 643 additions and 639 deletions

View File

@@ -1,4 +1,5 @@
import { getConfig } from '../../diagram-api/diagramAPI.js';
import type { DiagramDB } from '../../diagram-api/types.js';
import { log } from '../../logger.js';
import { ImperativeState } from '../../utils/imperativeState.js';
import { sanitizeText } from '../common/common.js';
@@ -28,7 +29,8 @@ interface SequenceState {
lastDestroyed?: Actor;
}
const state = new ImperativeState<SequenceState>(() => ({
export class SequenceDB implements DiagramDB {
private readonly state = new ImperativeState<SequenceState>(() => ({
prevActor: undefined,
actors: new Map(),
createdActors: new Map(),
@@ -41,36 +43,36 @@ const state = new ImperativeState<SequenceState>(() => ({
currentBox: undefined,
lastCreated: undefined,
lastDestroyed: undefined,
}));
}));
export const addBox = function (data: { text: string; color: string; wrap: boolean }) {
state.records.boxes.push({
public addBox = (data: { text: string; color: string; wrap: boolean }) => {
this.state.records.boxes.push({
name: data.text,
wrap: data.wrap ?? autoWrap(),
wrap: data.wrap ?? this.autoWrap(),
fill: data.color,
actorKeys: [],
});
state.records.currentBox = state.records.boxes.slice(-1)[0];
};
this.state.records.currentBox = this.state.records.boxes.slice(-1)[0];
};
export const addActor = function (
public addActor = (
id: string,
name: string,
description: { text: string; wrap?: boolean | null; type: string },
type: string
) {
let assignedBox = state.records.currentBox;
const old = state.records.actors.get(id);
) => {
let assignedBox = this.state.records.currentBox;
const old = this.state.records.actors.get(id);
if (old) {
// If already set and trying to set to a new one throw error
if (state.records.currentBox && old.box && state.records.currentBox !== old.box) {
if (this.state.records.currentBox && old.box && this.state.records.currentBox !== old.box) {
throw new Error(
`A same participant should only be defined in one Box: ${old.name} can't be in '${old.box.name}' and in '${state.records.currentBox.name}' at the same time.`
`A same participant should only be defined in one Box: ${old.name} can't be in '${old.box.name}' and in '${this.state.records.currentBox.name}' at the same time.`
);
}
// Don't change the box if already
assignedBox = old.box ? old.box : state.records.currentBox;
assignedBox = old.box ? old.box : this.state.records.currentBox;
old.box = assignedBox;
// Don't allow description nulling
@@ -87,78 +89,78 @@ export const addActor = function (
description = { text: name, type };
}
state.records.actors.set(id, {
this.state.records.actors.set(id, {
box: assignedBox,
name: name,
description: description.text,
wrap: description.wrap ?? autoWrap(),
prevActor: state.records.prevActor,
wrap: description.wrap ?? this.autoWrap(),
prevActor: this.state.records.prevActor,
links: {},
properties: {},
actorCnt: null,
rectData: null,
type: type ?? 'participant',
});
if (state.records.prevActor) {
const prevActorInRecords = state.records.actors.get(state.records.prevActor);
if (this.state.records.prevActor) {
const prevActorInRecords = this.state.records.actors.get(this.state.records.prevActor);
if (prevActorInRecords) {
prevActorInRecords.nextActor = id;
}
}
if (state.records.currentBox) {
state.records.currentBox.actorKeys.push(id);
if (this.state.records.currentBox) {
this.state.records.currentBox.actorKeys.push(id);
}
state.records.prevActor = id;
};
this.state.records.prevActor = id;
};
const activationCount = (part: string) => {
private readonly activationCount = (part: string) => {
let i;
let count = 0;
if (!part) {
return 0;
}
for (i = 0; i < state.records.messages.length; i++) {
for (i = 0; i < this.state.records.messages.length; i++) {
if (
state.records.messages[i].type === LINETYPE.ACTIVE_START &&
state.records.messages[i].from === part
this.state.records.messages[i].type === this.LINETYPE.ACTIVE_START &&
this.state.records.messages[i].from === part
) {
count++;
}
if (
state.records.messages[i].type === LINETYPE.ACTIVE_END &&
state.records.messages[i].from === part
this.state.records.messages[i].type === this.LINETYPE.ACTIVE_END &&
this.state.records.messages[i].from === part
) {
count--;
}
}
return count;
};
};
export const addMessage = function (
public addMessage = (
idFrom: Message['from'],
idTo: Message['to'],
message: { text: string; wrap?: boolean },
answer: Message['answer']
) {
state.records.messages.push({
) => {
this.state.records.messages.push({
from: idFrom,
to: idTo,
message: message.text,
wrap: message.wrap ?? autoWrap(),
wrap: message.wrap ?? this.autoWrap(),
answer: answer,
});
};
};
export const addSignal = function (
public addSignal = (
idFrom?: Message['from'],
idTo?: Message['to'],
message?: { text: string; wrap: boolean },
messageType?: number,
activate = false
) {
if (messageType === LINETYPE.ACTIVE_END) {
const cnt = activationCount(idFrom ?? '');
) => {
if (messageType === this.LINETYPE.ACTIVE_END) {
const cnt = this.activationCount(idFrom ?? '');
if (cnt < 1) {
// Bail out as there is an activation signal from an inactive participant
const error = new Error('Trying to inactivate an inactive participant (' + idFrom + ')');
@@ -174,61 +176,61 @@ export const addSignal = function (
throw error;
}
}
state.records.messages.push({
this.state.records.messages.push({
from: idFrom,
to: idTo,
message: message?.text ?? '',
wrap: message?.wrap ?? autoWrap(),
wrap: message?.wrap ?? this.autoWrap(),
type: messageType,
activate,
});
return true;
};
};
export const hasAtLeastOneBox = function () {
return state.records.boxes.length > 0;
};
public hasAtLeastOneBox = () => {
return this.state.records.boxes.length > 0;
};
export const hasAtLeastOneBoxWithTitle = function () {
return state.records.boxes.some((b) => b.name);
};
public hasAtLeastOneBoxWithTitle = () => {
return this.state.records.boxes.some((b) => b.name);
};
export const getMessages = function () {
return state.records.messages;
};
public getMessages = () => {
return this.state.records.messages;
};
export const getBoxes = function () {
return state.records.boxes;
};
export const getActors = function () {
return state.records.actors;
};
export const getCreatedActors = function () {
return state.records.createdActors;
};
export const getDestroyedActors = function () {
return state.records.destroyedActors;
};
export const getActor = function (id: string) {
public getBoxes = () => {
return this.state.records.boxes;
};
public getActors = () => {
return this.state.records.actors;
};
public getCreatedActors = () => {
return this.state.records.createdActors;
};
public getDestroyedActors = () => {
return this.state.records.destroyedActors;
};
public getActor = (id: string) => {
// TODO: do we ever use this function in a way that it might return undefined?
return state.records.actors.get(id)!;
};
export const getActorKeys = function () {
return [...state.records.actors.keys()];
};
export const enableSequenceNumbers = function () {
state.records.sequenceNumbersEnabled = true;
};
export const disableSequenceNumbers = function () {
state.records.sequenceNumbersEnabled = false;
};
export const showSequenceNumbers = () => state.records.sequenceNumbersEnabled;
return this.state.records.actors.get(id)!;
};
public getActorKeys = () => {
return [...this.state.records.actors.keys()];
};
public enableSequenceNumbers = () => {
this.state.records.sequenceNumbersEnabled = true;
};
public disableSequenceNumbers = () => {
this.state.records.sequenceNumbersEnabled = false;
};
public showSequenceNumbers = () => this.state.records.sequenceNumbersEnabled;
export const setWrap = function (wrapSetting?: boolean) {
state.records.wrapEnabled = wrapSetting;
};
public setWrap = (wrapSetting?: boolean) => {
this.state.records.wrapEnabled = wrapSetting;
};
const extractWrap = (text?: string): { cleanedText?: string; wrap?: boolean } => {
private readonly extractWrap = (text?: string): { cleanedText?: string; wrap?: boolean } => {
if (text === undefined) {
return {};
}
@@ -237,37 +239,37 @@ const extractWrap = (text?: string): { cleanedText?: string; wrap?: boolean } =>
/^:?wrap:/.exec(text) !== null ? true : /^:?nowrap:/.exec(text) !== null ? false : undefined;
const cleanedText = (wrap === undefined ? text : text.replace(/^:?(?:no)?wrap:/, '')).trim();
return { cleanedText, wrap };
};
};
export const autoWrap = () => {
public autoWrap = () => {
// if setWrap has been called, use that value, otherwise use the value from the config
// TODO: refactor, always use the config value let setWrap update the config value
if (state.records.wrapEnabled !== undefined) {
return state.records.wrapEnabled;
if (this.state.records.wrapEnabled !== undefined) {
return this.state.records.wrapEnabled;
}
return getConfig().sequence?.wrap ?? false;
};
};
export const clear = function () {
state.reset();
public clear = () => {
this.state.reset();
commonClear();
};
};
export const parseMessage = function (str: string) {
public parseMessage = (str: string) => {
const trimmedStr = str.trim();
const { wrap, cleanedText } = extractWrap(trimmedStr);
const { wrap, cleanedText } = this.extractWrap(trimmedStr);
const message = {
text: cleanedText,
wrap,
};
log.debug(`parseMessage: ${JSON.stringify(message)}`);
return message;
};
};
// We expect the box statement to be color first then description
// The color can be rgb,rgba,hsl,hsla, or css code names #hex codes are not supported for now because of the way the char # is handled
// We extract first segment as color, the rest of the line is considered as text
export const parseBoxData = function (str: string) {
// We expect the box statement to be color first then description
// The color can be rgb,rgba,hsl,hsla, or css code names #hex codes are not supported for now because of the way the char # is handled
// We extract first segment as color, the rest of the line is considered as text
public parseBoxData = (str: string) => {
const match = /^((?:rgba?|hsla?)\s*\(.*\)|\w*)(.*)$/.exec(str);
let color = match?.[1] ? match[1].trim() : 'transparent';
let title = match?.[2] ? match[2].trim() : undefined;
@@ -286,15 +288,15 @@ export const parseBoxData = function (str: string) {
title = str.trim();
}
}
const { wrap, cleanedText } = extractWrap(title);
const { wrap, cleanedText } = this.extractWrap(title);
return {
text: cleanedText ? sanitizeText(cleanedText, getConfig()) : undefined,
color,
wrap,
};
};
};
export const LINETYPE = {
public LINETYPE = {
SOLID: 0,
DOTTED: 1,
NOTE: 2,
@@ -327,48 +329,48 @@ export const LINETYPE = {
PAR_OVER_START: 32,
BIDIRECTIONAL_SOLID: 33,
BIDIRECTIONAL_DOTTED: 34,
};
};
export const ARROWTYPE = {
public ARROWTYPE = {
FILLED: 0,
OPEN: 1,
};
};
export const PLACEMENT = {
public PLACEMENT = {
LEFTOF: 0,
RIGHTOF: 1,
OVER: 2,
};
};
export const addNote = function (
public addNote = (
actor: { actor: string },
placement: Message['placement'],
message: { text: string; wrap?: boolean }
) {
) => {
const note: Note = {
actor: actor,
placement: placement,
message: message.text,
wrap: message.wrap ?? autoWrap(),
wrap: message.wrap ?? this.autoWrap(),
};
//@ts-ignore: Coerce actor into a [to, from, ...] array
// eslint-disable-next-line unicorn/prefer-spread
const actors = [].concat(actor, actor);
state.records.notes.push(note);
state.records.messages.push({
this.state.records.notes.push(note);
this.state.records.messages.push({
from: actors[0],
to: actors[1],
message: message.text,
wrap: message.wrap ?? autoWrap(),
type: LINETYPE.NOTE,
wrap: message.wrap ?? this.autoWrap(),
type: this.LINETYPE.NOTE,
placement: placement,
});
};
};
export const addLinks = function (actorId: string, text: { text: string }) {
public addLinks = (actorId: string, text: { text: string }) => {
// find the actor
const actor = getActor(actorId);
const actor = this.getActor(actorId);
// JSON.parse the text
try {
let sanitizedText = sanitizeText(text.text, getConfig());
@@ -376,15 +378,15 @@ export const addLinks = function (actorId: string, text: { text: string }) {
sanitizedText = sanitizedText.replace(/&equals;/g, '=');
const links = JSON.parse(sanitizedText);
// add the deserialized text to the actor's links field.
insertLinks(actor, links);
this.insertLinks(actor, links);
} catch (e) {
log.error('error while parsing actor link text', e);
}
};
};
export const addALink = function (actorId: string, text: { text: string }) {
public addALink = (actorId: string, text: { text: string }) => {
// find the actor
const actor = getActor(actorId);
const actor = this.getActor(actorId);
try {
const links: Record<string, string> = {};
let sanitizedText = sanitizeText(text.text, getConfig());
@@ -396,17 +398,17 @@ export const addALink = function (actorId: string, text: { text: string }) {
links[label] = link;
// add the deserialized text to the actor's links field.
insertLinks(actor, links);
this.insertLinks(actor, links);
} catch (e) {
log.error('error while parsing actor link text', e);
}
};
};
/**
/**
* @param actor - the actor to add the links to
* @param links - the links to add to the actor
*/
function insertLinks(actor: Actor, links: Record<string, string>) {
private readonly insertLinks = (actor: Actor, links: Record<string, string>) => {
if (actor.links == null) {
actor.links = links;
} else {
@@ -414,27 +416,27 @@ function insertLinks(actor: Actor, links: Record<string, string>) {
actor.links[key] = links[key];
}
}
}
};
export const addProperties = function (actorId: string, text: { text: string }) {
public addProperties = (actorId: string, text: { text: string }) => {
// find the actor
const actor = getActor(actorId);
const actor = this.getActor(actorId);
// JSON.parse the text
try {
const sanitizedText = sanitizeText(text.text, getConfig());
const properties: Record<string, unknown> = JSON.parse(sanitizedText);
// add the deserialized text to the actor's property field.
insertProperties(actor, properties);
this.insertProperties(actor, properties);
} catch (e) {
log.error('error while parsing actor properties text', e);
}
};
};
/**
/**
* @param actor - the actor to add the properties to
* @param properties - the properties to add to the actor's properties
*/
function insertProperties(actor: Actor, properties: Record<string, unknown>) {
private readonly insertProperties = (actor: Actor, properties: Record<string, unknown>) => {
if (actor.properties == null) {
actor.properties = properties;
} else {
@@ -442,15 +444,15 @@ function insertProperties(actor: Actor, properties: Record<string, unknown>) {
actor.properties[key] = properties[key];
}
}
}
};
function boxEnd() {
state.records.currentBox = undefined;
}
private readonly boxEnd = () => {
this.state.records.currentBox = undefined;
};
export const addDetails = function (actorId: string, text: { text: string }) {
public addDetails = (actorId: string, text: { text: string }) => {
// find the actor
const actor = getActor(actorId);
const actor = this.getActor(actorId);
const elem = document.getElementById(text.text)!;
// JSON.parse the text
@@ -459,35 +461,35 @@ export const addDetails = function (actorId: string, text: { text: string }) {
const details = JSON.parse(text);
// add the deserialized text to the actor's property field.
if (details.properties) {
insertProperties(actor, details.properties);
this.insertProperties(actor, details.properties);
}
if (details.links) {
insertLinks(actor, details.links);
this.insertLinks(actor, details.links);
}
} catch (e) {
log.error('error while parsing actor details text', e);
}
};
};
export const getActorProperty = function (actor: Actor, key: string) {
public getActorProperty = (actor: Actor, key: string) => {
if (actor?.properties !== undefined) {
return actor.properties[key];
}
return undefined;
};
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-redundant-type-constituents
export const apply = function (param: any | AddMessageParams | AddMessageParams[]) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-redundant-type-constituents
public apply = (param: any | AddMessageParams | AddMessageParams[]) => {
if (Array.isArray(param)) {
param.forEach(function (item) {
apply(item);
param.forEach((item) => {
this.apply(item);
});
} else {
switch (param.type) {
case 'sequenceIndex':
state.records.messages.push({
this.state.records.messages.push({
from: undefined,
to: undefined,
message: {
@@ -500,169 +502,139 @@ export const apply = function (param: any | AddMessageParams | AddMessageParams[
});
break;
case 'addParticipant':
addActor(param.actor, param.actor, param.description, param.draw);
this.addActor(param.actor, param.actor, param.description, param.draw);
break;
case 'createParticipant':
if (state.records.actors.has(param.actor)) {
if (this.state.records.actors.has(param.actor)) {
throw new Error(
"It is not possible to have actors with the same id, even if one is destroyed before the next is created. Use 'AS' aliases to simulate the behavior"
);
}
state.records.lastCreated = param.actor;
addActor(param.actor, param.actor, param.description, param.draw);
state.records.createdActors.set(param.actor, state.records.messages.length);
this.state.records.lastCreated = param.actor;
this.addActor(param.actor, param.actor, param.description, param.draw);
this.state.records.createdActors.set(param.actor, this.state.records.messages.length);
break;
case 'destroyParticipant':
state.records.lastDestroyed = param.actor;
state.records.destroyedActors.set(param.actor, state.records.messages.length);
this.state.records.lastDestroyed = param.actor;
this.state.records.destroyedActors.set(param.actor, this.state.records.messages.length);
break;
case 'activeStart':
addSignal(param.actor, undefined, undefined, param.signalType);
this.addSignal(param.actor, undefined, undefined, param.signalType);
break;
case 'activeEnd':
addSignal(param.actor, undefined, undefined, param.signalType);
this.addSignal(param.actor, undefined, undefined, param.signalType);
break;
case 'addNote':
addNote(param.actor, param.placement, param.text);
this.addNote(param.actor, param.placement, param.text);
break;
case 'addLinks':
addLinks(param.actor, param.text);
this.addLinks(param.actor, param.text);
break;
case 'addALink':
addALink(param.actor, param.text);
this.addALink(param.actor, param.text);
break;
case 'addProperties':
addProperties(param.actor, param.text);
this.addProperties(param.actor, param.text);
break;
case 'addDetails':
addDetails(param.actor, param.text);
this.addDetails(param.actor, param.text);
break;
case 'addMessage':
if (state.records.lastCreated) {
if (param.to !== state.records.lastCreated) {
if (this.state.records.lastCreated) {
if (param.to !== this.state.records.lastCreated) {
throw new Error(
'The created participant ' +
state.records.lastCreated.name +
this.state.records.lastCreated.name +
' does not have an associated creating message after its declaration. Please check the sequence diagram.'
);
} else {
state.records.lastCreated = undefined;
this.state.records.lastCreated = undefined;
}
} else if (state.records.lastDestroyed) {
} else if (this.state.records.lastDestroyed) {
if (
param.to !== state.records.lastDestroyed &&
param.from !== state.records.lastDestroyed
param.to !== this.state.records.lastDestroyed &&
param.from !== this.state.records.lastDestroyed
) {
throw new Error(
'The destroyed participant ' +
state.records.lastDestroyed.name +
this.state.records.lastDestroyed.name +
' does not have an associated destroying message after its declaration. Please check the sequence diagram.'
);
} else {
state.records.lastDestroyed = undefined;
this.state.records.lastDestroyed = undefined;
}
}
addSignal(param.from, param.to, param.msg, param.signalType, param.activate);
this.addSignal(param.from, param.to, param.msg, param.signalType, param.activate);
break;
case 'boxStart':
addBox(param.boxData);
this.addBox(param.boxData);
break;
case 'boxEnd':
boxEnd();
this.boxEnd();
break;
case 'loopStart':
addSignal(undefined, undefined, param.loopText, param.signalType);
this.addSignal(undefined, undefined, param.loopText, param.signalType);
break;
case 'loopEnd':
addSignal(undefined, undefined, undefined, param.signalType);
this.addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'rectStart':
addSignal(undefined, undefined, param.color, param.signalType);
this.addSignal(undefined, undefined, param.color, param.signalType);
break;
case 'rectEnd':
addSignal(undefined, undefined, undefined, param.signalType);
this.addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'optStart':
addSignal(undefined, undefined, param.optText, param.signalType);
this.addSignal(undefined, undefined, param.optText, param.signalType);
break;
case 'optEnd':
addSignal(undefined, undefined, undefined, param.signalType);
this.addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'altStart':
addSignal(undefined, undefined, param.altText, param.signalType);
this.addSignal(undefined, undefined, param.altText, param.signalType);
break;
case 'else':
addSignal(undefined, undefined, param.altText, param.signalType);
this.addSignal(undefined, undefined, param.altText, param.signalType);
break;
case 'altEnd':
addSignal(undefined, undefined, undefined, param.signalType);
this.addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'setAccTitle':
setAccTitle(param.text);
break;
case 'parStart':
addSignal(undefined, undefined, param.parText, param.signalType);
this.addSignal(undefined, undefined, param.parText, param.signalType);
break;
case 'and':
addSignal(undefined, undefined, param.parText, param.signalType);
this.addSignal(undefined, undefined, param.parText, param.signalType);
break;
case 'parEnd':
addSignal(undefined, undefined, undefined, param.signalType);
this.addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'criticalStart':
addSignal(undefined, undefined, param.criticalText, param.signalType);
this.addSignal(undefined, undefined, param.criticalText, param.signalType);
break;
case 'option':
addSignal(undefined, undefined, param.optionText, param.signalType);
this.addSignal(undefined, undefined, param.optionText, param.signalType);
break;
case 'criticalEnd':
addSignal(undefined, undefined, undefined, param.signalType);
this.addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'breakStart':
addSignal(undefined, undefined, param.breakText, param.signalType);
this.addSignal(undefined, undefined, param.breakText, param.signalType);
break;
case 'breakEnd':
addSignal(undefined, undefined, undefined, param.signalType);
this.addSignal(undefined, undefined, undefined, param.signalType);
break;
}
}
};
};
export default {
addActor,
addMessage,
addSignal,
addLinks,
addDetails,
addProperties,
autoWrap,
setWrap,
enableSequenceNumbers,
disableSequenceNumbers,
showSequenceNumbers,
getMessages,
getActors,
getCreatedActors,
getDestroyedActors,
getActor,
getActorKeys,
getActorProperty,
getAccTitle,
getBoxes,
getDiagramTitle,
setDiagramTitle,
getConfig: () => getConfig().sequence,
clear,
parseMessage,
parseBoxData,
LINETYPE,
ARROWTYPE,
PLACEMENT,
addNote,
setAccTitle,
apply,
setAccDescription,
getAccDescription,
hasAtLeastOneBox,
hasAtLeastOneBoxWithTitle,
};
public getAccTitle = getAccTitle;
public getDiagramTitle = getDiagramTitle;
public setDiagramTitle = setDiagramTitle;
public getConfig = () => getConfig().sequence;
public setAccTitle = setAccTitle;
public setAccDescription = setAccDescription;
public getAccDescription = getAccDescription;
}

View File

@@ -3,6 +3,7 @@ import { setSiteConfig } from '../../diagram-api/diagramAPI.js';
import mermaidAPI from '../../mermaidAPI.js';
import { Diagram } from '../../Diagram.js';
import { addDiagrams } from '../../diagram-api/diagram-orchestration.js';
import { SequenceDB } from './sequenceDb.js';
beforeAll(async () => {
// Is required to load the sequence diagram
@@ -2071,3 +2072,27 @@ ${prop}-->>A: Hello, how are you?`)
).resolves.toBeDefined();
});
});
describe('sequence db class', () => {
let sequenceDb;
beforeEach(() => {
sequenceDb = new SequenceDB();
});
// This is to ensure that functions used in sequence JISON are exposed as function from SequenceDB
it('should have functions used in sequence JISON as own property', () => {
const functionsUsedInParser = [
'apply',
'parseBoxData',
'LINETYPE',
'setDiagramTitle',
'setAccTitle',
'setAccDescription',
'parseMessage',
'PLACEMENT',
];
for (const fun of functionsUsedInParser) {
expect(Object.hasOwn(sequenceDb, fun)).toBe(true);
}
});
});

View File

@@ -1,13 +1,20 @@
import type { DiagramDefinition } from '../../diagram-api/types.js';
// @ts-ignore: JISON doesn't support types
import parser from './parser/sequenceDiagram.jison';
import db from './sequenceDb.js';
import { SequenceDB } from './sequenceDb.js';
import styles from './styles.js';
import renderer from './sequenceRenderer.js';
let db: SequenceDB;
export const diagram: DiagramDefinition = {
parser,
db,
get db() {
if (!db) {
db = new SequenceDB();
}
return db;
},
renderer,
styles,
init: ({ wrap }) => {