Skip to content

Commit bfa53f4

Browse files
authored
Merge pull request #77 from Software-Developers-IRL/f/lastlink3
F/lastlink3 ala cart docs 0.0.9
2 parents 7f05542 + a21c2eb commit bfa53f4

File tree

10 files changed

+314
-16
lines changed

10 files changed

+314
-16
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@funktechno/little-mermaid-2-the-sql",
3-
"version": "0.0.8",
3+
"version": "0.0.9",
44
"description": "",
55
"main": "./lib/index.js",
66
"types": "./lib/index.d.ts",

readme.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,131 @@
99
## Generating Mermaid erDiagram
1010
* see [samples](./samples/readme.md) for more information
1111

12+
## Ala Cart
13+
1. `npm install --save @funktechno/little-mermaid-2-the-sql`
14+
1. Example
15+
* from markdown content
16+
```typescript
17+
import { GenerateSqlFromMermaid } from "@funktechno/little-mermaid-2-the-sql/lib/src/Library";
18+
import { MarkdownContentResponseI } from "@funktechno/little-mermaid-2-the-sql/lib/src/types";
19+
20+
21+
const markdownContent:MarkdownContentResponseI ={
22+
settings: {
23+
database: "postgres",
24+
outputName: "result",
25+
isRaw: false,
26+
src: ""
27+
},
28+
content:`
29+
#Test
30+
\`\`\`mermaid
31+
erDiagram
32+
%% comment 1
33+
Persons {
34+
int PersonID PK "NOT NULL"
35+
varchar255 LastName
36+
varchar255 FirstName
37+
varchar255 Address
38+
varchar255 City
39+
}
40+
41+
%% comment 2
42+
Orders {
43+
int OrderID PK "NOT NULL"
44+
int PersonID FK "NOT NULL"
45+
}
46+
47+
Persons ||--o{ Orders : "[Persons.PersonId] to [Orders.PersonId]"
48+
\`\`\`
49+
`
50+
};
51+
52+
const sqlOutputs = GenerateSqlFromMermaid(markdownContent);
53+
```
54+
55+
* manual mermaid db model
56+
```typescript
57+
import { DbParser } from "@funktechno/little-mermaid-2-the-sql/lib/src/generate-sql-ddl";
58+
import erDb from "@funktechno/little-mermaid-2-the-sql/lib/src/mermaid/src/diagrams/er/erDb";
59+
60+
const db = erDb;
61+
62+
let entityName = "Persons";
63+
// load mermaid db with entities
64+
db.addEntity(entityName);
65+
let attributes:DbEntityAttributesDefinition[] = [
66+
{
67+
attributeName: "PersonID",
68+
attributeKeyType: "PK",
69+
attributeType: "int",
70+
attributeComment: "NOT NULL"
71+
},
72+
{
73+
attributeName: "LastName",
74+
attributeType: "varchar255"
75+
},
76+
{
77+
attributeName: "FirstName",
78+
attributeType: "varchar255"
79+
},
80+
{
81+
attributeName: "Address",
82+
attributeType: "varchar255"
83+
},
84+
{
85+
attributeName: "City",
86+
attributeType: "varchar255"
87+
}
88+
];
89+
db.addAttributes(entityName,attributes);
90+
91+
entityName = "Orders";
92+
db.addEntity(entityName);
93+
attributes = [
94+
{
95+
attributeName: "OrderID",
96+
attributeKeyType: "PK",
97+
attributeType: "int",
98+
attributeComment: "NOT NULL"
99+
},
100+
{
101+
attributeName: "PersonID",
102+
attributeKeyType: "FK",
103+
attributeType: "int",
104+
attributeComment: "NOT NULL"
105+
}
106+
];
107+
db.addAttributes(entityName,attributes);
108+
109+
const relSpec:DbRelSpec= {
110+
cardA: "ZERO_OR_MORE",
111+
cardB: "ONLY_ONE",
112+
relType: "IDENTIFYING"
113+
};
114+
115+
db.addRelationship("Persons", `[Persons.PersonId] to [${entityName}.PersonId]`, entityName, relSpec);
116+
const ddlSyntax = new DbParser('sqlite', db).getSQLDataDefinition();
117+
```
118+
* sql output
119+
```sql
120+
CREATE TABLE "Persons" (
121+
"City" varchar(255),
122+
"Address" varchar(255),
123+
"FirstName" varchar(255),
124+
"LastName" varchar(255),
125+
"PersonID" int NOT NULL,
126+
PRIMARY KEY("PersonID")
127+
);
128+
129+
CREATE TABLE "Orders" (
130+
"PersonID" int NOT NULL,
131+
"OrderID" int NOT NULL,
132+
PRIMARY KEY("OrderID"),
133+
FOREIGN KEY ("PersonId") REFERENCES "Persons"("PersonId")
134+
);
135+
```
136+
12137
## Development
13138

14139
1. git clone repo

src/mermaid/src/diagrams/er/erDb.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
DbEntityAttributesDefinition,
55
DbEntityDefinition,
66
DbRelationshipDefinition,
7+
DbRelSpec,
78
} from "../../../../types";
89
// import mermaidAPI from '../../mermaidAPI';
910
// import * as configApi from '../../../../../deps/mermaid/src/config'
@@ -69,7 +70,7 @@ const addRelationship = function (
6970
entA: string,
7071
rolA: string,
7172
entB: string,
72-
rSpec: string
73+
rSpec: DbRelSpec
7374
) {
7475
const rel: DbRelationshipDefinition = {
7576
entityA: entA,

src/types/index.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,38 @@ export interface DiagramDefinition {
2424
export interface DbEntityAttributesDefinition {
2525
attributeType?: string;
2626
attributeName?: string;
27-
attributeKeyType?: string;
27+
attributeKeyType?: "PK" | "FK";
2828
attributeComment?: string;
2929
}
3030

3131
export interface DbEntityDefinition {
3232
attributes: DbEntityAttributesDefinition[];
3333
}
3434

35+
export interface DbRelSpec {
36+
cardA: string;
37+
cardB: string;
38+
relType: string;
39+
}
40+
3541
export interface DbRelationshipDefinition {
3642
entityA: string;
3743
roleA: string;
3844
entityB: string;
39-
relSpec: string;
45+
relSpec: DbRelSpec;
4046
}
4147

4248
export interface DbDefinition {
4349
Cardinality: Record<string, string>;
4450
Identification: Record<string, string>;
4551
addEntity: (name: string) => void;
46-
addAttributes: (entityName: string, attribs: any[]) => void;
52+
addAttributes: (entityName: string, attribs: DbEntityAttributesDefinition[]) => void;
4753
getEntities: () => Record<string, DbEntityDefinition>;
4854
addRelationship: (
4955
entA: string,
5056
rolA: string,
5157
entB: string,
52-
rSpec: string
58+
rSpec: DbRelSpec
5359
) => void;
5460
getRelationships: () => DbRelationshipDefinition[];
5561
clear: () => void;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"Generate DDL examples Should generate create table SQL syntax": "CREATE TABLE \"Persons\" (\n\t\"City\" varchar(255),\n\t\"Address\" varchar(255),\n\t\"FirstName\" varchar(255),\n\t\"LastName\" varchar(255),\n\t\"PersonID\" int NOT NULL,\n\tPRIMARY KEY(\"PersonID\")\n);\n\nCREATE TABLE \"Orders\" (\n\t\"PersonID\" int NOT NULL,\n\t\"OrderID\" int NOT NULL,\n\tPRIMARY KEY(\"OrderID\"),\n\tFOREIGN KEY (\"PersonId\") REFERENCES \"Persons\"(\"PersonId\")\n);\n\n"
3+
}

tests/generate-sql-ddl.spec.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests/src/Library.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { getExpected, updateExpected } from "../utils/helper";
2+
import { GenerateSqlFromMermaid } from "../../src/Library";
3+
import { MarkdownContentResponseI } from "../../src/types";
4+
5+
const dataSource = "GenerateSqlFromMermaid";
6+
7+
describe("Generate DDL examples from markdown", () => {
8+
it("Create DLL", async () => {
9+
const markdownContent:MarkdownContentResponseI ={
10+
settings: {
11+
database: "postgres",
12+
outputName: "result",
13+
isRaw: false,
14+
src: ""
15+
},
16+
content:`
17+
#Test
18+
\`\`\`mermaid
19+
erDiagram
20+
%% comment 1
21+
Persons {
22+
int PersonID PK "NOT NULL"
23+
varchar255 LastName
24+
varchar255 FirstName
25+
varchar255 Address
26+
varchar255 City
27+
}
28+
29+
%% comment 2
30+
Orders {
31+
int OrderID PK "NOT NULL"
32+
int PersonID FK "NOT NULL"
33+
}
34+
35+
Persons ||--o{ Orders : "[Persons.PersonId] to [Orders.PersonId]"
36+
\`\`\`
37+
`
38+
};
39+
// junit compile error for require parser.js export
40+
// const sqlOutputs = GenerateSqlFromMermaid(markdownContent);
41+
42+
// const dataKey = expect.getState().currentTestName || "unknown";
43+
44+
// const expectedResult = await getExpected(dataSource, dataKey);
45+
46+
// if (sqlOutputs != expectedResult) {
47+
// await updateExpected(dataSource, dataKey, sqlOutputs);
48+
// }
49+
50+
// expect(sqlOutputs).toStrictEqual(expectedResult);
51+
});
52+
});
53+

