https://observablehq.com/@gordonsmith/sample-graphviz
graphviz = {
//const path = await require.resolve("@hpcc-js/wasm@1.6.1");
//const path = await require.resolve("@hpcc-js/wasm@1.7.0");
const path = await require.resolve("@hpcc-js/wasm@1.8.1");
//const path = await require.resolve("@hpcc-js/wasm");
const hpccWasm = await require(path);
// Setting wasmFolder is not typically needed ---
const pathParts = path.split("/");
pathParts.pop();
hpccWasm.wasmFolder(pathParts.join("/"));
hpccWasm.graphviz.version = hpccWasm.graphvizVersion && await hpccWasm.graphvizVersion();
return hpccWasm.graphviz;
}
Datapackage 📦 Tables 🗗 Diagram
https://observablehq.com/@randomfractals/datapackage-diagram
erDiagram = diagram(data)
async function diagram(db) {
const tables = (await db.query("SELECT * FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'"))
.filter(({sql}) => sql)
.map(({sql}) => sqlParser(sql))
.map((ast) => ast.statement[0])
.filter(statement => statement.format === 'table' &&
!statement.name?.name.includes('_fts_')) // filter out hidden system tables
const tableNodes = tables.map((table) =>
`"${table.name.name}" [shape=none, label=<
<table bgcolor="#cccccc" border="0" cellborder="0" cellspacing="1" cellpadding="3">
<tr>
<td colspan="2" bgcolor="skyblue"><b>${table.name.name}</b></td>
</tr>${table.definition.filter(({variant}) => variant === 'column').map(({name, datatype}) => `
<tr>
<td port="${name}" align="left" bgcolor="white">${name}</td>
<td align="left" bgcolor="white">${datatype?.variant} ${datatype?.args?.expression?.[0]?.value ? `(${datatype?.args?.expression?.[0]?.value})` : ''}</td>
</tr>`).join('')}}
</table>
>]`).join('\n');
const tableReferences = (await db.query(`
SELECT sqlite_master.name as from_table,
fk_info.[from] as from_column,
fk_info.[table] as to_table,
fk_info.[to] as to_column
FROM sqlite_master
JOIN pragma_foreign_key_list(sqlite_master.name) as fk_info
ORDER BY sqlite_master.name
`)).map((reference) =>
`${reference.from_table}:${reference.from_column} -> ${reference.to_table}:${reference.to_column}`).join('\n');
return dot`digraph "ERD" {
node [fontsize=12]
rankdir = LR
${tableNodes}
${tableReferences}
}`;
}
DuckDb Data Tables
https://observablehq.com/@randomfractals/duckdb-data-tables
digraph Tables {
node [fontsize=12]
rankdir = LR;
"iris" [shape=none, label=<
<table bgcolor="#cccccc" border="0" cellborder="0" cellspacing="1" cellpadding="3">
<tr>
<td colspan="2" bgcolor="skyblue">
<b>iris</b>
</td>
</tr>
<tr>
<td port="petal_length" align="left" bgcolor="white">petal_length</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="petal_width" align="left" bgcolor="white">petal_width</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="sepal_length" align="left" bgcolor="white">sepal_length</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="sepal_width" align="left" bgcolor="white">sepal_width</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="species" align="left" bgcolor="white">species</td>
<td align="left" bgcolor="white">VARCHAR</td>
</tr>}
</table>
>]
"penguins" [shape=none, label=<
<table bgcolor="#cccccc" border="0" cellborder="0" cellspacing="1" cellpadding="3">
<tr>
<td colspan="2" bgcolor="skyblue">
<b>penguins</b>
</td>
</tr>
<tr>
<td port="species" align="left" bgcolor="white">species</td>
<td align="left" bgcolor="white">VARCHAR</td>
</tr>
<tr>
<td port="island" align="left" bgcolor="white">island</td>
<td align="left" bgcolor="white">VARCHAR</td>
</tr>
<tr>
<td port="bill_length_mm" align="left" bgcolor="white">bill_length_mm</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="bill_depth_mm" align="left" bgcolor="white">bill_depth_mm</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="flipper_length_mm" align="left" bgcolor="white">flipper_length_mm</td>
<td align="left" bgcolor="white">INTEGER</td>
</tr>
<tr>
<td port="body_mass_g" align="left" bgcolor="white">body_mass_g</td>
<td align="left" bgcolor="white">INTEGER</td>
</tr>
<tr>
<td port="sex" align="left" bgcolor="white">sex</td>
<td align="left" bgcolor="white">VARCHAR</td>
</tr>}
</table>
>]
"weather" [shape=none, label=<
<table bgcolor="#cccccc" border="0" cellborder="0" cellspacing="1" cellpadding="3">
<tr>
<td colspan="2" bgcolor="skyblue">
<b>weather</b>
</td>
</tr>
<tr>
<td port="location" align="left" bgcolor="white">location</td>
<td align="left" bgcolor="white">VARCHAR</td>
</tr>
<tr>
<td port="date" align="left" bgcolor="white">date</td>
<td align="left" bgcolor="white">DATE</td>
</tr>
<tr>
<td port="precipitation" align="left" bgcolor="white">precipitation</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="temp_max" align="left" bgcolor="white">temp_max</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="temp_min" align="left" bgcolor="white">temp_min</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="wind" align="left" bgcolor="white">wind</td>
<td align="left" bgcolor="white">DOUBLE</td>
</tr>
<tr>
<td port="weather" align="left" bgcolor="white">weather</td>
<td align="left" bgcolor="white">VARCHAR</td>
</tr>}
</table>
>]
}