quickdbd-cli 0.4.2__py3-none-any.whl → 0.5.0__py3-none-any.whl
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.
- quickdbd_cli/__init__.py +1 -1
- quickdbd_cli/assets/icon.svg +1 -1
- quickdbd_cli/assets/style.css +2 -2
- quickdbd_cli/cli.py +83 -5
- quickdbd_cli/html.py +25 -0
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/METADATA +2 -2
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/RECORD +13 -13
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/WHEEL +0 -0
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/entry_points.txt +0 -0
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/licenses/NOTICE +0 -0
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/licenses/src/quickdbd_cli/assets/Inter-LICENSE.txt +0 -0
- {quickdbd_cli-0.4.2.dist-info → quickdbd_cli-0.5.0.dist-info}/licenses/src/quickdbd_cli/assets/elk-LICENSE.md +0 -0
quickdbd_cli/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.5.0"
|
quickdbd_cli/assets/icon.svg
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><rect width="128" height="128" rx="28" fill="#
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><rect width="128" height="128" rx="28" fill="#2b5797"/><rect x="22" y="22" width="42" height="36" rx="9" fill="#fff"/><path d="M44 58v19a10 10 0 0 0 10 10h12" fill="none" stroke="#fff" stroke-width="8"/><rect x="64" y="70" width="42" height="33" rx="8" fill="#a9bfdd"/></svg>
|
quickdbd_cli/assets/style.css
CHANGED
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
--t-edge: #b8bcc2;
|
|
35
35
|
--row-hl: #dbe6f6;
|
|
36
36
|
--row-hover: #eef3fa;
|
|
37
|
-
--lit: #
|
|
38
|
-
--lit-deep: #
|
|
37
|
+
--lit: #2b5797;
|
|
38
|
+
--lit-deep: #1c3a66;
|
|
39
39
|
}
|
|
40
40
|
/* Dark theme. viewer.js sets data-theme from the toggle, or from prefers-color-scheme when it's on auto. */
|
|
41
41
|
:root[data-theme="dark"] {
|
quickdbd_cli/cli.py
CHANGED
|
@@ -32,11 +32,12 @@ def _open(args) -> Project:
|
|
|
32
32
|
return Project.open([Path(p) for p in args.paths], Path(args.layout) if getattr(args, "layout", None) else None)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def _name(p: Path) -> str:
|
|
36
|
+
return p.stem if p.is_file() else (p.resolve().name or "diagram")
|
|
37
|
+
|
|
38
|
+
|
|
35
39
|
def _title(project: Project) -> str:
|
|
36
|
-
if len(project.inputs) == 1
|
|
37
|
-
p = project.inputs[0]
|
|
38
|
-
return p.stem if p.is_file() else (p.resolve().name or "diagram")
|
|
39
|
-
return "diagram"
|
|
40
|
+
return _name(project.inputs[0]) if len(project.inputs) == 1 else "diagram"
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def _github_annotation(d: Diagnostic, level: str) -> str:
|
|
@@ -76,7 +77,30 @@ def _symbols(schema: Schema) -> dict:
|
|
|
76
77
|
return {"tables": tables, "rels": rels}
|
|
77
78
|
|
|
78
79
|
|
|
80
|
+
def _check_each(args) -> int:
|
|
81
|
+
"""Check each PATH on its own, as ``build --site`` builds them; folders with no schema files are skipped."""
|
|
82
|
+
from .project import discover
|
|
83
|
+
|
|
84
|
+
if args.format == "json" or args.stdin_file:
|
|
85
|
+
print("error: --each can't be used with --format json or --stdin-file", file=sys.stderr)
|
|
86
|
+
return 2
|
|
87
|
+
code, checked = 0, 0
|
|
88
|
+
for p in args.paths:
|
|
89
|
+
if Path(p).is_dir() and not discover([Path(p)]):
|
|
90
|
+
print(f"Skipped {p}: no .txt or .dbml schema files", file=sys.stderr)
|
|
91
|
+
continue
|
|
92
|
+
print(f"{p}:")
|
|
93
|
+
code = max(code, cmd_check(argparse.Namespace(**{**vars(args), "paths": [p], "each": False})))
|
|
94
|
+
checked += 1
|
|
95
|
+
if not checked:
|
|
96
|
+
print("error: no schema files found in: " + ", ".join(args.paths), file=sys.stderr)
|
|
97
|
+
return 2
|
|
98
|
+
return code
|
|
99
|
+
|
|
100
|
+
|
|
79
101
|
def cmd_check(args) -> int:
|
|
102
|
+
if args.each:
|
|
103
|
+
return _check_each(args)
|
|
80
104
|
project = _open(args)
|
|
81
105
|
overrides = None
|
|
82
106
|
if args.stdin_file:
|
|
@@ -143,7 +167,52 @@ def _built_page(args) -> tuple[str, dict] | int:
|
|
|
143
167
|
return render_page(model, pos, _title(project)), model
|
|
144
168
|
|
|
145
169
|
|
|
170
|
+
def _build_site(args) -> int:
|
|
171
|
+
"""One page per PATH plus an index linking them, in the folder ``args.site``."""
|
|
172
|
+
from urllib.parse import quote
|
|
173
|
+
|
|
174
|
+
from .html import render_index
|
|
175
|
+
from .project import discover
|
|
176
|
+
|
|
177
|
+
if args.layout:
|
|
178
|
+
print("error: --layout can't be used with --site: each PATH uses its own layout file", file=sys.stderr)
|
|
179
|
+
return 2
|
|
180
|
+
pages, seen, failed = [], {}, 0
|
|
181
|
+
for p in map(Path, args.paths):
|
|
182
|
+
if p.is_dir() and not discover([p]):
|
|
183
|
+
print(f"Skipped {p}: no .txt or .dbml schema files", file=sys.stderr)
|
|
184
|
+
continue
|
|
185
|
+
name = _name(p)
|
|
186
|
+
if name.lower() in seen or name.lower() == "index":
|
|
187
|
+
other = seen.get(name.lower(), "the index page")
|
|
188
|
+
print(f"error: {p} and {other} would both be written to {name}.html", file=sys.stderr)
|
|
189
|
+
return 2
|
|
190
|
+
seen[name.lower()] = p
|
|
191
|
+
res = _built_page(argparse.Namespace(**{**vars(args), "paths": [str(p)]}))
|
|
192
|
+
if isinstance(res, int):
|
|
193
|
+
failed = max(failed, res)
|
|
194
|
+
continue
|
|
195
|
+
pages.append((name, *res))
|
|
196
|
+
if failed: # nothing is written, so a failed build never leaves a half-updated site
|
|
197
|
+
return failed
|
|
198
|
+
if not pages:
|
|
199
|
+
print("error: no schema files found in: " + ", ".join(args.paths), file=sys.stderr)
|
|
200
|
+
return 2
|
|
201
|
+
out = Path(args.site)
|
|
202
|
+
out.mkdir(parents=True, exist_ok=True)
|
|
203
|
+
index = []
|
|
204
|
+
for name, page, model in pages:
|
|
205
|
+
(out / f"{name}.html").write_text(page, encoding="utf-8")
|
|
206
|
+
index.append((name, quote(f"{name}.html"), len(model["tables"]), len(model["rels"])))
|
|
207
|
+
print(f"Wrote {out / f'{name}.html'} ({len(model['tables'])} tables, {len(model['rels'])} relationships)")
|
|
208
|
+
(out / "index.html").write_text(render_index(index), encoding="utf-8")
|
|
209
|
+
print(f"Wrote {out / 'index.html'} ({len(pages)} diagrams)")
|
|
210
|
+
return 0
|
|
211
|
+
|
|
212
|
+
|
|
146
213
|
def cmd_build(args) -> int:
|
|
214
|
+
if args.site:
|
|
215
|
+
return _build_site(args)
|
|
147
216
|
res = _built_page(args)
|
|
148
217
|
if isinstance(res, int):
|
|
149
218
|
return res
|
|
@@ -575,11 +644,20 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
575
644
|
metavar="PATH",
|
|
576
645
|
help="read this schema file's text from stdin instead of disk (an editor's unsaved buffer)",
|
|
577
646
|
)
|
|
647
|
+
sp.add_argument(
|
|
648
|
+
"--each",
|
|
649
|
+
action="store_true",
|
|
650
|
+
help="check each PATH as its own schema, as build --site does (folders with no schema files are skipped)",
|
|
651
|
+
)
|
|
578
652
|
sp.set_defaults(func=cmd_check)
|
|
579
653
|
|
|
580
654
|
sp = sub.add_parser("build", help="write an interactive HTML diagram")
|
|
581
655
|
paths(sp)
|
|
582
|
-
sp.
|
|
656
|
+
out = sp.add_mutually_exclusive_group()
|
|
657
|
+
out.add_argument("-o", "--output", default="diagram.html")
|
|
658
|
+
out.add_argument(
|
|
659
|
+
"--site", metavar="DIR", help="one page per PATH (named after it) plus an index.html linking them, in DIR"
|
|
660
|
+
)
|
|
583
661
|
selectors(sp)
|
|
584
662
|
sp.add_argument(
|
|
585
663
|
"--diff-base", metavar="GIT_REF", help="colour tables/columns changed since this git ref (e.g. origin/main)"
|
quickdbd_cli/html.py
CHANGED
|
@@ -190,3 +190,28 @@ def render_page(
|
|
|
190
190
|
f"<script>{_asset('viewer.js')}</script>"
|
|
191
191
|
f"{scripts}</body></html>\n"
|
|
192
192
|
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
INDEX_CSS = (
|
|
196
|
+
":root{color-scheme:light dark;--fg:#1f2328;--muted:#656d76;--bg:#fff;--line:#d0d7de}"
|
|
197
|
+
"@media (prefers-color-scheme:dark){:root{--fg:#e6edf3;--muted:#8d96a0;--bg:#0d1117;--line:#30363d}}"
|
|
198
|
+
"body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.5 system-ui,sans-serif}"
|
|
199
|
+
"main{max-width:640px;margin:0 auto;padding:32px 16px}h1{font-size:20px;margin:0 0 16px}"
|
|
200
|
+
"ul{list-style:none;margin:0;padding:0}li{border-top:1px solid var(--line);padding:10px 0}"
|
|
201
|
+
"a{color:inherit;font-weight:600}span{color:var(--muted);margin-left:8px}"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def render_index(pages: list[tuple[str, str, int, int]], title: str = "Diagrams") -> str:
|
|
206
|
+
"""``qdbd build --site``'s index: a link per (name, href, tables, relationships)."""
|
|
207
|
+
items = "".join(
|
|
208
|
+
f'<li><a href="{_escape(href)}">{_escape(name)}</a><span>{t} tables, {r} relationships</span></li>'
|
|
209
|
+
for name, href, t, r in pages
|
|
210
|
+
)
|
|
211
|
+
return (
|
|
212
|
+
'<!doctype html>\n<html lang="en"><head><meta charset="utf-8">'
|
|
213
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1">'
|
|
214
|
+
'<meta name="generator" content="qdbd">'
|
|
215
|
+
f"{favicon()}<title>{_escape(title)}</title><style>{INDEX_CSS}</style></head>"
|
|
216
|
+
f"<body><main><h1>{_escape(title)}</h1><ul>{items}</ul></main></body></html>\n"
|
|
217
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: quickdbd-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Compile QuickDBD-syntax schema files into interactive HTML ER diagrams, with no table limit.
|
|
5
5
|
Project-URL: Homepage, https://qdbd.dev/
|
|
6
6
|
Project-URL: Documentation, https://qdbd.dev/guide/
|
|
@@ -193,7 +193,7 @@ jobs:
|
|
|
193
193
|
permissions: { contents: read, pull-requests: write }
|
|
194
194
|
steps:
|
|
195
195
|
- uses: actions/checkout@v4
|
|
196
|
-
- uses: MarkPhamm/quickdbd-cli@v0.
|
|
196
|
+
- uses: MarkPhamm/quickdbd-cli@v0.5.0
|
|
197
197
|
with:
|
|
198
198
|
path: erd/ # schema file(s) or folder(s)
|
|
199
199
|
output: site/index.html
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
quickdbd_cli/__init__.py,sha256=
|
|
1
|
+
quickdbd_cli/__init__.py,sha256=LBK46heutvn3KmsCrKIYu8RQikbfnjZaj2xFrXaeCzQ,22
|
|
2
2
|
quickdbd_cli/__main__.py,sha256=E6Gls0DNz8GQK2K-kOUIx8cYhgANW_CH54VKrfCfs14,52
|
|
3
3
|
quickdbd_cli/agent.py,sha256=LEuReTkwWDlRLs-GfQQMpMosHDFWbin0EAXRo73j-dA,37202
|
|
4
|
-
quickdbd_cli/cli.py,sha256=
|
|
4
|
+
quickdbd_cli/cli.py,sha256=zP9wnA_gcLZQ1bt3YCVt14V87fYmdgzsmDpi8E_0g3Y,33862
|
|
5
5
|
quickdbd_cli/convert.py,sha256=1AYFm4YmEav_wZp7xCAcL7TsD3qC17Y1I5g6V_fyAU0,16682
|
|
6
6
|
quickdbd_cli/dbml.py,sha256=tHJOtMm1PHx4-yqs6rncPqdDfbwPcW8F54j_kKlWkx0,59413
|
|
7
7
|
quickdbd_cli/dbt.py,sha256=AMHzERmc8WfL1tBLX4bJdPVghIHrqrfx8nMDbZMrueY,23100
|
|
8
8
|
quickdbd_cli/diff.py,sha256=UBiCE3dk_cN-xSRZFQoLiIIFh_FAVZUpLwsdtHG9eBo,9986
|
|
9
9
|
quickdbd_cli/export.py,sha256=XbSvWqFmhQHPcBtPHPit1SmhJ6qXrPyGlHYt7FpIMyo,3539
|
|
10
|
-
quickdbd_cli/html.py,sha256=
|
|
10
|
+
quickdbd_cli/html.py,sha256=tcbxiUmKhKfpAb7Pke1AVSRPK5VWaw9znpOi_3mQkoQ,9634
|
|
11
11
|
quickdbd_cli/jsrt.py,sha256=_sRkmUbgHDTwK272jeTNUwojfjUKAkv4UeD2E2u3H1A,3464
|
|
12
12
|
quickdbd_cli/layout.py,sha256=2wrryJ-SSJbMlOdxmtCTzC2_zkTtvRVs-OuOBS1bGEQ,10856
|
|
13
13
|
quickdbd_cli/mcp.py,sha256=ibUg1a50BBco-hZABdxTexGZi_gclFCdcBDalTvFar8,12350
|
|
@@ -28,16 +28,16 @@ quickdbd_cli/assets/editor.js,sha256=Gare_MeAOKlc2QZpTR9nD8Ty-U6JBY3HRWAeMnDkCsU
|
|
|
28
28
|
quickdbd_cli/assets/elk-LICENSE.md,sha256=Y36B9KG2tAeVNcSZ_KBeI4z3YFwf9bdtYNfafOlnAMk,14443
|
|
29
29
|
quickdbd_cli/assets/elk.bundled.js,sha256=EiLkT5U853Rq8jgB5yNwj45vQ2uLN3pqX8dVLzSjB7M,1609707
|
|
30
30
|
quickdbd_cli/assets/font-metrics.json,sha256=sXSiElxQSK8md8IEePLwh16TTdAqKt9rV140pvMlVS8,8654
|
|
31
|
-
quickdbd_cli/assets/icon.svg,sha256=
|
|
31
|
+
quickdbd_cli/assets/icon.svg,sha256=z1KKpKN3dJbESzbC1EDS3NYOj9aKQw1pJfzwXFPg_M0,338
|
|
32
32
|
quickdbd_cli/assets/render.js,sha256=WzxX_sUgdz0O4GgiaupKl8J_LI4YCqF9PUxzRbwebwo,31891
|
|
33
|
-
quickdbd_cli/assets/style.css,sha256=
|
|
33
|
+
quickdbd_cli/assets/style.css,sha256=mTkpexDcMilBtds2WRk6SYiCrIA1DpZLueKmm3pRQw0,18877
|
|
34
34
|
quickdbd_cli/assets/syntax-reference.md,sha256=WERcsWjyrfeHQPgxQriWKBsqFJnmWTQ2oRZjKYAHhKc,5322
|
|
35
35
|
quickdbd_cli/assets/viewer.js,sha256=3rKXI80TNv9jF1dJNQa3Gpy0042yTcGfTz_8qg4h5WU,49676
|
|
36
|
-
quickdbd_cli-0.
|
|
37
|
-
quickdbd_cli-0.
|
|
38
|
-
quickdbd_cli-0.
|
|
39
|
-
quickdbd_cli-0.
|
|
40
|
-
quickdbd_cli-0.
|
|
41
|
-
quickdbd_cli-0.
|
|
42
|
-
quickdbd_cli-0.
|
|
43
|
-
quickdbd_cli-0.
|
|
36
|
+
quickdbd_cli-0.5.0.dist-info/METADATA,sha256=NjeLisXVxAEYPnC53QjQpJv0IUrwcJgiYHHjf1BNfiw,17704
|
|
37
|
+
quickdbd_cli-0.5.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
38
|
+
quickdbd_cli-0.5.0.dist-info/entry_points.txt,sha256=nRhiYYug-XOY95nWUmi4oanico3Zjkfqk2OHtIE6SQ0,47
|
|
39
|
+
quickdbd_cli-0.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
40
|
+
quickdbd_cli-0.5.0.dist-info/licenses/NOTICE,sha256=pyv3BfIYiGzKLU4w-GcBe7GXoXxHqZ97Mf6Zpx_3_i0,2067
|
|
41
|
+
quickdbd_cli-0.5.0.dist-info/licenses/src/quickdbd_cli/assets/Inter-LICENSE.txt,sha256=JiSB6ERSGzJvXs0FPlm5jIstp4yO4b27boF0MF5Uk1o,4380
|
|
42
|
+
quickdbd_cli-0.5.0.dist-info/licenses/src/quickdbd_cli/assets/elk-LICENSE.md,sha256=Y36B9KG2tAeVNcSZ_KBeI4z3YFwf9bdtYNfafOlnAMk,14443
|
|
43
|
+
quickdbd_cli-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|