ts-prorm-orm 1.2.2 → 2.0.0
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/CHANGELOG.md +209 -0
- package/README.md +32 -24
- package/dist/compliance/index.d.ts +2 -0
- package/dist/compliance/index.js +13 -1
- package/dist/connection-manager.js +13 -1
- package/dist/core/expressions.d.ts +58 -0
- package/dist/core/expressions.js +83 -0
- package/dist/core/hooks-manager.d.ts +179 -0
- package/dist/core/hooks-manager.js +291 -0
- package/dist/core/types.d.ts +235 -0
- package/dist/core/types.js +9 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.js +11 -1
- package/dist/diagrams/chen-diagram.d.ts +15 -12
- package/dist/diagrams/chen-diagram.js +76 -85
- package/dist/diagrams/class-diagram.d.ts +9 -8
- package/dist/diagrams/class-diagram.js +60 -82
- package/dist/diagrams/core/index.d.ts +13 -0
- package/dist/diagrams/core/index.js +33 -0
- package/dist/diagrams/core/layout.d.ts +104 -0
- package/dist/diagrams/core/layout.js +223 -0
- package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
- package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
- package/dist/diagrams/core/theme.d.ts +84 -0
- package/dist/diagrams/core/theme.js +62 -0
- package/dist/diagrams/dependency-diagram.d.ts +15 -14
- package/dist/diagrams/dependency-diagram.js +71 -105
- package/dist/diagrams/er-diagram.d.ts +13 -26
- package/dist/diagrams/er-diagram.js +180 -259
- package/dist/diagrams/flow-diagram.d.ts +16 -11
- package/dist/diagrams/flow-diagram.js +96 -91
- package/dist/diagrams/gantt-diagram.d.ts +10 -5
- package/dist/diagrams/gantt-diagram.js +77 -103
- package/dist/diagrams/index-diagram.d.ts +10 -10
- package/dist/diagrams/index-diagram.js +106 -116
- package/dist/diagrams/index.d.ts +6 -9
- package/dist/diagrams/index.js +9 -24
- package/dist/diagrams/migration-diagram.d.ts +8 -4
- package/dist/diagrams/migration-diagram.js +189 -161
- package/dist/diagrams/model-diagram.d.ts +34 -34
- package/dist/diagrams/model-diagram.js +106 -485
- package/dist/diagrams/package-diagram.d.ts +9 -6
- package/dist/diagrams/package-diagram.js +64 -101
- package/dist/diagrams/relational-diagram.d.ts +12 -10
- package/dist/diagrams/relational-diagram.js +87 -114
- package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
- package/dist/diagrams/schemadoc-diagram.js +71 -93
- package/dist/diagrams/sequence-diagram.d.ts +10 -10
- package/dist/diagrams/sequence-diagram.js +64 -89
- package/dist/diagrams/state-diagram.d.ts +10 -9
- package/dist/diagrams/state-diagram.js +69 -92
- package/dist/diagrams/tree-diagram.d.ts +11 -5
- package/dist/diagrams/tree-diagram.js +41 -65
- package/dist/dialects/clickhouse/index.js +15 -0
- package/dist/dialects/cockroachdb/index.d.ts +1 -1
- package/dist/dialects/cockroachdb/index.js +32 -63
- package/dist/dialects/db2/index.js +23 -8
- package/dist/dialects/dialect.d.ts +29 -5
- package/dist/dialects/duckdb/index.js +9 -2
- package/dist/dialects/hana/index.js +22 -5
- package/dist/dialects/lock-clause-helper.d.ts +167 -0
- package/dist/dialects/lock-clause-helper.js +316 -0
- package/dist/dialects/mariadb/index.d.ts +7 -4
- package/dist/dialects/mariadb/index.js +36 -60
- package/dist/dialects/mssql/index.js +34 -3
- package/dist/dialects/mysql/index.d.ts +1 -1
- package/dist/dialects/mysql/index.js +17 -45
- package/dist/dialects/oracle/index.d.ts +14 -3
- package/dist/dialects/oracle/index.js +66 -36
- package/dist/dialects/order-expression-helper.d.ts +72 -0
- package/dist/dialects/order-expression-helper.js +154 -0
- package/dist/dialects/partial-index.d.ts +52 -0
- package/dist/dialects/partial-index.js +251 -0
- package/dist/dialects/postgres/index.d.ts +1 -1
- package/dist/dialects/postgres/index.js +43 -68
- package/dist/dialects/redshift/index.js +9 -2
- package/dist/dialects/snowflake/index.js +17 -0
- package/dist/dialects/spanner/index.js +7 -2
- package/dist/dialects/sqlite/driver.d.ts +55 -0
- package/dist/dialects/sqlite/driver.js +102 -0
- package/dist/dialects/sqlite/index.d.ts +1 -1
- package/dist/dialects/sqlite/index.js +49 -27
- package/dist/graph/base-graph-dialect.d.ts +24 -3
- package/dist/graph/base-graph-dialect.js +43 -2
- package/dist/graph/dgraph/index.js +6 -0
- package/dist/graph/gremlin/index.d.ts +6 -0
- package/dist/graph/gremlin/index.js +12 -1
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/neo4j/index.d.ts +2 -0
- package/dist/graph/neo4j/index.js +6 -1
- package/dist/graph/types.d.ts +12 -1
- package/dist/index.d.ts +13 -4
- package/dist/index.js +54 -7
- package/dist/logging/index.d.ts +10 -0
- package/dist/logging/index.js +23 -0
- package/dist/logging/query-logging.d.ts +82 -0
- package/dist/logging/query-logging.js +102 -0
- package/dist/models/decorators.d.ts +39 -3
- package/dist/models/decorators.js +74 -0
- package/dist/models/eager-load.d.ts +99 -0
- package/dist/models/eager-load.js +348 -5
- package/dist/models/indexes.d.ts +3 -2
- package/dist/models/indexes.js +7 -1
- package/dist/models/model.js +69 -43
- package/dist/prorm.d.ts +175 -409
- package/dist/prorm.js +1142 -557
- package/dist/query-builders/order-limit-builder.js +12 -10
- package/dist/query-builders/sql-compiler.d.ts +10 -3
- package/dist/query-builders/sql-compiler.js +14 -43
- package/dist/query-interface.d.ts +2 -1
- package/dist/sql-constants.d.ts +44 -0
- package/dist/sql-constants.js +138 -1
- package/dist/types/index.d.ts +53 -17
- package/dist/types/index.js +10 -15
- package/dist/types/query-types.d.ts +26 -0
- package/dist/types/query-types.js +30 -0
- package/package.json +32 -5
- package/dist/decorators/belongs-to-many.js +0 -115
- package/dist/decorators/belongs-to.js +0 -115
- package/dist/decorators/has-many.js +0 -127
- package/dist/decorators/has-one.js +0 -116
- package/dist/diagrams/palette.d.ts +0 -138
- package/dist/diagrams/palette.js +0 -194
- package/dist/hooks/hooks-manager.d.ts +0 -189
- package/dist/hooks/hooks-manager.js +0 -350
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/index.js +0 -37
- /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
- /package/dist/{logging.js → logging/logger.js} +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Layout primitives shared by every generator.
|
|
4
|
+
*
|
|
5
|
+
* Each generator previously carried its own text measurement, box drawing,
|
|
6
|
+
* arrow routing and footer code. These are the pieces that were duplicated,
|
|
7
|
+
* factored once so a change to how a panel or an edge looks lands everywhere.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.measureText = measureText;
|
|
11
|
+
exports.truncate = truncate;
|
|
12
|
+
exports.rect = rect;
|
|
13
|
+
exports.line = line;
|
|
14
|
+
exports.text = text;
|
|
15
|
+
exports.panelSize = panelSize;
|
|
16
|
+
exports.panel = panel;
|
|
17
|
+
exports.defineArrowhead = defineArrowhead;
|
|
18
|
+
exports.edge = edge;
|
|
19
|
+
exports.gridPack = gridPack;
|
|
20
|
+
exports.documentTitle = documentTitle;
|
|
21
|
+
exports.footer = footer;
|
|
22
|
+
const theme_1 = require("./theme");
|
|
23
|
+
/**
|
|
24
|
+
* Approximate rendered width of a string.
|
|
25
|
+
*
|
|
26
|
+
* SVG has no text metrics without a layout engine, so this is the usual
|
|
27
|
+
* average-advance estimate. It is deliberately slightly generous: under-
|
|
28
|
+
* measuring clips text, over-measuring only adds whitespace.
|
|
29
|
+
*/
|
|
30
|
+
function measureText(text, size = theme_1.FONT.body, mono = false) {
|
|
31
|
+
const ratio = mono ? 0.6 : 0.55;
|
|
32
|
+
return Math.ceil(text.length * size * ratio);
|
|
33
|
+
}
|
|
34
|
+
/** Truncate to fit `maxWidth`, appending a single-character ellipsis. */
|
|
35
|
+
function truncate(text, maxWidth, size = theme_1.FONT.body, mono = false) {
|
|
36
|
+
if (measureText(text, size, mono) <= maxWidth)
|
|
37
|
+
return text;
|
|
38
|
+
let out = text;
|
|
39
|
+
while (out.length > 1 && measureText(out + '...', size, mono) > maxWidth) {
|
|
40
|
+
out = out.slice(0, -1);
|
|
41
|
+
}
|
|
42
|
+
return out + '...';
|
|
43
|
+
}
|
|
44
|
+
/** Draw a plain hairline rectangle. */
|
|
45
|
+
function rect(parent, box, fill = theme_1.INK.ground) {
|
|
46
|
+
return parent.child('rect', {
|
|
47
|
+
x: box.x,
|
|
48
|
+
y: box.y,
|
|
49
|
+
width: box.w,
|
|
50
|
+
height: box.h,
|
|
51
|
+
fill,
|
|
52
|
+
stroke: theme_1.INK.line,
|
|
53
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/** Draw a hairline between two points. */
|
|
57
|
+
function line(parent, x1, y1, x2, y2, dashed = false) {
|
|
58
|
+
const el = parent.child('line', {
|
|
59
|
+
x1,
|
|
60
|
+
y1,
|
|
61
|
+
x2,
|
|
62
|
+
y2,
|
|
63
|
+
stroke: theme_1.INK.line,
|
|
64
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
65
|
+
});
|
|
66
|
+
if (dashed)
|
|
67
|
+
el.attr('stroke-dasharray', '4 3');
|
|
68
|
+
return el;
|
|
69
|
+
}
|
|
70
|
+
/** Draw a run of text. */
|
|
71
|
+
function text(parent, x, y, value, opts = {}) {
|
|
72
|
+
const el = parent
|
|
73
|
+
.child('text', {
|
|
74
|
+
x,
|
|
75
|
+
y,
|
|
76
|
+
'font-family': opts.mono ? theme_1.FONT.mono : theme_1.FONT.family,
|
|
77
|
+
'font-size': opts.size ?? theme_1.FONT.body,
|
|
78
|
+
fill: opts.fill ?? theme_1.INK.line,
|
|
79
|
+
})
|
|
80
|
+
.text(value);
|
|
81
|
+
if (opts.anchor && opts.anchor !== 'start')
|
|
82
|
+
el.attr('text-anchor', opts.anchor);
|
|
83
|
+
if (opts.weight === 'bold')
|
|
84
|
+
el.attr('font-weight', 'bold');
|
|
85
|
+
return el;
|
|
86
|
+
}
|
|
87
|
+
/** Compute a panel's size without drawing it, for layout passes. */
|
|
88
|
+
function panelSize(opts) {
|
|
89
|
+
const rows = opts.rows ?? [];
|
|
90
|
+
const headerH = opts.subtitle ? theme_1.ROW_HEIGHT * 2 : theme_1.ROW_HEIGHT + theme_1.SPACE.sm;
|
|
91
|
+
let contentW = measureText(opts.title, theme_1.FONT.title) + theme_1.SPACE.lg;
|
|
92
|
+
if (opts.subtitle)
|
|
93
|
+
contentW = Math.max(contentW, measureText(opts.subtitle, theme_1.FONT.small) + theme_1.SPACE.lg);
|
|
94
|
+
for (const r of rows) {
|
|
95
|
+
const marker = r.marker ? measureText(r.marker, theme_1.FONT.small, true) + theme_1.SPACE.sm : 0;
|
|
96
|
+
const label = measureText(r.label, theme_1.FONT.body);
|
|
97
|
+
const detail = r.detail ? measureText(r.detail, theme_1.FONT.small, true) + theme_1.SPACE.lg : 0;
|
|
98
|
+
contentW = Math.max(contentW, marker + label + detail + theme_1.SPACE.lg * 2);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
w: Math.max(opts.minWidth ?? 0, contentW),
|
|
102
|
+
h: headerH + rows.length * theme_1.ROW_HEIGHT + (rows.length ? theme_1.SPACE.xs : 0),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Draw a titled panel at `x,y` and return the box it occupies.
|
|
107
|
+
*
|
|
108
|
+
* The header is a washed bar with a hairline under it; rows are plain text with
|
|
109
|
+
* the detail column right-aligned.
|
|
110
|
+
*/
|
|
111
|
+
function panel(parent, x, y, opts) {
|
|
112
|
+
const { w, h } = panelSize(opts);
|
|
113
|
+
const rows = opts.rows ?? [];
|
|
114
|
+
const headerH = opts.subtitle ? theme_1.ROW_HEIGHT * 2 : theme_1.ROW_HEIGHT + theme_1.SPACE.sm;
|
|
115
|
+
const box = { x, y, w, h };
|
|
116
|
+
const g = parent.child('g');
|
|
117
|
+
rect(g, box);
|
|
118
|
+
// Header bar
|
|
119
|
+
g.child('rect', {
|
|
120
|
+
x,
|
|
121
|
+
y,
|
|
122
|
+
width: w,
|
|
123
|
+
height: headerH,
|
|
124
|
+
fill: theme_1.INK.wash,
|
|
125
|
+
stroke: theme_1.INK.line,
|
|
126
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
127
|
+
});
|
|
128
|
+
text(g, x + theme_1.SPACE.sm, y + theme_1.FONT.title + theme_1.SPACE.xs, opts.title, {
|
|
129
|
+
size: theme_1.FONT.title,
|
|
130
|
+
weight: 'bold',
|
|
131
|
+
});
|
|
132
|
+
if (opts.subtitle) {
|
|
133
|
+
text(g, x + theme_1.SPACE.sm, y + theme_1.ROW_HEIGHT + theme_1.FONT.small + theme_1.SPACE.xs, opts.subtitle, {
|
|
134
|
+
size: theme_1.FONT.small,
|
|
135
|
+
fill: theme_1.INK.muted,
|
|
136
|
+
mono: true,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
rows.forEach((r, i) => {
|
|
140
|
+
const rowY = y + headerH + i * theme_1.ROW_HEIGHT;
|
|
141
|
+
const baseline = rowY + theme_1.ROW_HEIGHT - theme_1.SPACE.xs - 1;
|
|
142
|
+
if (r.rule)
|
|
143
|
+
line(g, x, rowY, x + w, rowY);
|
|
144
|
+
let cursor = x + theme_1.SPACE.sm;
|
|
145
|
+
if (r.marker) {
|
|
146
|
+
text(g, cursor, baseline, r.marker, { size: theme_1.FONT.small, mono: true, fill: theme_1.INK.muted });
|
|
147
|
+
cursor += measureText(r.marker, theme_1.FONT.small, true) + theme_1.SPACE.sm;
|
|
148
|
+
}
|
|
149
|
+
text(g, cursor, baseline, r.label, { size: theme_1.FONT.body });
|
|
150
|
+
if (r.detail) {
|
|
151
|
+
text(g, x + w - theme_1.SPACE.sm, baseline, r.detail, {
|
|
152
|
+
size: theme_1.FONT.small,
|
|
153
|
+
mono: true,
|
|
154
|
+
fill: theme_1.INK.muted,
|
|
155
|
+
anchor: 'end',
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return box;
|
|
160
|
+
}
|
|
161
|
+
/** Register the single arrowhead marker. Call once per document. */
|
|
162
|
+
function defineArrowhead(defs, id = 'arrow') {
|
|
163
|
+
defs
|
|
164
|
+
.child('marker', {
|
|
165
|
+
id,
|
|
166
|
+
viewBox: '0 0 10 10',
|
|
167
|
+
refX: 9,
|
|
168
|
+
refY: 5,
|
|
169
|
+
markerWidth: 6,
|
|
170
|
+
markerHeight: 6,
|
|
171
|
+
orient: 'auto-start-reverse',
|
|
172
|
+
})
|
|
173
|
+
.child('path', { d: 'M 0 0 L 10 5 L 0 10 z', fill: theme_1.INK.line });
|
|
174
|
+
}
|
|
175
|
+
/** Draw a straight edge, optionally arrowed and/or dashed, with a label. */
|
|
176
|
+
function edge(parent, from, to, opts = {}) {
|
|
177
|
+
const el = line(parent, from.x, from.y, to.x, to.y, opts.dashed);
|
|
178
|
+
if (opts.arrow)
|
|
179
|
+
el.attr('marker-end', `url(#${opts.markerId ?? 'arrow'})`);
|
|
180
|
+
if (opts.label) {
|
|
181
|
+
text(parent, (from.x + to.x) / 2, (from.y + to.y) / 2 - theme_1.SPACE.xs, opts.label, {
|
|
182
|
+
size: theme_1.FONT.small,
|
|
183
|
+
fill: theme_1.INK.muted,
|
|
184
|
+
anchor: 'middle',
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return el;
|
|
188
|
+
}
|
|
189
|
+
/** Pack boxes into a grid, returning positions and the total canvas size. */
|
|
190
|
+
function gridPack(sizes, columns, gap = theme_1.SPACE.xl, origin = { x: theme_1.SPACE.xl, y: theme_1.SPACE.xl }) {
|
|
191
|
+
const cols = Math.max(1, columns);
|
|
192
|
+
const colWidth = sizes.length ? Math.max(...sizes.map((s) => s.w)) : 0;
|
|
193
|
+
const positions = [];
|
|
194
|
+
let rowTop = origin.y;
|
|
195
|
+
let rowHeight = 0;
|
|
196
|
+
sizes.forEach((s, i) => {
|
|
197
|
+
const col = i % cols;
|
|
198
|
+
if (col === 0 && i > 0) {
|
|
199
|
+
rowTop += rowHeight + gap;
|
|
200
|
+
rowHeight = 0;
|
|
201
|
+
}
|
|
202
|
+
positions.push({ x: origin.x + col * (colWidth + gap), y: rowTop });
|
|
203
|
+
rowHeight = Math.max(rowHeight, s.h);
|
|
204
|
+
});
|
|
205
|
+
const rows = Math.ceil(sizes.length / cols);
|
|
206
|
+
return {
|
|
207
|
+
positions,
|
|
208
|
+
width: origin.x * 2 + cols * colWidth + (cols - 1) * gap,
|
|
209
|
+
height: rowTop + rowHeight + origin.y,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/** Draw a title at the top of a document. Returns the y to continue from. */
|
|
213
|
+
function documentTitle(parent, x, y, title) {
|
|
214
|
+
text(parent, x, y + theme_1.FONT.title, title, { size: theme_1.FONT.title + 3, weight: 'bold' });
|
|
215
|
+
return y + theme_1.FONT.title + theme_1.SPACE.md;
|
|
216
|
+
}
|
|
217
|
+
/** Draw a footer line. Plain text, no separators or glyphs. */
|
|
218
|
+
function footer(parent, x, y, parts) {
|
|
219
|
+
return text(parent, x, y, parts.filter(Boolean).join(' '), {
|
|
220
|
+
size: theme_1.FONT.small,
|
|
221
|
+
fill: theme_1.INK.muted,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* A small DOM-backed SVG builder shared by every diagram generator.
|
|
3
3
|
*
|
|
4
4
|
* Diagrams are constructed against a real DOM document (via `@xmldom/xmldom`)
|
|
5
5
|
* using `createElement`/`setAttribute`/`appendChild`, then serialized once with
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
* values are escaped by the serializer, element nesting can't be malformed, and
|
|
8
8
|
* every generator shares one construction API.
|
|
9
9
|
*
|
|
10
|
-
* The `El` wrapper is a thin fluent facade over a DOM `Element`
|
|
11
|
-
* `.text()`, `.child()`
|
|
12
|
-
* underlying nodes remain inspectable
|
|
10
|
+
* The `El` wrapper is a thin fluent facade over a DOM `Element` - `.attr()`,
|
|
11
|
+
* `.text()`, `.child()` - so generator code reads declaratively while the
|
|
12
|
+
* underlying nodes remain inspectable and testable as real DOM.
|
|
13
|
+
*
|
|
14
|
+
* The gradient helper was removed with the move to a monochrome theme; nothing
|
|
15
|
+
* in the redesigned generators emits a gradient.
|
|
13
16
|
*/
|
|
14
17
|
export type AttrValue = string | number | undefined | null;
|
|
15
18
|
export type Attrs = Record<string, AttrValue>;
|
|
@@ -38,25 +41,10 @@ export declare class SvgDocument {
|
|
|
38
41
|
constructor(width: number, height: number, viewBox?: string);
|
|
39
42
|
/** Create a standalone element not yet attached to the tree. */
|
|
40
43
|
create(tag: string, attrs?: Attrs): El;
|
|
41
|
-
/**
|
|
42
|
-
* Embed a `<style>` block (inside <defs>) so browser renderers can resolve
|
|
43
|
-
* web fonts / CSS. Used by the Industry-styled generators to @import Barlow /
|
|
44
|
-
* Barlow Condensed / JetBrains Mono; non-browser renderers ignore it and fall
|
|
45
|
-
* back to the system fonts declared per family.
|
|
46
|
-
*/
|
|
44
|
+
/** Embed a `<style>` block inside <defs>. */
|
|
47
45
|
style(css: string): this;
|
|
48
46
|
/** Get (creating on first use) the shared <defs> block. */
|
|
49
47
|
defs(): El;
|
|
50
|
-
/**
|
|
51
|
-
* Convenience: add a linear gradient to <defs> and return its id.
|
|
52
|
-
* `stops` is a list of [offsetPercent, color] pairs.
|
|
53
|
-
*/
|
|
54
|
-
linearGradient(id: string, stops: Array<[number, string]>, opts?: {
|
|
55
|
-
x1?: number;
|
|
56
|
-
y1?: number;
|
|
57
|
-
x2?: number;
|
|
58
|
-
y2?: number;
|
|
59
|
-
}): string;
|
|
60
48
|
/** Serialize the whole document to an XML/SVG string (with XML prolog). */
|
|
61
49
|
toString(comment?: string): string;
|
|
62
50
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* A small DOM-backed SVG builder shared by every diagram generator.
|
|
4
4
|
*
|
|
5
5
|
* Diagrams are constructed against a real DOM document (via `@xmldom/xmldom`)
|
|
6
6
|
* using `createElement`/`setAttribute`/`appendChild`, then serialized once with
|
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
* values are escaped by the serializer, element nesting can't be malformed, and
|
|
9
9
|
* every generator shares one construction API.
|
|
10
10
|
*
|
|
11
|
-
* The `El` wrapper is a thin fluent facade over a DOM `Element`
|
|
12
|
-
* `.text()`, `.child()`
|
|
13
|
-
* underlying nodes remain inspectable
|
|
11
|
+
* The `El` wrapper is a thin fluent facade over a DOM `Element` - `.attr()`,
|
|
12
|
+
* `.text()`, `.child()` - so generator code reads declaratively while the
|
|
13
|
+
* underlying nodes remain inspectable and testable as real DOM.
|
|
14
|
+
*
|
|
15
|
+
* The gradient helper was removed with the move to a monochrome theme; nothing
|
|
16
|
+
* in the redesigned generators emits a gradient.
|
|
14
17
|
*/
|
|
15
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
19
|
exports.SvgDocument = exports.El = void 0;
|
|
@@ -74,12 +77,7 @@ class SvgDocument {
|
|
|
74
77
|
el.attrs(attrs);
|
|
75
78
|
return el;
|
|
76
79
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Embed a `<style>` block (inside <defs>) so browser renderers can resolve
|
|
79
|
-
* web fonts / CSS. Used by the Industry-styled generators to @import Barlow /
|
|
80
|
-
* Barlow Condensed / JetBrains Mono; non-browser renderers ignore it and fall
|
|
81
|
-
* back to the system fonts declared per family.
|
|
82
|
-
*/
|
|
80
|
+
/** Embed a `<style>` block inside <defs>. */
|
|
83
81
|
style(css) {
|
|
84
82
|
const s = this.defs().child('style', { type: 'text/css' });
|
|
85
83
|
s.node.appendChild(this.doc.createTextNode(css));
|
|
@@ -94,29 +92,23 @@ class SvgDocument {
|
|
|
94
92
|
}
|
|
95
93
|
return this._defs;
|
|
96
94
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Convenience: add a linear gradient to <defs> and return its id.
|
|
99
|
-
* `stops` is a list of [offsetPercent, color] pairs.
|
|
100
|
-
*/
|
|
101
|
-
linearGradient(id, stops, opts) {
|
|
102
|
-
const g = this.defs().child('linearGradient', {
|
|
103
|
-
id,
|
|
104
|
-
x1: opts?.x1 ?? 0,
|
|
105
|
-
y1: opts?.y1 ?? 0,
|
|
106
|
-
x2: opts?.x2 ?? 1,
|
|
107
|
-
y2: opts?.y2 ?? 1,
|
|
108
|
-
gradientUnits: 'objectBoundingBox',
|
|
109
|
-
});
|
|
110
|
-
for (const [offset, color] of stops) {
|
|
111
|
-
g.child('stop', { offset: `${offset}%`, 'stop-color': color });
|
|
112
|
-
}
|
|
113
|
-
return id;
|
|
114
|
-
}
|
|
115
95
|
/** Serialize the whole document to an XML/SVG string (with XML prolog). */
|
|
116
96
|
toString(comment) {
|
|
117
97
|
const body = new xmldom_1.XMLSerializer().serializeToString(this.doc);
|
|
118
98
|
const prolog = `<?xml version="1.0" encoding="UTF-8"?>`;
|
|
119
|
-
|
|
99
|
+
if (!comment)
|
|
100
|
+
return `${prolog}\n${body}`;
|
|
101
|
+
// The comment is concatenated outside the serializer, so it has to be made
|
|
102
|
+
// safe here. Caller-supplied text (a model name) reaches this, and an
|
|
103
|
+
// unescaped `&` or an embedded `--` produces a document that is not
|
|
104
|
+
// well-formed XML - which some SVG consumers reject outright.
|
|
105
|
+
const safe = comment
|
|
106
|
+
.replace(/&/g, '&')
|
|
107
|
+
.replace(/</g, '<')
|
|
108
|
+
.replace(/>/g, '>')
|
|
109
|
+
.replace(/-{2,}/g, '-')
|
|
110
|
+
.trim();
|
|
111
|
+
return `${prolog}\n<!-- ${safe} -->\n${body}`;
|
|
120
112
|
}
|
|
121
113
|
}
|
|
122
114
|
exports.SvgDocument = SvgDocument;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One theme, monochrome hairline.
|
|
3
|
+
*
|
|
4
|
+
* This replaces a 239-line palette module that carried nine accent palettes,
|
|
5
|
+
* three-stop gradient definitions, badge tint tables and a light/dark theme
|
|
6
|
+
* resolver. Diagrams are technical drawings: black on white, 1px rules, square
|
|
7
|
+
* corners, one font stack. They print, diff and embed predictably, and there is
|
|
8
|
+
* no colour to keep consistent across fifteen generators.
|
|
9
|
+
*
|
|
10
|
+
* The old `resolveAccent` / `resolveTheme` / `rotatedPalettes` entry points are
|
|
11
|
+
* kept as thin shims in ./legacy-palette so existing generators and callers
|
|
12
|
+
* keep compiling while they are converted.
|
|
13
|
+
*/
|
|
14
|
+
/** Ink, rules and fills. Every generator draws from these four values. */
|
|
15
|
+
export declare const INK: {
|
|
16
|
+
/** Text, borders, arrowheads. */
|
|
17
|
+
readonly line: "#000000";
|
|
18
|
+
/** Page and shape fill. */
|
|
19
|
+
readonly ground: "#ffffff";
|
|
20
|
+
/** Secondary text: types, counts, footers. */
|
|
21
|
+
readonly muted: "#666666";
|
|
22
|
+
/** Fill for header bars and emphasis rows. */
|
|
23
|
+
readonly wash: "#f0f0f0";
|
|
24
|
+
};
|
|
25
|
+
/** Stroke widths. Hairline everywhere; `heavy` only for emphasis. */
|
|
26
|
+
export declare const STROKE: {
|
|
27
|
+
readonly hair: 1;
|
|
28
|
+
readonly heavy: 2;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* One font stack, three sizes. No web-font import: diagrams should render the
|
|
32
|
+
* same offline and in a PDF pipeline, which a Google Fonts `@import` cannot
|
|
33
|
+
* guarantee.
|
|
34
|
+
*/
|
|
35
|
+
export declare const FONT: {
|
|
36
|
+
readonly family: "ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif";
|
|
37
|
+
readonly mono: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
38
|
+
readonly title: 13;
|
|
39
|
+
readonly body: 11;
|
|
40
|
+
readonly small: 9;
|
|
41
|
+
};
|
|
42
|
+
/** Spacing scale. Multiples of 4 keep everything on a grid. */
|
|
43
|
+
export declare const SPACE: {
|
|
44
|
+
readonly xs: 4;
|
|
45
|
+
readonly sm: 8;
|
|
46
|
+
readonly md: 12;
|
|
47
|
+
readonly lg: 16;
|
|
48
|
+
readonly xl: 24;
|
|
49
|
+
};
|
|
50
|
+
/** Row height for tabular content (field lists, columns, tasks). */
|
|
51
|
+
export declare const ROW_HEIGHT = 18;
|
|
52
|
+
/** The complete theme, for generators that prefer one object. */
|
|
53
|
+
export declare const THEME: {
|
|
54
|
+
readonly ink: {
|
|
55
|
+
/** Text, borders, arrowheads. */
|
|
56
|
+
readonly line: "#000000";
|
|
57
|
+
/** Page and shape fill. */
|
|
58
|
+
readonly ground: "#ffffff";
|
|
59
|
+
/** Secondary text: types, counts, footers. */
|
|
60
|
+
readonly muted: "#666666";
|
|
61
|
+
/** Fill for header bars and emphasis rows. */
|
|
62
|
+
readonly wash: "#f0f0f0";
|
|
63
|
+
};
|
|
64
|
+
readonly stroke: {
|
|
65
|
+
readonly hair: 1;
|
|
66
|
+
readonly heavy: 2;
|
|
67
|
+
};
|
|
68
|
+
readonly font: {
|
|
69
|
+
readonly family: "ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif";
|
|
70
|
+
readonly mono: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
71
|
+
readonly title: 13;
|
|
72
|
+
readonly body: 11;
|
|
73
|
+
readonly small: 9;
|
|
74
|
+
};
|
|
75
|
+
readonly space: {
|
|
76
|
+
readonly xs: 4;
|
|
77
|
+
readonly sm: 8;
|
|
78
|
+
readonly md: 12;
|
|
79
|
+
readonly lg: 16;
|
|
80
|
+
readonly xl: 24;
|
|
81
|
+
};
|
|
82
|
+
readonly rowHeight: 18;
|
|
83
|
+
};
|
|
84
|
+
export type Theme = typeof THEME;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* One theme, monochrome hairline.
|
|
4
|
+
*
|
|
5
|
+
* This replaces a 239-line palette module that carried nine accent palettes,
|
|
6
|
+
* three-stop gradient definitions, badge tint tables and a light/dark theme
|
|
7
|
+
* resolver. Diagrams are technical drawings: black on white, 1px rules, square
|
|
8
|
+
* corners, one font stack. They print, diff and embed predictably, and there is
|
|
9
|
+
* no colour to keep consistent across fifteen generators.
|
|
10
|
+
*
|
|
11
|
+
* The old `resolveAccent` / `resolveTheme` / `rotatedPalettes` entry points are
|
|
12
|
+
* kept as thin shims in ./legacy-palette so existing generators and callers
|
|
13
|
+
* keep compiling while they are converted.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.THEME = exports.ROW_HEIGHT = exports.SPACE = exports.FONT = exports.STROKE = exports.INK = void 0;
|
|
17
|
+
/** Ink, rules and fills. Every generator draws from these four values. */
|
|
18
|
+
exports.INK = {
|
|
19
|
+
/** Text, borders, arrowheads. */
|
|
20
|
+
line: '#000000',
|
|
21
|
+
/** Page and shape fill. */
|
|
22
|
+
ground: '#ffffff',
|
|
23
|
+
/** Secondary text: types, counts, footers. */
|
|
24
|
+
muted: '#666666',
|
|
25
|
+
/** Fill for header bars and emphasis rows. */
|
|
26
|
+
wash: '#f0f0f0',
|
|
27
|
+
};
|
|
28
|
+
/** Stroke widths. Hairline everywhere; `heavy` only for emphasis. */
|
|
29
|
+
exports.STROKE = {
|
|
30
|
+
hair: 1,
|
|
31
|
+
heavy: 2,
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* One font stack, three sizes. No web-font import: diagrams should render the
|
|
35
|
+
* same offline and in a PDF pipeline, which a Google Fonts `@import` cannot
|
|
36
|
+
* guarantee.
|
|
37
|
+
*/
|
|
38
|
+
exports.FONT = {
|
|
39
|
+
family: 'ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif',
|
|
40
|
+
mono: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',
|
|
41
|
+
title: 13,
|
|
42
|
+
body: 11,
|
|
43
|
+
small: 9,
|
|
44
|
+
};
|
|
45
|
+
/** Spacing scale. Multiples of 4 keep everything on a grid. */
|
|
46
|
+
exports.SPACE = {
|
|
47
|
+
xs: 4,
|
|
48
|
+
sm: 8,
|
|
49
|
+
md: 12,
|
|
50
|
+
lg: 16,
|
|
51
|
+
xl: 24,
|
|
52
|
+
};
|
|
53
|
+
/** Row height for tabular content (field lists, columns, tasks). */
|
|
54
|
+
exports.ROW_HEIGHT = 18;
|
|
55
|
+
/** The complete theme, for generators that prefer one object. */
|
|
56
|
+
exports.THEME = {
|
|
57
|
+
ink: exports.INK,
|
|
58
|
+
stroke: exports.STROKE,
|
|
59
|
+
font: exports.FONT,
|
|
60
|
+
space: exports.SPACE,
|
|
61
|
+
rowHeight: exports.ROW_HEIGHT,
|
|
62
|
+
};
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DependencyDiagram
|
|
2
|
+
* DependencyDiagram - renders a directed dependency graph of models/tables.
|
|
3
3
|
*
|
|
4
|
-
* Nodes are models/tables; a directed edge `from
|
|
4
|
+
* Nodes are models/tables; a directed edge `from -> to` means "from depends on
|
|
5
5
|
* to" (e.g. table `from` holds a foreign key into table `to`). The generator:
|
|
6
6
|
*
|
|
7
7
|
* - Computes a layered / topological layout: each node's layer is the longest
|
|
8
8
|
* dependency path to a leaf. Nodes with no dependencies sit in layer 0;
|
|
9
9
|
* their dependents fan out into higher layers.
|
|
10
10
|
* - Detects cycles (back edges) with a DFS colouring pass and visually flags
|
|
11
|
-
* the cyclic edges
|
|
12
|
-
* so a cycle can never send it into an infinite loop.
|
|
13
|
-
* - Draws each node as a labelled
|
|
11
|
+
* the cyclic edges with a heavier dashed stroke. The layering pass carries
|
|
12
|
+
* its own visited guard so a cycle can never send it into an infinite loop.
|
|
13
|
+
* - Draws each node as a labelled box sized to its label, with arrows
|
|
14
14
|
* between dependent boxes.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* (`light` | `dark`) drives the canvas + text colours. Both genuinely change
|
|
18
|
-
* real fill/stroke values in the emitted SVG. The viewBox auto-sizes to the
|
|
19
|
-
* computed layout.
|
|
16
|
+
* The viewBox auto-sizes to the computed layout.
|
|
20
17
|
*
|
|
21
18
|
* Usage:
|
|
22
19
|
* const d = new DependencyDiagram({ nodes, edges, title: 'Schema deps' });
|
|
@@ -36,8 +33,12 @@ export interface DependencyDiagramOptions {
|
|
|
36
33
|
nodes: DepNode[];
|
|
37
34
|
edges: DepEdge[];
|
|
38
35
|
title?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Accepted for backward compatibility and ignored: diagrams render in a
|
|
38
|
+
* single monochrome theme.
|
|
39
|
+
*/
|
|
39
40
|
theme?: 'light' | 'dark';
|
|
40
|
-
/**
|
|
41
|
+
/** Accepted for backward compatibility and ignored. */
|
|
41
42
|
color?: string;
|
|
42
43
|
direction?: 'horizontal' | 'vertical';
|
|
43
44
|
}
|
|
@@ -51,9 +52,8 @@ export declare class DependencyDiagram {
|
|
|
51
52
|
private static readonly MIN_NODE_W;
|
|
52
53
|
private static readonly LAYER_GAP;
|
|
53
54
|
private static readonly NODE_GAP;
|
|
54
|
-
private static readonly R;
|
|
55
55
|
constructor(options: DependencyDiagramOptions);
|
|
56
|
-
/** Adjacency: node
|
|
56
|
+
/** Adjacency: node -> the nodes it depends on (its outgoing edge targets). */
|
|
57
57
|
private buildAdjacency;
|
|
58
58
|
/**
|
|
59
59
|
* Assign each node a layer = longest dependency path length (0 for nodes with
|
|
@@ -62,16 +62,17 @@ export declare class DependencyDiagram {
|
|
|
62
62
|
*/
|
|
63
63
|
private computeLayers;
|
|
64
64
|
/**
|
|
65
|
-
* Detect cyclic edges via DFS colouring. Returns a set of "from
|
|
65
|
+
* Detect cyclic edges via DFS colouring. Returns a set of "from-to" keys that
|
|
66
66
|
* are back edges (participate in a cycle).
|
|
67
67
|
*/
|
|
68
68
|
private detectCyclicEdges;
|
|
69
69
|
private nodeWidth;
|
|
70
70
|
/**
|
|
71
71
|
* Point on the boundary of a rectangle along the line from the rect centre
|
|
72
|
-
* toward an external point
|
|
72
|
+
* toward an external point - used so arrowheads land on the box edge.
|
|
73
73
|
*/
|
|
74
74
|
private edgePoint;
|
|
75
|
+
private build;
|
|
75
76
|
generate(): string;
|
|
76
77
|
private place;
|
|
77
78
|
private defineArrow;
|