ts-prorm-orm 1.2.3 → 2.1.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 +331 -1
- package/README.md +32 -24
- package/dist/compliance/data-classifier.d.ts +6 -0
- package/dist/compliance/data-classifier.js +6 -0
- package/dist/compliance/data-lineage.d.ts +4 -0
- package/dist/compliance/data-lineage.js +4 -0
- package/dist/compliance/data-masker.d.ts +4 -0
- package/dist/compliance/data-masker.js +4 -0
- package/dist/compliance/index.d.ts +4 -0
- package/dist/compliance/index.js +15 -1
- package/dist/compliance/pseudonymization.d.ts +4 -0
- package/dist/compliance/pseudonymization.js +4 -0
- package/dist/compliance/query-firewall.d.ts +9 -9
- package/dist/compliance/query-firewall.js +9 -9
- package/dist/compliance/rate-limiter.d.ts +4 -0
- package/dist/compliance/rate-limiter.js +4 -0
- package/dist/compliance/row-level-security.d.ts +2 -0
- package/dist/compliance/row-level-security.js +2 -0
- package/dist/compliance/security-decorator.d.ts +8 -0
- package/dist/compliance/security-decorator.js +8 -0
- package/dist/compliance/session-isolation.d.ts +4 -0
- package/dist/compliance/session-isolation.js +4 -0
- package/dist/compliance/worm-storage.d.ts +4 -0
- package/dist/compliance/worm-storage.js +4 -0
- 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/audit.d.ts +3 -1
- package/dist/decorators/audit.js +3 -1
- package/dist/decorators/check.d.ts +15 -15
- package/dist/decorators/check.js +15 -15
- package/dist/decorators/collate.d.ts +16 -0
- package/dist/decorators/collate.js +16 -0
- package/dist/decorators/comment.d.ts +3 -1
- package/dist/decorators/comment.js +3 -1
- package/dist/decorators/database-settings.d.ts +6 -0
- package/dist/decorators/database-settings.js +6 -0
- package/dist/decorators/default.d.ts +2 -0
- package/dist/decorators/default.js +2 -0
- package/dist/decorators/encryption.d.ts +7 -1
- package/dist/decorators/encryption.js +7 -1
- package/dist/decorators/engine.d.ts +4 -0
- package/dist/decorators/engine.js +4 -0
- package/dist/decorators/fk-constraints.d.ts +32 -32
- package/dist/decorators/fk-constraints.js +32 -32
- package/dist/decorators/foreign-table.d.ts +1 -1
- package/dist/decorators/generated.d.ts +8 -0
- package/dist/decorators/generated.js +8 -0
- package/dist/decorators/hstore.d.ts +6 -0
- package/dist/decorators/hstore.js +6 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.js +11 -1
- package/dist/decorators/json-column.d.ts +2 -0
- package/dist/decorators/json-column.js +2 -0
- package/dist/decorators/jsonb.d.ts +6 -0
- package/dist/decorators/jsonb.js +6 -0
- package/dist/decorators/permissions.d.ts +12 -0
- package/dist/decorators/permissions.js +12 -0
- package/dist/decorators/procedure.d.ts +4 -2
- package/dist/decorators/procedure.js +4 -2
- package/dist/decorators/query-options.d.ts +24 -0
- package/dist/decorators/query-options.js +24 -0
- package/dist/decorators/range.d.ts +8 -0
- package/dist/decorators/range.js +8 -0
- package/dist/decorators/set-column.d.ts +2 -0
- package/dist/decorators/set-column.js +2 -0
- package/dist/decorators/spatial.d.ts +2 -0
- package/dist/decorators/spatial.js +2 -0
- package/dist/decorators/storage.d.ts +24 -0
- package/dist/decorators/storage.js +24 -0
- package/dist/decorators/timezone.d.ts +7 -7
- package/dist/decorators/timezone.js +7 -7
- package/dist/decorators/trigger.d.ts +3 -1
- package/dist/decorators/trigger.js +3 -1
- package/dist/decorators/uuid.d.ts +6 -0
- package/dist/decorators/uuid.js +6 -0
- package/dist/decorators/view.d.ts +7 -1
- package/dist/decorators/view.js +7 -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 +141 -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/external-fields/decorator.d.ts +2 -0
- package/dist/external-fields/decorator.js +2 -0
- 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 +12 -3
- package/dist/index.js +53 -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/associations.d.ts +38 -0
- package/dist/models/associations.js +16 -0
- package/dist/models/decorators.d.ts +55 -19
- package/dist/models/decorators.js +95 -19
- 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 +1132 -553
- 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/schema-objects.d.ts +42 -0
- package/dist/schema-objects.js +28 -0
- package/dist/sql-constants.d.ts +44 -0
- package/dist/sql-constants.js +138 -1
- package/dist/types/index.d.ts +387 -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 +39 -8
- 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
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* SchemaDocDiagram
|
|
3
|
+
* SchemaDocDiagram - generates a print-friendly "data dictionary" / schema
|
|
4
4
|
* documentation sheet as SVG.
|
|
5
5
|
*
|
|
6
6
|
* Where ERDiagram / ModelDiagram render the *visual* shape of a schema, this
|
|
7
7
|
* generator renders the *reference* counterpart: for every table a titled
|
|
8
8
|
* section followed by a tabular grid with one row per column, listing
|
|
9
|
-
* Column
|
|
10
|
-
* zebra-striped and each grid's header row is painted in the accent color.
|
|
9
|
+
* Column, Type, Nullable, Key, Default, Description. Rows are zebra-striped.
|
|
11
10
|
* A document title banner and a summary line ("N tables, M columns") top the
|
|
12
11
|
* sheet.
|
|
13
12
|
*
|
|
14
|
-
* All markup is built against a real DOM document (see ./svg-dom) — never by
|
|
15
|
-
* concatenating strings — and both `--theme` and `--color` genuinely change
|
|
16
|
-
* fill/stroke values in the output.
|
|
17
|
-
*
|
|
18
13
|
* Usage:
|
|
19
14
|
* const doc = new SchemaDocDiagram({ tables: [...], title: 'My Schema' });
|
|
20
15
|
* doc.save('./diagrams/schema.svg');
|
|
@@ -58,9 +53,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
58
53
|
exports.SchemaDocDiagram = void 0;
|
|
59
54
|
const fs = __importStar(require("fs"));
|
|
60
55
|
const path = __importStar(require("path"));
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
56
|
+
const svg_1 = require("./core/svg");
|
|
57
|
+
const theme_1 = require("./core/theme");
|
|
58
|
+
const layout_1 = require("./core/layout");
|
|
59
|
+
// -- Layout constants (px) ---------------------------------------------------
|
|
64
60
|
const W = 820; // content width
|
|
65
61
|
const PAD = 28; // outer canvas padding
|
|
66
62
|
const BANNER_H = 78; // title banner height
|
|
@@ -69,7 +65,6 @@ const SECTION_TITLE_H = 40; // per-table section title bar
|
|
|
69
65
|
const COL_HDR_H = 30; // grid header row
|
|
70
66
|
const ROW_H = 28; // grid data row
|
|
71
67
|
const SECTION_GAP = 22; // space between tables
|
|
72
|
-
const R = 0; // border radius (blueprint = square corners)
|
|
73
68
|
// Column layout: [label, x offset, width]
|
|
74
69
|
const COLS = [
|
|
75
70
|
{ label: 'Column', x: 0, w: 170 },
|
|
@@ -79,20 +74,10 @@ const COLS = [
|
|
|
79
74
|
{ label: 'Default', x: 450, w: 130 },
|
|
80
75
|
{ label: 'Description', x: 580, w: 240 },
|
|
81
76
|
];
|
|
82
|
-
const FONT_SANS = palette_1.FONTS.body;
|
|
83
|
-
const FONT_HEAD = palette_1.FONTS.heading;
|
|
84
|
-
const FONT_MONO = palette_1.FONTS.mono;
|
|
85
|
-
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
86
77
|
/** Truncate text to roughly fit `width` px at the given font size. */
|
|
87
78
|
function truncate(text, width, fontSize) {
|
|
88
|
-
|
|
89
|
-
if (text.length <= maxChars)
|
|
90
|
-
return text;
|
|
91
|
-
if (maxChars <= 1)
|
|
92
|
-
return '…';
|
|
93
|
-
return text.slice(0, maxChars - 1) + '…';
|
|
79
|
+
return (0, layout_1.truncate)(text, width, fontSize);
|
|
94
80
|
}
|
|
95
|
-
// ─── Main class ────────────────────────────────────────────────────────────
|
|
96
81
|
class SchemaDocDiagram {
|
|
97
82
|
constructor(options) {
|
|
98
83
|
this.opts = {
|
|
@@ -110,11 +95,9 @@ class SchemaDocDiagram {
|
|
|
110
95
|
sectionHeight(table) {
|
|
111
96
|
return SECTION_TITLE_H + COL_HDR_H + (table.columns?.length ?? 0) * ROW_H;
|
|
112
97
|
}
|
|
113
|
-
|
|
114
|
-
const { tables, title
|
|
115
|
-
|
|
116
|
-
const t = (0, palette_1.resolveTheme)(theme);
|
|
117
|
-
// ── Compute total height (auto-size viewBox) ────────────────────────
|
|
98
|
+
build() {
|
|
99
|
+
const { tables, title } = this.opts;
|
|
100
|
+
// Compute total height (auto-size viewBox).
|
|
118
101
|
let contentH = BANNER_H + SUMMARY_H + 16;
|
|
119
102
|
tables.forEach((tbl, i) => {
|
|
120
103
|
contentH += this.sectionHeight(tbl);
|
|
@@ -124,43 +107,41 @@ class SchemaDocDiagram {
|
|
|
124
107
|
const svgW = W + 2 * PAD;
|
|
125
108
|
const svgH = contentH + 2 * PAD;
|
|
126
109
|
const cx = PAD;
|
|
127
|
-
const doc = new
|
|
110
|
+
const doc = new svg_1.SvgDocument(svgW, svgH);
|
|
128
111
|
const svg = doc.root;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// ── Canvas ground (theme) ───────────────────────────────────────────
|
|
132
|
-
svg.child('rect', { width: svgW, height: svgH, fill: t.canvasBg });
|
|
133
|
-
// ── Title banner (solid accent bar) ─────────────────────────────────
|
|
112
|
+
svg.child('rect', { width: svgW, height: svgH, fill: theme_1.INK.ground });
|
|
113
|
+
// Title banner.
|
|
134
114
|
svg.child('rect', {
|
|
135
115
|
x: cx,
|
|
136
116
|
y: PAD,
|
|
137
117
|
width: W,
|
|
138
118
|
height: BANNER_H,
|
|
139
|
-
|
|
140
|
-
|
|
119
|
+
fill: theme_1.INK.wash,
|
|
120
|
+
stroke: theme_1.INK.line,
|
|
121
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
141
122
|
});
|
|
142
123
|
svg
|
|
143
124
|
.child('text', {
|
|
144
125
|
x: cx + 22,
|
|
145
126
|
y: PAD + 36,
|
|
146
|
-
'font-family':
|
|
147
|
-
'font-size':
|
|
148
|
-
'font-weight':
|
|
149
|
-
fill:
|
|
127
|
+
'font-family': theme_1.FONT.family,
|
|
128
|
+
'font-size': theme_1.FONT.title + 11,
|
|
129
|
+
'font-weight': 'bold',
|
|
130
|
+
fill: theme_1.INK.line,
|
|
150
131
|
})
|
|
151
132
|
.text(truncate(title, W - 44, 24));
|
|
152
133
|
svg
|
|
153
134
|
.child('text', {
|
|
154
135
|
x: cx + 22,
|
|
155
136
|
y: PAD + 58,
|
|
156
|
-
'font-family':
|
|
157
|
-
'font-size':
|
|
158
|
-
'font-weight':
|
|
159
|
-
fill:
|
|
137
|
+
'font-family': theme_1.FONT.family,
|
|
138
|
+
'font-size': theme_1.FONT.small + 3,
|
|
139
|
+
'font-weight': 'bold',
|
|
140
|
+
fill: theme_1.INK.muted,
|
|
160
141
|
'letter-spacing': 1.4,
|
|
161
142
|
})
|
|
162
143
|
.text('DATA DICTIONARY');
|
|
163
|
-
//
|
|
144
|
+
// Summary line.
|
|
164
145
|
const summaryY = PAD + BANNER_H + 8;
|
|
165
146
|
const tableCount = tables.length;
|
|
166
147
|
const colCount = this.totalColumns();
|
|
@@ -168,51 +149,46 @@ class SchemaDocDiagram {
|
|
|
168
149
|
.child('text', {
|
|
169
150
|
x: cx + 4,
|
|
170
151
|
y: summaryY + 22,
|
|
171
|
-
'font-family':
|
|
172
|
-
'font-size':
|
|
173
|
-
'font-weight':
|
|
174
|
-
fill:
|
|
152
|
+
'font-family': theme_1.FONT.family,
|
|
153
|
+
'font-size': theme_1.FONT.body + 2,
|
|
154
|
+
'font-weight': 'bold',
|
|
155
|
+
fill: theme_1.INK.muted,
|
|
175
156
|
})
|
|
176
157
|
.text(`${tableCount} table${tableCount !== 1 ? 's' : ''}, ${colCount} column${colCount !== 1 ? 's' : ''}`);
|
|
177
|
-
//
|
|
158
|
+
// Table sections.
|
|
178
159
|
let y = summaryY + SUMMARY_H + 8;
|
|
179
160
|
tables.forEach((table) => {
|
|
180
|
-
y = this.drawTable(
|
|
161
|
+
y = this.drawTable(svg, table, cx, y);
|
|
181
162
|
y += SECTION_GAP;
|
|
182
163
|
});
|
|
183
|
-
return doc
|
|
164
|
+
return doc;
|
|
165
|
+
}
|
|
166
|
+
generate() {
|
|
167
|
+
return this.build().toString('Generated by ts-prorm-orm SchemaDocDiagram');
|
|
184
168
|
}
|
|
185
169
|
/** Draw one table section starting at `y`; returns the y after the section. */
|
|
186
|
-
drawTable(
|
|
170
|
+
drawTable(svg, table, cx, y) {
|
|
187
171
|
const columns = table.columns ?? [];
|
|
188
|
-
//
|
|
172
|
+
// Section title bar.
|
|
189
173
|
svg.child('rect', {
|
|
190
174
|
x: cx,
|
|
191
175
|
y,
|
|
192
176
|
width: W,
|
|
193
177
|
height: SECTION_TITLE_H,
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
svg.child('rect', {
|
|
198
|
-
x: cx,
|
|
199
|
-
y,
|
|
200
|
-
width: W,
|
|
201
|
-
height: SECTION_TITLE_H,
|
|
202
|
-
fill: 'none',
|
|
203
|
-
stroke: t.border,
|
|
204
|
-
'stroke-width': 1,
|
|
178
|
+
fill: theme_1.INK.wash,
|
|
179
|
+
stroke: theme_1.INK.line,
|
|
180
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
205
181
|
});
|
|
206
|
-
svg.child('rect', { x: cx, y, width: 4, height: SECTION_TITLE_H, fill:
|
|
182
|
+
svg.child('rect', { x: cx, y, width: 4, height: SECTION_TITLE_H, fill: theme_1.INK.line });
|
|
207
183
|
svg
|
|
208
184
|
.child('text', {
|
|
209
185
|
x: cx + 18,
|
|
210
186
|
y: y + 27,
|
|
211
|
-
'font-family':
|
|
212
|
-
'font-size':
|
|
213
|
-
'font-weight':
|
|
187
|
+
'font-family': theme_1.FONT.family,
|
|
188
|
+
'font-size': theme_1.FONT.title + 5,
|
|
189
|
+
'font-weight': 'bold',
|
|
214
190
|
'letter-spacing': 0.3,
|
|
215
|
-
fill:
|
|
191
|
+
fill: theme_1.INK.line,
|
|
216
192
|
})
|
|
217
193
|
.text(truncate(table.name, 420, 16));
|
|
218
194
|
if (table.comment) {
|
|
@@ -220,14 +196,14 @@ class SchemaDocDiagram {
|
|
|
220
196
|
.child('text', {
|
|
221
197
|
x: cx + W - 14,
|
|
222
198
|
y: y + 26,
|
|
223
|
-
'font-family':
|
|
224
|
-
'font-size':
|
|
225
|
-
fill:
|
|
199
|
+
'font-family': theme_1.FONT.family,
|
|
200
|
+
'font-size': theme_1.FONT.small + 2,
|
|
201
|
+
fill: theme_1.INK.muted,
|
|
226
202
|
'text-anchor': 'end',
|
|
227
203
|
})
|
|
228
204
|
.text(truncate(table.comment, 340, 11));
|
|
229
205
|
}
|
|
230
|
-
//
|
|
206
|
+
// Grid header row.
|
|
231
207
|
const gridX = cx;
|
|
232
208
|
let rowY = y + SECTION_TITLE_H;
|
|
233
209
|
svg.child('rect', {
|
|
@@ -235,25 +211,27 @@ class SchemaDocDiagram {
|
|
|
235
211
|
y: rowY,
|
|
236
212
|
width: W,
|
|
237
213
|
height: COL_HDR_H,
|
|
238
|
-
fill:
|
|
214
|
+
fill: theme_1.INK.wash,
|
|
215
|
+
stroke: theme_1.INK.line,
|
|
216
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
239
217
|
});
|
|
240
218
|
COLS.forEach((c) => {
|
|
241
219
|
svg
|
|
242
220
|
.child('text', {
|
|
243
221
|
x: gridX + c.x + 10,
|
|
244
222
|
y: rowY + 20,
|
|
245
|
-
'font-family':
|
|
246
|
-
'font-size':
|
|
247
|
-
'font-weight':
|
|
248
|
-
fill:
|
|
223
|
+
'font-family': theme_1.FONT.family,
|
|
224
|
+
'font-size': theme_1.FONT.small + 2,
|
|
225
|
+
'font-weight': 'bold',
|
|
226
|
+
fill: theme_1.INK.line,
|
|
249
227
|
'letter-spacing': 1,
|
|
250
228
|
})
|
|
251
229
|
.text(c.label.toUpperCase());
|
|
252
230
|
});
|
|
253
|
-
//
|
|
231
|
+
// Data rows (zebra).
|
|
254
232
|
rowY += COL_HDR_H;
|
|
255
233
|
columns.forEach((col, i) => {
|
|
256
|
-
const rowBg = i % 2 === 0 ?
|
|
234
|
+
const rowBg = i % 2 === 0 ? theme_1.INK.ground : theme_1.INK.wash;
|
|
257
235
|
svg.child('rect', { x: gridX, y: rowY, width: W, height: ROW_H, fill: rowBg });
|
|
258
236
|
const baseY = rowY + 18;
|
|
259
237
|
const cell = (idx, value, opts) => {
|
|
@@ -263,42 +241,42 @@ class SchemaDocDiagram {
|
|
|
263
241
|
.child('text', {
|
|
264
242
|
x: gridX + c.x + 10,
|
|
265
243
|
y: baseY,
|
|
266
|
-
'font-family': opts?.mono ?
|
|
244
|
+
'font-family': opts?.mono ? theme_1.FONT.mono : theme_1.FONT.family,
|
|
267
245
|
'font-size': fs,
|
|
268
|
-
fill: opts?.fill ??
|
|
246
|
+
fill: opts?.fill ?? theme_1.INK.line,
|
|
269
247
|
})
|
|
270
248
|
.text(truncate(value, c.w - 16, fs));
|
|
271
249
|
};
|
|
272
|
-
cell(0, col.name, { mono: true, fill:
|
|
273
|
-
cell(1, col.type, { mono: true, fill:
|
|
250
|
+
cell(0, col.name, { mono: true, fill: theme_1.INK.line });
|
|
251
|
+
cell(1, col.type, { mono: true, fill: theme_1.INK.muted });
|
|
274
252
|
cell(2, col.nullable === false ? 'NO' : 'YES', {
|
|
275
|
-
fill: col.nullable === false ?
|
|
253
|
+
fill: col.nullable === false ? theme_1.INK.line : theme_1.INK.muted,
|
|
276
254
|
});
|
|
277
|
-
cell(3, col.key ?? '', { mono: true, fill:
|
|
255
|
+
cell(3, col.key ?? '', { mono: true, fill: theme_1.INK.line });
|
|
278
256
|
cell(4, col.default != null ? String(col.default) : '', {
|
|
279
257
|
mono: true,
|
|
280
|
-
fill:
|
|
258
|
+
fill: theme_1.INK.muted,
|
|
281
259
|
});
|
|
282
|
-
cell(5, col.description ?? '', { fill:
|
|
260
|
+
cell(5, col.description ?? '', { fill: theme_1.INK.muted });
|
|
283
261
|
svg.child('line', {
|
|
284
262
|
x1: gridX,
|
|
285
263
|
y1: rowY + ROW_H,
|
|
286
264
|
x2: gridX + W,
|
|
287
265
|
y2: rowY + ROW_H,
|
|
288
|
-
stroke:
|
|
289
|
-
'stroke-width':
|
|
266
|
+
stroke: theme_1.INK.line,
|
|
267
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
290
268
|
});
|
|
291
269
|
rowY += ROW_H;
|
|
292
270
|
});
|
|
293
|
-
//
|
|
271
|
+
// Grid outline.
|
|
294
272
|
svg.child('rect', {
|
|
295
273
|
x: gridX,
|
|
296
274
|
y: y + SECTION_TITLE_H,
|
|
297
275
|
width: W,
|
|
298
276
|
height: COL_HDR_H + columns.length * ROW_H,
|
|
299
277
|
fill: 'none',
|
|
300
|
-
stroke:
|
|
301
|
-
'stroke-width':
|
|
278
|
+
stroke: theme_1.INK.line,
|
|
279
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
302
280
|
});
|
|
303
281
|
return y + this.sectionHeight(table);
|
|
304
282
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SequenceDiagram
|
|
2
|
+
* SequenceDiagram - generates a UML sequence diagram as an SVG.
|
|
3
3
|
*
|
|
4
4
|
* Renders participants (actors / objects / databases) as header boxes across
|
|
5
5
|
* the top, each dropping a vertical dashed lifeline. Messages are drawn as
|
|
@@ -7,13 +7,8 @@
|
|
|
7
7
|
* synchronous call, a dashed arrow is a return / async message. Activation
|
|
8
8
|
* bars (thin rectangles) are drawn on a lifeline while it is active.
|
|
9
9
|
*
|
|
10
|
-
* The accent color (via resolveAccent) drives participant header boxes and
|
|
11
|
-
* arrowheads; the theme (via resolveTheme) drives the canvas, lifelines and
|
|
12
|
-
* text. Both `theme` and `color` genuinely change fill/stroke values in the
|
|
13
|
-
* generated SVG. The viewBox is auto-sized to fit all content.
|
|
14
|
-
*
|
|
15
10
|
* Usage:
|
|
16
|
-
* const diag = new SequenceDiagram({ participants: [
|
|
11
|
+
* const diag = new SequenceDiagram({ participants: [...], messages: [...] });
|
|
17
12
|
* diag.save('./diagrams/flow.svg');
|
|
18
13
|
* // or:
|
|
19
14
|
* const svgString = diag.generate();
|
|
@@ -35,8 +30,12 @@ export interface SequenceDiagramOptions {
|
|
|
35
30
|
participants: SeqParticipant[];
|
|
36
31
|
messages: SeqMessage[];
|
|
37
32
|
title?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Accepted for backward compatibility and ignored: diagrams render in a
|
|
35
|
+
* single monochrome theme.
|
|
36
|
+
*/
|
|
38
37
|
theme?: 'light' | 'dark';
|
|
39
|
-
/**
|
|
38
|
+
/** Accepted for backward compatibility and ignored. */
|
|
40
39
|
color?: string;
|
|
41
40
|
}
|
|
42
41
|
export declare class SequenceDiagram {
|
|
@@ -51,8 +50,9 @@ export declare class SequenceDiagram {
|
|
|
51
50
|
private static readonly BOT_GAP;
|
|
52
51
|
private static readonly ACT_W;
|
|
53
52
|
constructor(options: SequenceDiagramOptions);
|
|
54
|
-
/**
|
|
55
|
-
private
|
|
53
|
+
/** Short ASCII kind label drawn inside a participant header. */
|
|
54
|
+
private kindLabel;
|
|
55
|
+
private build;
|
|
56
56
|
generate(): string;
|
|
57
57
|
/**
|
|
58
58
|
* Write the SVG to a file. Creates parent directories if needed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* SequenceDiagram
|
|
3
|
+
* SequenceDiagram - generates a UML sequence diagram as an SVG.
|
|
4
4
|
*
|
|
5
5
|
* Renders participants (actors / objects / databases) as header boxes across
|
|
6
6
|
* the top, each dropping a vertical dashed lifeline. Messages are drawn as
|
|
@@ -8,13 +8,8 @@
|
|
|
8
8
|
* synchronous call, a dashed arrow is a return / async message. Activation
|
|
9
9
|
* bars (thin rectangles) are drawn on a lifeline while it is active.
|
|
10
10
|
*
|
|
11
|
-
* The accent color (via resolveAccent) drives participant header boxes and
|
|
12
|
-
* arrowheads; the theme (via resolveTheme) drives the canvas, lifelines and
|
|
13
|
-
* text. Both `theme` and `color` genuinely change fill/stroke values in the
|
|
14
|
-
* generated SVG. The viewBox is auto-sized to fit all content.
|
|
15
|
-
*
|
|
16
11
|
* Usage:
|
|
17
|
-
* const diag = new SequenceDiagram({ participants: [
|
|
12
|
+
* const diag = new SequenceDiagram({ participants: [...], messages: [...] });
|
|
18
13
|
* diag.save('./diagrams/flow.svg');
|
|
19
14
|
* // or:
|
|
20
15
|
* const svgString = diag.generate();
|
|
@@ -56,18 +51,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
56
51
|
exports.SequenceDiagram = void 0;
|
|
57
52
|
const fs = __importStar(require("fs"));
|
|
58
53
|
const path = __importStar(require("path"));
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
// Barlow / JetBrains Mono typography, hairline borders and square "blueprint"
|
|
63
|
-
// corners are fixed by the Industry spec; accent + surface colours still route
|
|
64
|
-
// through resolveAccent / resolveTheme so --color / --theme keep working.
|
|
65
|
-
const IND_FONT_HEAD = '"Barlow Condensed", system-ui, sans-serif';
|
|
66
|
-
const IND_FONT_BODY = '"Barlow", system-ui, sans-serif';
|
|
67
|
-
const IND_FONT_MONO = 'ui-monospace, "JetBrains Mono", "SF Mono", Menlo, monospace';
|
|
68
|
-
const IND_HAIRLINE = 'rgba(29,31,32,0.16)';
|
|
69
|
-
const IND_FONT_IMPORT = "@import url('https://fonts.googleapis.com/css2?family=Barlow:wght@400;500;700&family=Barlow+Condensed:wght@400;600&family=JetBrains+Mono&display=swap');";
|
|
70
|
-
// ─── Main class ────────────────────────────────────────────────────────────
|
|
54
|
+
const svg_1 = require("./core/svg");
|
|
55
|
+
const theme_1 = require("./core/theme");
|
|
56
|
+
const layout_1 = require("./core/layout");
|
|
71
57
|
class SequenceDiagram {
|
|
72
58
|
constructor(options) {
|
|
73
59
|
this.opts = {
|
|
@@ -78,18 +64,16 @@ class SequenceDiagram {
|
|
|
78
64
|
color: options.color ?? '',
|
|
79
65
|
};
|
|
80
66
|
}
|
|
81
|
-
/**
|
|
82
|
-
|
|
67
|
+
/** Short ASCII kind label drawn inside a participant header. */
|
|
68
|
+
kindLabel(kind) {
|
|
83
69
|
if (kind === 'actor')
|
|
84
|
-
return '
|
|
70
|
+
return 'ACTOR';
|
|
85
71
|
if (kind === 'database')
|
|
86
|
-
return '
|
|
87
|
-
return '
|
|
72
|
+
return 'DB';
|
|
73
|
+
return 'OBJECT';
|
|
88
74
|
}
|
|
89
|
-
|
|
90
|
-
const { participants, messages, title
|
|
91
|
-
const accent = (0, palette_1.resolveAccent)(color);
|
|
92
|
-
const t = (0, palette_1.resolveTheme)(theme);
|
|
75
|
+
build() {
|
|
76
|
+
const { participants, messages, title } = this.opts;
|
|
93
77
|
const PAD = SequenceDiagram.PAD;
|
|
94
78
|
const LANE = SequenceDiagram.LANE;
|
|
95
79
|
const HDR_W = SequenceDiagram.HDR_W;
|
|
@@ -114,38 +98,25 @@ class SequenceDiagram {
|
|
|
114
98
|
const lifelineBottom = firstMsgY + m * MSG_GAP + BOT_GAP;
|
|
115
99
|
const svgW = PAD * 2 + HDR_W + (n - 1) * LANE;
|
|
116
100
|
const svgH = lifelineBottom + PAD;
|
|
117
|
-
const doc = new
|
|
101
|
+
const doc = new svg_1.SvgDocument(svgW, svgH);
|
|
118
102
|
const svg = doc.root;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// ── Arrowhead marker (accent-colored) ───────────────────────────────
|
|
123
|
-
const headId = `seqhead${accent.name.replace(/\W/g, '')}`;
|
|
124
|
-
const marker = doc.defs().child('marker', {
|
|
125
|
-
id: headId,
|
|
126
|
-
markerWidth: 10,
|
|
127
|
-
markerHeight: 10,
|
|
128
|
-
refX: 8,
|
|
129
|
-
refY: 4,
|
|
130
|
-
orient: 'auto',
|
|
131
|
-
markerUnits: 'userSpaceOnUse',
|
|
132
|
-
});
|
|
133
|
-
marker.child('path', { d: 'M0,0 L8,4 L0,8 Z', fill: accent.mid });
|
|
134
|
-
// ── Title ───────────────────────────────────────────────────────────
|
|
103
|
+
svg.child('rect', { width: svgW, height: svgH, fill: theme_1.INK.ground });
|
|
104
|
+
// Arrowhead marker, shared by all message arrows.
|
|
105
|
+
(0, layout_1.defineArrowhead)(doc.defs(), 'seqhead');
|
|
135
106
|
if (title) {
|
|
136
107
|
svg
|
|
137
108
|
.child('text', {
|
|
138
109
|
x: svgW / 2,
|
|
139
110
|
y: PAD + 24,
|
|
140
|
-
'font-family':
|
|
141
|
-
'font-size':
|
|
142
|
-
'font-weight':
|
|
143
|
-
fill:
|
|
111
|
+
'font-family': theme_1.FONT.family,
|
|
112
|
+
'font-size': theme_1.FONT.title + 3,
|
|
113
|
+
'font-weight': 'bold',
|
|
114
|
+
fill: theme_1.INK.line,
|
|
144
115
|
'text-anchor': 'middle',
|
|
145
116
|
})
|
|
146
117
|
.text(title);
|
|
147
118
|
}
|
|
148
|
-
//
|
|
119
|
+
// Lifelines (dashed).
|
|
149
120
|
participants.forEach((_p, i) => {
|
|
150
121
|
const x = laneX(i);
|
|
151
122
|
svg.child('line', {
|
|
@@ -153,32 +124,31 @@ class SequenceDiagram {
|
|
|
153
124
|
y1: headerBottom,
|
|
154
125
|
x2: x,
|
|
155
126
|
y2: lifelineBottom,
|
|
156
|
-
stroke:
|
|
157
|
-
'stroke-width':
|
|
127
|
+
stroke: theme_1.INK.line,
|
|
128
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
158
129
|
'stroke-dasharray': '6 5',
|
|
159
130
|
class: 'lifeline',
|
|
160
131
|
});
|
|
161
132
|
});
|
|
162
|
-
//
|
|
133
|
+
// Activation bars, drawn under the arrows so they sit on top of the edge.
|
|
163
134
|
messages.forEach((msg, i) => {
|
|
164
135
|
if (!msg.activate)
|
|
165
136
|
return;
|
|
166
137
|
const y = firstMsgY + i * MSG_GAP;
|
|
167
138
|
const x = laneX(indexOf(msg.to));
|
|
168
|
-
// Extend the bar to the next message (or to the lifeline end).
|
|
169
139
|
const endY = i + 1 < m ? firstMsgY + (i + 1) * MSG_GAP : y + MSG_GAP;
|
|
170
140
|
svg.child('rect', {
|
|
171
141
|
x: x - ACT_W / 2,
|
|
172
142
|
y,
|
|
173
143
|
width: ACT_W,
|
|
174
144
|
height: Math.max(endY - y, MSG_GAP / 2),
|
|
175
|
-
fill:
|
|
176
|
-
stroke:
|
|
177
|
-
'stroke-width':
|
|
145
|
+
fill: theme_1.INK.wash,
|
|
146
|
+
stroke: theme_1.INK.line,
|
|
147
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
178
148
|
class: 'activation',
|
|
179
149
|
});
|
|
180
150
|
});
|
|
181
|
-
//
|
|
151
|
+
// Participant header boxes.
|
|
182
152
|
participants.forEach((p, i) => {
|
|
183
153
|
const cxLine = laneX(i);
|
|
184
154
|
const boxX = cxLine - HDR_W / 2;
|
|
@@ -187,34 +157,34 @@ class SequenceDiagram {
|
|
|
187
157
|
y: headerTop,
|
|
188
158
|
width: HDR_W,
|
|
189
159
|
height: HDR_H,
|
|
190
|
-
fill:
|
|
191
|
-
stroke:
|
|
192
|
-
'stroke-width':
|
|
160
|
+
fill: theme_1.INK.wash,
|
|
161
|
+
stroke: theme_1.INK.line,
|
|
162
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
193
163
|
class: 'participant',
|
|
194
164
|
});
|
|
195
165
|
svg
|
|
196
166
|
.child('text', {
|
|
197
167
|
x: cxLine,
|
|
198
|
-
y: headerTop +
|
|
199
|
-
'font-family':
|
|
200
|
-
'font-size':
|
|
201
|
-
fill:
|
|
168
|
+
y: headerTop + 18,
|
|
169
|
+
'font-family': theme_1.FONT.mono,
|
|
170
|
+
'font-size': theme_1.FONT.small,
|
|
171
|
+
fill: theme_1.INK.muted,
|
|
202
172
|
'text-anchor': 'middle',
|
|
203
173
|
})
|
|
204
|
-
.text(this.
|
|
174
|
+
.text(this.kindLabel(p.kind));
|
|
205
175
|
svg
|
|
206
176
|
.child('text', {
|
|
207
177
|
x: cxLine,
|
|
208
|
-
y: headerTop +
|
|
209
|
-
'font-family':
|
|
210
|
-
'font-size':
|
|
211
|
-
'font-weight':
|
|
212
|
-
fill:
|
|
178
|
+
y: headerTop + 36,
|
|
179
|
+
'font-family': theme_1.FONT.family,
|
|
180
|
+
'font-size': theme_1.FONT.body,
|
|
181
|
+
'font-weight': 'bold',
|
|
182
|
+
fill: theme_1.INK.line,
|
|
213
183
|
'text-anchor': 'middle',
|
|
214
184
|
})
|
|
215
|
-
.text(
|
|
185
|
+
.text((0, layout_1.truncate)(p.name, HDR_W - 12, theme_1.FONT.body));
|
|
216
186
|
});
|
|
217
|
-
//
|
|
187
|
+
// Messages (numbered arrows).
|
|
218
188
|
messages.forEach((msg, i) => {
|
|
219
189
|
const y = firstMsgY + i * MSG_GAP;
|
|
220
190
|
const fromI = indexOf(msg.from);
|
|
@@ -235,10 +205,10 @@ class SequenceDiagram {
|
|
|
235
205
|
svg.child('path', {
|
|
236
206
|
d: `M${x1},${y} h${w} v${yb - y} h-${w}`,
|
|
237
207
|
fill: 'none',
|
|
238
|
-
stroke:
|
|
239
|
-
'stroke-width':
|
|
208
|
+
stroke: theme_1.INK.line,
|
|
209
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
240
210
|
'stroke-dasharray': isReturn ? '5 4' : undefined,
|
|
241
|
-
'marker-end':
|
|
211
|
+
'marker-end': 'url(#seqhead)',
|
|
242
212
|
class: isReturn ? 'message message-return' : 'message message-call',
|
|
243
213
|
});
|
|
244
214
|
}
|
|
@@ -248,10 +218,10 @@ class SequenceDiagram {
|
|
|
248
218
|
y1: y,
|
|
249
219
|
x2,
|
|
250
220
|
y2: y,
|
|
251
|
-
stroke:
|
|
252
|
-
'stroke-width':
|
|
221
|
+
stroke: theme_1.INK.line,
|
|
222
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
253
223
|
'stroke-dasharray': isReturn ? '5 4' : undefined,
|
|
254
|
-
'marker-end':
|
|
224
|
+
'marker-end': 'url(#seqhead)',
|
|
255
225
|
class: isReturn ? 'message message-return' : 'message message-call',
|
|
256
226
|
});
|
|
257
227
|
}
|
|
@@ -261,17 +231,19 @@ class SequenceDiagram {
|
|
|
261
231
|
cx: badgeX,
|
|
262
232
|
cy: y - 12,
|
|
263
233
|
r: 9,
|
|
264
|
-
fill:
|
|
234
|
+
fill: theme_1.INK.ground,
|
|
235
|
+
stroke: theme_1.INK.line,
|
|
236
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
265
237
|
class: 'seq-num',
|
|
266
238
|
});
|
|
267
239
|
svg
|
|
268
240
|
.child('text', {
|
|
269
241
|
x: badgeX,
|
|
270
242
|
y: y - 8,
|
|
271
|
-
'font-family':
|
|
272
|
-
'font-size':
|
|
273
|
-
'font-weight':
|
|
274
|
-
fill:
|
|
243
|
+
'font-family': theme_1.FONT.mono,
|
|
244
|
+
'font-size': theme_1.FONT.small,
|
|
245
|
+
'font-weight': 'bold',
|
|
246
|
+
fill: theme_1.INK.line,
|
|
275
247
|
'text-anchor': 'middle',
|
|
276
248
|
})
|
|
277
249
|
.text(i + 1);
|
|
@@ -281,15 +253,18 @@ class SequenceDiagram {
|
|
|
281
253
|
.child('text', {
|
|
282
254
|
x: fromI === toI ? x1 + 66 : midX,
|
|
283
255
|
y: y - 8,
|
|
284
|
-
'font-family':
|
|
285
|
-
'font-size':
|
|
286
|
-
'font-weight':
|
|
287
|
-
fill:
|
|
256
|
+
'font-family': theme_1.FONT.family,
|
|
257
|
+
'font-size': theme_1.FONT.small + 1,
|
|
258
|
+
'font-weight': 'bold',
|
|
259
|
+
fill: theme_1.INK.line,
|
|
288
260
|
'text-anchor': fromI === toI ? 'start' : 'middle',
|
|
289
261
|
})
|
|
290
262
|
.text(msg.label);
|
|
291
263
|
});
|
|
292
|
-
return doc
|
|
264
|
+
return doc;
|
|
265
|
+
}
|
|
266
|
+
generate() {
|
|
267
|
+
return this.build().toString('Generated by ts-prorm-orm SequenceDiagram');
|
|
293
268
|
}
|
|
294
269
|
/**
|
|
295
270
|
* Write the SVG to a file. Creates parent directories if needed.
|