tests/src/generate-sql-ddl.spec.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { DbParser } from "../../src/generate-sql-ddl";
2+
import erDb from "../../src/mermaid/src/diagrams/er/erDb";
3+
import { DbEntityAttributesDefinition, DbRelSpec } from "../../src/types";
4+
import { getExpected, updateExpected } from "../utils/helper";
5+
import * as fs from "fs";
6+
7+
const dataSource = "getSQLDataDefinition";
8+
describe("Generate DDL examples", () => {
9+
it("Should generate create table SQL syntax", async () => {
10+
const db = erDb;
11+
let entityName = "Persons";
12+
db.addEntity(entityName);
13+
let attributes:DbEntityAttributesDefinition[] = [
14+
{
15+
attributeName: "PersonID",
16+
attributeKeyType: "PK",
17+
attributeType: "int",
18+
attributeComment: "NOT NULL"
19+
},
20+
{
21+
attributeName: "LastName",
22+
attributeType: "varchar255"
23+
},
24+
{
25+
attributeName: "FirstName",
26+
attributeType: "varchar255"
27+
},
28+
{
29+
attributeName: "Address",
30+
attributeType: "varchar255"
31+
},
32+
{
33+
attributeName: "City",
34+
attributeType: "varchar255"
35+
}
36+
];
37+
db.addAttributes(entityName,attributes);
38+
39+
entityName = "Orders";
40+
db.addEntity(entityName);
41+
attributes = [
42+
{
43+
attributeName: "OrderID",
44+
attributeKeyType: "PK",
45+
attributeType: "int",
46+
attributeComment: "NOT NULL"
47+
},
48+
{
49+
attributeName: "PersonID",
50+
attributeKeyType: "FK",
51+
attributeType: "int",
52+
attributeComment: "NOT NULL"
53+
}
54+
];
55+
db.addAttributes(entityName,attributes);
56+
57+
const relSpec:DbRelSpec= {
58+
cardA: "ZERO_OR_MORE",
59+
cardB: "ONLY_ONE",
60+
relType: "IDENTIFYING"
61+
};
62+
63+
db.addRelationship("Persons", `[Persons.PersonId] to [${entityName}.PersonId]`,entityName, relSpec);
64+
// `erDiagram artists { }`;
65+
const ddlSyntax = new DbParser("sqlite", db).getSQLDataDefinition();
66+
67+
const dataKey = expect.getState().currentTestName || "unknown";
68+
69+
const expectedResult = await getExpected(dataSource, dataKey);
70+
71+
if (ddlSyntax != expectedResult) {
72+
await updateExpected(dataSource, dataKey, ddlSyntax);
73+
}
74+
75+
// console.log(result);
76+
expect(ddlSyntax).toStrictEqual(expectedResult);
77+
// expect(ddlSyntax).toBe('CREATE TABLE artists');
78+
79+
// await fs.writeFileSync(
80+
// "output-sqlite.sql",
81+
// ddlSyntax
82+
// );
83+
});
84+
});

