duckerd 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -26,7 +26,7 @@ Generate an ERD diagram of the database schemas.
26
26
 
27
27
  - `-d, --database <path>`: Path to the database file
28
28
  - `-t, --theme [theme]`: Theme of the chart (choices: `default`, `forest`, `dark`, `neutral`, default: `default`)
29
- - `-o, --output [output]`: Path to the output file
29
+ - `-o, --output <path>`: Path to the output file
30
30
  - `-w, --width [width]`: Width of the page (default: `1024`)
31
31
  - `-H, --height [height]`: Height of the page (default: `768`)
32
32
  - `-f, --outputFormat [format]`: Output format for the generated image (choices: `svg`, `png`, `pdf`, default: `png`)
@@ -36,3 +36,25 @@ Generate an ERD diagram of the database schemas.
36
36
  ```bash
37
37
  duckerd -d ./mydb.duckdb -o ./erd.png -f png -t neutral -w 1600
38
38
  ```
39
+
40
+ **It's possible that you need to re-run the command after the first execution, because the DuckERD CLI automatically installs the `@mermaid-js/mermaid-cli` package globally when it's missing on your system.**
41
+
42
+ ## Usage example
43
+
44
+ ### Download the example database
45
+ For this example we use the [AWS IAM database](https://raw.githubusercontent.com/tobilg/aws-iam-data/main/data/db/iam.duckdb) from the [AWS IAM Data](https://github.com/tobilg/aws-iam-data) project.
46
+
47
+ ```bash
48
+ curl -LO https://raw.githubusercontent.com/tobilg/aws-iam-data/main/data/db/iam.duckdb
49
+ ```
50
+
51
+ ### Generate the ERD
52
+ Then, we can generate the ERD as PNG with the `neutral` theme and otherwise default settings:
53
+
54
+ ```bash
55
+ duckerd -d ./iam.duckdb -f png -t neutral
56
+ ```
57
+
58
+ ### Result
59
+
60
+ ![ERD of the AWS IAM DuckDB database](docs/iam_erd.png)
package/dist/index.js CHANGED
@@ -16,13 +16,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
16
16
  }) : function(o, v) {
17
17
  o["default"] = v;
18
18
  });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
26
36
  Object.defineProperty(exports, "__esModule", { value: true });
27
37
  const commander_1 = require("commander");
28
38
  const path = __importStar(require("path"));
@@ -67,7 +77,8 @@ const run = async (dbPath, options) => {
67
77
  return;
68
78
  }
69
79
  if (stderr) {
70
- console.error(`ERD generation stderr: ${stderr}`);
80
+ console.error(`ERD generation: ${stderr}`);
81
+ console.error(`Please re-run the command!`);
71
82
  return;
72
83
  }
73
84
  console.log(`ERD diagram generated: ${outputFile}`);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sanitizeDataType = exports.generateMermaidCodeForAllDBs = exports.getMetadata = void 0;
3
+ exports.addCommentIfNecessary = exports.sanitizeDataType = exports.generateMermaidCodeForAllDBs = exports.getMetadata = void 0;
4
4
  // Database metadata query
5
5
  const databaseMetadataQuery = `SELECT database_name as databaseName FROM duckdb_databases() WHERE database_name NOT IN ('system', 'temp') ORDER BY database_name`;
6
6
  // Schema metadata query
@@ -84,7 +84,7 @@ const generateMermaidCodeForAllDBs = (metadata) => {
84
84
  // Add tables, columns and constraints
85
85
  mermaidCode += tables.map((table) => {
86
86
  return `"${table.databaseName}.${table.name}" {
87
- ${table.columns.map((column) => ` ${(0, exports.sanitizeDataType)(column.dataType.toUpperCase())} ${column.name} ${table.constraints?.filter((constraint) => constraint.columnName === column.name).map((constraint) => ((constraint.constraintType === "PRIMARY KEY" ? "PK" : "") || (constraint.constraintType === "FOREIGN KEY" ? "FK" : "") || "")).filter(str => str)}`).join("\n")}
87
+ ${table.columns.map((column) => ` ${(0, exports.sanitizeDataType)(column.dataType.toUpperCase())} ${column.name} ${table.constraints?.filter((constraint) => constraint.columnName === column.name).map((constraint) => ((constraint.constraintType === "PRIMARY KEY" ? "PK" : "") || (constraint.constraintType === "FOREIGN KEY" ? "FK" : "") || "")).filter(str => str)}${(0, exports.addCommentIfNecessary)(column.dataType)}`).join("\n")}
88
88
  }\n${table.constraints?.filter((constraint) => constraint.constraintType === "FOREIGN KEY").map((constraint) => ` "${table.databaseName}.${constraint.sql.match(/(?:^|)REFERENCES\s([^*]+?)\b\(/i)[1]}" ||--o{ "${table.databaseName}.${table.name}" : has`).join("\n")}`;
89
89
  }).join("\n ");
90
90
  return mermaidCode;
@@ -99,6 +99,22 @@ ${table.columns.map((column) => ` ${(0, exports.sanitizeDataType)(column.da
99
99
  };
100
100
  exports.generateMermaidCodeForAllDBs = generateMermaidCodeForAllDBs;
101
101
  const sanitizeDataType = (dataType) => {
102
- return dataType.startsWith("STRUCT(") ? "STRUCT" : dataType;
102
+ if (dataType.startsWith("STRUCT(")) {
103
+ return dataType.replace("STRUCT(", "STRUCT").replace(")", "");
104
+ }
105
+ if (dataType.startsWith("ENUM(")) {
106
+ return "ENUM";
107
+ }
108
+ if (dataType.includes(",")) {
109
+ return dataType.replace(",", "_");
110
+ }
111
+ return dataType;
103
112
  };
104
113
  exports.sanitizeDataType = sanitizeDataType;
114
+ const addCommentIfNecessary = (dataType) => {
115
+ if (dataType.startsWith("ENUM(")) {
116
+ return ` "${dataType.replace("ENUM(", "").replace(")", "").split(",").map((value) => value.trim().replace(/'/g, "").replace(/"/g, "")).join(", ")}"`;
117
+ }
118
+ return "";
119
+ };
120
+ exports.addCommentIfNecessary = addCommentIfNecessary;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "duckerd",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "A CLI tool for generating ERD diagrams from DuckDB databases",
5
5
  "author": "TobiLG <tobilg@gmail.com>",
6
6
  "repository": {
@@ -16,7 +16,7 @@
16
16
  "duckerd": "dist/index.js"
17
17
  },
18
18
  "scripts": {
19
- "build": "tsc",
19
+ "build": "rm -rf dist && tsc",
20
20
  "start": "ts-node src/index.ts"
21
21
  },
22
22
  "engines": {
@@ -24,12 +24,12 @@
24
24
  },
25
25
  "keywords": ["duckdb", "erd", "diagram", "cli"],
26
26
  "dependencies": {
27
- "commander": "^12.1.0",
28
- "duckdb-async": "^1.0.0"
27
+ "commander": "^13.1.0",
28
+ "duckdb-async": "^1.2.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^18.11.9",
32
- "ts-node": "^10.9.1",
33
- "typescript": "^5.6.2"
32
+ "ts-node": "^10.9.2",
33
+ "typescript": "^5.8.2"
34
34
  }
35
35
  }