tests/utils/helper.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint-disable @typescript-eslint/no-var-requires */
2+
// import {fs} from "fs";
3+
import * as fs from "fs";
4+
// const fs = require("fs");
5+
const path = require("path");
6+
const base_DIR = path.join(__dirname, "../data/results");
7+
8+
export async function getExpectedDict<T>(testData: string): Promise<Record<string, T | null>> {
9+
const filePath = path.join(base_DIR, testData + ".json");
10+
console.log(filePath);
11+
if (await fs.existsSync(filePath)) {
12+
const expectedResults: Record<string, T> = await JSON.parse(fs.readFileSync(filePath, "utf8"));
13+
return expectedResults;
14+
} else
15+
return {};
16+
}
17+
18+
export async function getExpected<T>(testData: string, key: string): Promise<T | null> {
19+
const expectedResults = await getExpectedDict<T>(testData);
20+
if (expectedResults[key]) {
21+
return expectedResults[key];
22+
} else {
23+
return null;
24+
}
25+
}
26+
27+
export async function updateExpected<T>(testData: string, key: string, result: T | null) {
28+
const expectedResults = await getExpectedDict<T>(testData);
29+
30+
expectedResults[key] = result;
31+
32+
const filePath = path.join(base_DIR, testData + ".json");
33+
const stringResults = JSON.stringify(expectedResults, null, 4);
34+
await fs.writeFileSync(filePath, stringResults);
35+
}

0 commit comments

Comments
 (0)