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.
Files changed (129) hide show
  1. package/CHANGELOG.md +209 -0
  2. package/README.md +32 -24
  3. package/dist/compliance/index.d.ts +2 -0
  4. package/dist/compliance/index.js +13 -1
  5. package/dist/connection-manager.js +13 -1
  6. package/dist/core/expressions.d.ts +58 -0
  7. package/dist/core/expressions.js +83 -0
  8. package/dist/core/hooks-manager.d.ts +179 -0
  9. package/dist/core/hooks-manager.js +291 -0
  10. package/dist/core/types.d.ts +235 -0
  11. package/dist/core/types.js +9 -0
  12. package/dist/decorators/index.d.ts +2 -0
  13. package/dist/decorators/index.js +11 -1
  14. package/dist/diagrams/chen-diagram.d.ts +15 -12
  15. package/dist/diagrams/chen-diagram.js +76 -85
  16. package/dist/diagrams/class-diagram.d.ts +9 -8
  17. package/dist/diagrams/class-diagram.js +60 -82
  18. package/dist/diagrams/core/index.d.ts +13 -0
  19. package/dist/diagrams/core/index.js +33 -0
  20. package/dist/diagrams/core/layout.d.ts +104 -0
  21. package/dist/diagrams/core/layout.js +223 -0
  22. package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
  23. package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
  24. package/dist/diagrams/core/theme.d.ts +84 -0
  25. package/dist/diagrams/core/theme.js +62 -0
  26. package/dist/diagrams/dependency-diagram.d.ts +15 -14
  27. package/dist/diagrams/dependency-diagram.js +71 -105
  28. package/dist/diagrams/er-diagram.d.ts +13 -26
  29. package/dist/diagrams/er-diagram.js +180 -259
  30. package/dist/diagrams/flow-diagram.d.ts +16 -11
  31. package/dist/diagrams/flow-diagram.js +96 -91
  32. package/dist/diagrams/gantt-diagram.d.ts +10 -5
  33. package/dist/diagrams/gantt-diagram.js +77 -103
  34. package/dist/diagrams/index-diagram.d.ts +10 -10
  35. package/dist/diagrams/index-diagram.js +106 -116
  36. package/dist/diagrams/index.d.ts +6 -9
  37. package/dist/diagrams/index.js +9 -24
  38. package/dist/diagrams/migration-diagram.d.ts +8 -4
  39. package/dist/diagrams/migration-diagram.js +189 -161
  40. package/dist/diagrams/model-diagram.d.ts +34 -34
  41. package/dist/diagrams/model-diagram.js +106 -485
  42. package/dist/diagrams/package-diagram.d.ts +9 -6
  43. package/dist/diagrams/package-diagram.js +64 -101
  44. package/dist/diagrams/relational-diagram.d.ts +12 -10
  45. package/dist/diagrams/relational-diagram.js +87 -114
  46. package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
  47. package/dist/diagrams/schemadoc-diagram.js +71 -93
  48. package/dist/diagrams/sequence-diagram.d.ts +10 -10
  49. package/dist/diagrams/sequence-diagram.js +64 -89
  50. package/dist/diagrams/state-diagram.d.ts +10 -9
  51. package/dist/diagrams/state-diagram.js +69 -92
  52. package/dist/diagrams/tree-diagram.d.ts +11 -5
  53. package/dist/diagrams/tree-diagram.js +41 -65
  54. package/dist/dialects/clickhouse/index.js +15 -0
  55. package/dist/dialects/cockroachdb/index.d.ts +1 -1
  56. package/dist/dialects/cockroachdb/index.js +32 -63
  57. package/dist/dialects/db2/index.js +23 -8
  58. package/dist/dialects/dialect.d.ts +29 -5
  59. package/dist/dialects/duckdb/index.js +9 -2
  60. package/dist/dialects/hana/index.js +22 -5
  61. package/dist/dialects/lock-clause-helper.d.ts +167 -0
  62. package/dist/dialects/lock-clause-helper.js +316 -0
  63. package/dist/dialects/mariadb/index.d.ts +7 -4
  64. package/dist/dialects/mariadb/index.js +36 -60
  65. package/dist/dialects/mssql/index.js +34 -3
  66. package/dist/dialects/mysql/index.d.ts +1 -1
  67. package/dist/dialects/mysql/index.js +17 -45
  68. package/dist/dialects/oracle/index.d.ts +14 -3
  69. package/dist/dialects/oracle/index.js +66 -36
  70. package/dist/dialects/order-expression-helper.d.ts +72 -0
  71. package/dist/dialects/order-expression-helper.js +154 -0
  72. package/dist/dialects/partial-index.d.ts +52 -0
  73. package/dist/dialects/partial-index.js +251 -0
  74. package/dist/dialects/postgres/index.d.ts +1 -1
  75. package/dist/dialects/postgres/index.js +43 -68
  76. package/dist/dialects/redshift/index.js +9 -2
  77. package/dist/dialects/snowflake/index.js +17 -0
  78. package/dist/dialects/spanner/index.js +7 -2
  79. package/dist/dialects/sqlite/driver.d.ts +55 -0
  80. package/dist/dialects/sqlite/driver.js +102 -0
  81. package/dist/dialects/sqlite/index.d.ts +1 -1
  82. package/dist/dialects/sqlite/index.js +49 -27
  83. package/dist/graph/base-graph-dialect.d.ts +24 -3
  84. package/dist/graph/base-graph-dialect.js +43 -2
  85. package/dist/graph/dgraph/index.js +6 -0
  86. package/dist/graph/gremlin/index.d.ts +6 -0
  87. package/dist/graph/gremlin/index.js +12 -1
  88. package/dist/graph/index.d.ts +1 -1
  89. package/dist/graph/neo4j/index.d.ts +2 -0
  90. package/dist/graph/neo4j/index.js +6 -1
  91. package/dist/graph/types.d.ts +12 -1
  92. package/dist/index.d.ts +13 -4
  93. package/dist/index.js +54 -7
  94. package/dist/logging/index.d.ts +10 -0
  95. package/dist/logging/index.js +23 -0
  96. package/dist/logging/query-logging.d.ts +82 -0
  97. package/dist/logging/query-logging.js +102 -0
  98. package/dist/models/decorators.d.ts +39 -3
  99. package/dist/models/decorators.js +74 -0
  100. package/dist/models/eager-load.d.ts +99 -0
  101. package/dist/models/eager-load.js +348 -5
  102. package/dist/models/indexes.d.ts +3 -2
  103. package/dist/models/indexes.js +7 -1
  104. package/dist/models/model.js +69 -43
  105. package/dist/prorm.d.ts +175 -409
  106. package/dist/prorm.js +1142 -557
  107. package/dist/query-builders/order-limit-builder.js +12 -10
  108. package/dist/query-builders/sql-compiler.d.ts +10 -3
  109. package/dist/query-builders/sql-compiler.js +14 -43
  110. package/dist/query-interface.d.ts +2 -1
  111. package/dist/sql-constants.d.ts +44 -0
  112. package/dist/sql-constants.js +138 -1
  113. package/dist/types/index.d.ts +53 -17
  114. package/dist/types/index.js +10 -15
  115. package/dist/types/query-types.d.ts +26 -0
  116. package/dist/types/query-types.js +30 -0
  117. package/package.json +32 -5
  118. package/dist/decorators/belongs-to-many.js +0 -115
  119. package/dist/decorators/belongs-to.js +0 -115
  120. package/dist/decorators/has-many.js +0 -127
  121. package/dist/decorators/has-one.js +0 -116
  122. package/dist/diagrams/palette.d.ts +0 -138
  123. package/dist/diagrams/palette.js +0 -194
  124. package/dist/hooks/hooks-manager.d.ts +0 -189
  125. package/dist/hooks/hooks-manager.js +0 -350
  126. package/dist/hooks/index.d.ts +0 -8
  127. package/dist/hooks/index.js +0 -37
  128. /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
  129. /package/dist/{logging.js → logging/logger.js} +0 -0
@@ -1,21 +1,17 @@
1
1
  /**
2
- * StateDiagram generates a UML state-machine diagram as an SVG.
2
+ * StateDiagram - generates a UML state-machine diagram as an SVG.
3
3
  *
4
4
  * Renders:
5
- * - normal states as rounded rectangles
6
- * - an initial pseudo-state as a filled black circle
5
+ * - normal states as square hairline boxes
6
+ * - an initial pseudo-state as a filled circle
7
7
  * - a final state as a ringed (double) circle
8
8
  * - transitions as arrows between states, labeled with their trigger/event
9
9
  * - self-transitions as loop arrows
10
10
  *
11
- * Great for showing a record lifecycle (e.g. draft active archived
11
+ * Great for showing a record lifecycle (e.g. draft -> active -> archived ->
12
12
  * deleted). States are auto-placed left-to-right in a wrapping grid unless
13
13
  * explicit x/y hints are supplied per state. The SVG viewBox is auto-sized.
14
14
  *
15
- * Both `--theme light|dark` and `--color <name|hex>` genuinely change the
16
- * output: the accent drives state fills + arrowheads, the theme drives the
17
- * canvas background, text and borders.
18
- *
19
15
  * Usage:
20
16
  * const diag = new StateDiagram({
21
17
  * states: [
@@ -56,8 +52,12 @@ export interface StateDiagramOptions {
56
52
  states: StateNode[];
57
53
  transitions: StateTransition[];
58
54
  title?: string;
55
+ /**
56
+ * Accepted for backward compatibility and ignored: diagrams render in a
57
+ * single monochrome theme.
58
+ */
59
59
  theme?: 'light' | 'dark';
60
- /** Custom accent color (named palette entry or hex). */
60
+ /** Accepted for backward compatibility and ignored. */
61
61
  color?: string;
62
62
  }
63
63
  export declare class StateDiagram {
@@ -74,6 +74,7 @@ export declare class StateDiagram {
74
74
  constructor(options: StateDiagramOptions);
75
75
  private layout;
76
76
  private edgePoint;
77
+ private build;
77
78
  generate(): string;
78
79
  private drawTransition;
79
80
  private drawSelfLoop;
@@ -1,22 +1,18 @@
1
1
  "use strict";
2
2
  /**
3
- * StateDiagram generates a UML state-machine diagram as an SVG.
3
+ * StateDiagram - generates a UML state-machine diagram as an SVG.
4
4
  *
5
5
  * Renders:
6
- * - normal states as rounded rectangles
7
- * - an initial pseudo-state as a filled black circle
6
+ * - normal states as square hairline boxes
7
+ * - an initial pseudo-state as a filled circle
8
8
  * - a final state as a ringed (double) circle
9
9
  * - transitions as arrows between states, labeled with their trigger/event
10
10
  * - self-transitions as loop arrows
11
11
  *
12
- * Great for showing a record lifecycle (e.g. draft active archived
12
+ * Great for showing a record lifecycle (e.g. draft -> active -> archived ->
13
13
  * deleted). States are auto-placed left-to-right in a wrapping grid unless
14
14
  * explicit x/y hints are supplied per state. The SVG viewBox is auto-sized.
15
15
  *
16
- * Both `--theme light|dark` and `--color <name|hex>` genuinely change the
17
- * output: the accent drives state fills + arrowheads, the theme drives the
18
- * canvas background, text and borders.
19
- *
20
16
  * Usage:
21
17
  * const diag = new StateDiagram({
22
18
  * states: [
@@ -73,18 +69,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
73
69
  exports.StateDiagram = void 0;
74
70
  const fs = __importStar(require("fs"));
75
71
  const path = __importStar(require("path"));
76
- const palette_1 = require("./palette");
77
- const svg_dom_1 = require("./svg-dom");
78
- // ─── Industry design system ────────────────────────────────────────────────
79
- // Barlow / JetBrains Mono typography, hairline borders and square "blueprint"
80
- // corners are fixed by the Industry spec; accent + surface colours still route
81
- // through resolveAccent / resolveTheme so --color / --theme keep working.
82
- const IND_FONT_HEAD = '"Barlow Condensed", system-ui, sans-serif';
83
- const IND_FONT_BODY = '"Barlow", system-ui, sans-serif';
84
- const IND_FONT_MONO = 'ui-monospace, "JetBrains Mono", "SF Mono", Menlo, monospace';
85
- const IND_HAIRLINE = 'rgba(29,31,32,0.16)';
86
- 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');";
87
- // ─── Main class ────────────────────────────────────────────────────────────
72
+ const svg_1 = require("./core/svg");
73
+ const theme_1 = require("./core/theme");
74
+ const layout_1 = require("./core/layout");
75
+ // -- Main class ----------------------------------------------------------------
88
76
  class StateDiagram {
89
77
  constructor(options) {
90
78
  this.opts = {
@@ -95,7 +83,7 @@ class StateDiagram {
95
83
  color: options.color ?? '',
96
84
  };
97
85
  }
98
- // ── Auto-place states in a wrapping row/grid (honoring x/y hints) ─────────
86
+ // -- Auto-place states in a wrapping row/grid (honoring x/y hints) ---------
99
87
  layout() {
100
88
  const { states } = this.opts;
101
89
  const PAD = StateDiagram.PAD;
@@ -131,7 +119,7 @@ class StateDiagram {
131
119
  const height = maxY + PAD;
132
120
  return { placed, width, height };
133
121
  }
134
- // ── Compute a point on the box perimeter toward a target point ────────────
122
+ // -- Compute a point on the box perimeter toward a target point ------------
135
123
  edgePoint(p, tx, ty) {
136
124
  const dx = tx - p.cx;
137
125
  const dy = ty - p.cy;
@@ -142,109 +130,94 @@ class StateDiagram {
142
130
  const s = Math.min(scaleX, scaleY);
143
131
  return { x: p.cx + dx * s, y: p.cy + dy * s };
144
132
  }
145
- // ── Generate full SVG string (built via a real DOM document) ──────────────
146
- generate() {
147
- const { title, theme, color } = this.opts;
148
- const accent = (0, palette_1.resolveAccent)(color);
149
- const t = (0, palette_1.resolveTheme)(theme);
133
+ // -- Build the SVG document -------------------------------------------------
134
+ build() {
135
+ const { title } = this.opts;
150
136
  const { placed, width, height } = this.layout();
151
137
  const PAD = StateDiagram.PAD;
152
- const R = StateDiagram.R;
153
- const doc = new svg_dom_1.SvgDocument(width, height);
138
+ const doc = new svg_1.SvgDocument(width, height);
154
139
  const svg = doc.root;
155
- // ── Background + embedded Industry web-fonts ────────────────────────
156
- svg.child('rect', { width, height, fill: t.canvasBg });
157
- svg.child('style').text(IND_FONT_IMPORT);
158
- // ── Defs: arrowhead marker (solid accent states — no gradient) ──────
159
- const marker = doc.defs().child('marker', {
160
- id: 'arrow',
161
- markerWidth: 10,
162
- markerHeight: 10,
163
- refX: 8,
164
- refY: 3,
165
- orient: 'auto',
166
- markerUnits: 'strokeWidth',
167
- });
168
- marker.child('path', { d: 'M0,0 L8,3 L0,6 Z', fill: accent.mid });
169
- // ── Title ───────────────────────────────────────────────────────────
140
+ svg.child('rect', { width, height, fill: theme_1.INK.ground });
141
+ // Defs: the single shared arrowhead marker.
142
+ (0, layout_1.defineArrowhead)(doc.defs(), 'arrow');
170
143
  if (title) {
171
144
  svg
172
145
  .child('text', {
173
146
  x: PAD,
174
147
  y: PAD + 8,
175
- 'font-family': IND_FONT_HEAD,
176
- 'font-size': 22,
177
- 'font-weight': 600,
178
- fill: t.textPrimary,
148
+ 'font-family': theme_1.FONT.family,
149
+ 'font-size': theme_1.FONT.title + 9,
150
+ 'font-weight': 'bold',
151
+ fill: theme_1.INK.line,
179
152
  })
180
153
  .text(title);
181
154
  }
182
- // ── Transitions (drawn first so states sit on top) ──────────────────
155
+ // Transitions, drawn first so states sit on top.
183
156
  this.opts.transitions.forEach((tr) => {
184
157
  const from = placed.get(tr.from);
185
158
  const to = placed.get(tr.to);
186
159
  if (!from || !to)
187
160
  return;
188
161
  if (tr.from === tr.to) {
189
- this.drawSelfLoop(svg, from, tr.event, accent.mid, t.textSecondary);
162
+ this.drawSelfLoop(svg, from, tr.event);
190
163
  }
191
164
  else {
192
- this.drawTransition(svg, from, to, tr.event, accent.mid, t.textSecondary);
165
+ this.drawTransition(svg, from, to, tr.event);
193
166
  }
194
167
  });
195
- // ── States ──────────────────────────────────────────────────────────
168
+ // States.
196
169
  placed.forEach((p) => {
197
170
  const node = p.node;
198
171
  if (node.initial) {
199
- // Filled black circle (initial pseudo-state).
172
+ // Filled circle (initial pseudo-state).
200
173
  svg.child('circle', {
201
174
  cx: p.cx,
202
175
  cy: p.cy,
203
176
  r: StateDiagram.PSEUDO_R,
204
- fill: '#1d1f20',
205
- stroke: t.border,
206
- 'stroke-width': 1,
177
+ fill: theme_1.INK.line,
178
+ stroke: theme_1.INK.line,
179
+ 'stroke-width': theme_1.STROKE.hair,
207
180
  });
208
181
  }
209
182
  else if (node.final) {
210
- // Ringed circle (final state): outer ring + filled accent core.
183
+ // Ringed circle (final state): outer ring + filled core.
211
184
  svg.child('circle', {
212
185
  cx: p.cx,
213
186
  cy: p.cy,
214
187
  r: StateDiagram.PSEUDO_R,
215
188
  fill: 'none',
216
- stroke: t.textPrimary,
217
- 'stroke-width': 2,
189
+ stroke: theme_1.INK.line,
190
+ 'stroke-width': theme_1.STROKE.heavy,
218
191
  });
219
192
  svg.child('circle', {
220
193
  cx: p.cx,
221
194
  cy: p.cy,
222
195
  r: StateDiagram.PSEUDO_R - 6,
223
- fill: accent.mid,
196
+ fill: theme_1.INK.line,
224
197
  });
225
198
  }
226
199
  else {
227
- // Normal state: square box with solid accent fill (blueprint).
200
+ // Normal state: square hairline box.
228
201
  svg.child('rect', {
229
202
  x: p.cx - p.hw,
230
203
  y: p.cy - p.hh,
231
204
  width: p.hw * 2,
232
205
  height: p.hh * 2,
233
- fill: accent.mid,
234
- stroke: accent.from,
235
- 'stroke-width': 1,
206
+ fill: theme_1.INK.wash,
207
+ stroke: theme_1.INK.line,
208
+ 'stroke-width': theme_1.STROKE.hair,
236
209
  });
237
210
  svg
238
211
  .child('text', {
239
212
  x: p.cx,
240
213
  y: p.cy + 5,
241
- 'font-family': IND_FONT_HEAD,
242
- 'font-size': 15,
243
- 'font-weight': 700,
244
- fill: '#FFFFFF',
214
+ 'font-family': theme_1.FONT.family,
215
+ 'font-size': theme_1.FONT.body + 2,
216
+ 'font-weight': 'bold',
217
+ fill: theme_1.INK.line,
245
218
  'text-anchor': 'middle',
246
219
  })
247
- .text(node.name);
220
+ .text((0, layout_1.truncate)(node.name, p.hw * 2 - 12, theme_1.FONT.body + 2));
248
221
  }
249
222
  // Label markers (initial/final) beneath the circle.
250
223
  if (node.initial || node.final) {
@@ -252,19 +225,22 @@ class StateDiagram {
252
225
  .child('text', {
253
226
  x: p.cx,
254
227
  y: p.cy + StateDiagram.PSEUDO_R + 16,
255
- 'font-family': IND_FONT_BODY,
256
- 'font-size': 11,
257
- 'font-weight': 600,
258
- fill: t.textSecondary,
228
+ 'font-family': theme_1.FONT.family,
229
+ 'font-size': theme_1.FONT.small + 2,
230
+ 'font-weight': 'bold',
231
+ fill: theme_1.INK.muted,
259
232
  'text-anchor': 'middle',
260
233
  })
261
234
  .text(node.name);
262
235
  }
263
236
  });
264
- return doc.toString('Generated by ts-prorm-orm StateDiagram');
237
+ return doc;
238
+ }
239
+ generate() {
240
+ return this.build().toString('Generated by ts-prorm-orm StateDiagram');
265
241
  }
266
- // ── Draw a straight transition arrow with an optional event label ─────────
267
- drawTransition(svg, from, to, event, stroke, labelColor) {
242
+ // -- Draw a straight transition arrow with an optional event label ---------
243
+ drawTransition(svg, from, to, event) {
268
244
  const start = this.edgePoint(from, to.cx, to.cy);
269
245
  const end = this.edgePoint(to, from.cx, from.cy);
270
246
  svg.child('line', {
@@ -272,18 +248,18 @@ class StateDiagram {
272
248
  y1: start.y,
273
249
  x2: end.x,
274
250
  y2: end.y,
275
- stroke,
276
- 'stroke-width': 2,
251
+ stroke: theme_1.INK.line,
252
+ 'stroke-width': theme_1.STROKE.heavy,
277
253
  'marker-end': 'url(#arrow)',
278
254
  });
279
255
  if (event) {
280
256
  const mx = (start.x + end.x) / 2;
281
257
  const my = (start.y + end.y) / 2;
282
- this.drawEventLabel(svg, mx, my - 6, event, labelColor);
258
+ this.drawEventLabel(svg, mx, my - 6, event);
283
259
  }
284
260
  }
285
- // ── Draw a self-transition loop arrow above the state ─────────────────────
286
- drawSelfLoop(svg, p, event, stroke, labelColor) {
261
+ // -- Draw a self-transition loop arrow above the state ---------------------
262
+ drawSelfLoop(svg, p, event) {
287
263
  const topY = p.cy - p.hh;
288
264
  const x1 = p.cx - p.hw * 0.4;
289
265
  const x2 = p.cx + p.hw * 0.4;
@@ -292,33 +268,34 @@ class StateDiagram {
292
268
  svg.child('path', {
293
269
  d,
294
270
  fill: 'none',
295
- stroke,
296
- 'stroke-width': 2,
271
+ stroke: theme_1.INK.line,
272
+ 'stroke-width': theme_1.STROKE.heavy,
297
273
  'marker-end': 'url(#arrow)',
298
274
  });
299
275
  if (event) {
300
- this.drawEventLabel(svg, p.cx, topY - loopH - 4, event, labelColor);
276
+ this.drawEventLabel(svg, p.cx, topY - loopH - 4, event);
301
277
  }
302
278
  }
303
- // ── Draw an event label with a subtle background pill for legibility ───────
304
- drawEventLabel(svg, x, y, event, color) {
279
+ // -- Draw an event label with a background pill for legibility -------------
280
+ drawEventLabel(svg, x, y, event) {
305
281
  const w = event.length * 7 + 12;
306
282
  svg.child('rect', {
307
283
  x: x - w / 2,
308
284
  y: y - 13,
309
285
  width: w,
310
286
  height: 18,
311
- fill: '#FFFFFF',
312
- opacity: 0.85,
287
+ fill: theme_1.INK.ground,
288
+ stroke: theme_1.INK.line,
289
+ 'stroke-width': theme_1.STROKE.hair,
313
290
  });
314
291
  svg
315
292
  .child('text', {
316
293
  x,
317
294
  y: y - 1,
318
- 'font-family': IND_FONT_MONO,
319
- 'font-size': 11,
320
- 'font-weight': 600,
321
- fill: color,
295
+ 'font-family': theme_1.FONT.mono,
296
+ 'font-size': theme_1.FONT.small + 2,
297
+ 'font-weight': 'bold',
298
+ fill: theme_1.INK.line,
322
299
  'text-anchor': 'middle',
323
300
  })
324
301
  .text(event);
@@ -1,18 +1,18 @@
1
1
  /**
2
- * TreeDiagram renders a recursive hierarchical tree / mind-map as SVG.
2
+ * TreeDiagram - renders a recursive hierarchical tree / mind-map as SVG.
3
3
  *
4
4
  * A `TreeNode` tree of arbitrary depth is laid out with a classic "tidy tree"
5
5
  * algorithm: each node's cross-axis span equals the number of its leaf
6
6
  * descendants, so siblings never overlap. The main axis is driven by depth
7
7
  * (columns for `horizontal`, rows for `vertical`). Parents connect to children
8
- * with smooth cubic-Bezier <path> connectors. Nodes are rounded label boxes,
9
- * colored by depth from a rotated accent palette; the canvas/text use the
10
- * light/dark theme.
8
+ * with cubic-Bezier <path> connectors. Nodes are square hairline label boxes;
9
+ * the root is distinguished with a heavier stroke and a wash fill.
11
10
  *
12
11
  * Usage:
13
12
  * const diag = new TreeDiagram({ root: { name: 'db', children: [...] } });
14
13
  * diag.save('./diagrams/tree.svg'); // or: diag.generate()
15
14
  */
15
+ import { measureText } from './core/layout';
16
16
  export interface TreeNode {
17
17
  name: string;
18
18
  children?: TreeNode[];
@@ -21,7 +21,12 @@ export interface TreeNode {
21
21
  export interface TreeDiagramOptions {
22
22
  root: TreeNode;
23
23
  title?: string;
24
+ /**
25
+ * Accepted for backward compatibility and ignored: diagrams render in a
26
+ * single monochrome theme.
27
+ */
24
28
  theme?: 'light' | 'dark';
29
+ /** Accepted for backward compatibility and ignored. */
25
30
  color?: string;
26
31
  direction?: 'horizontal' | 'vertical';
27
32
  }
@@ -29,7 +34,6 @@ export declare class TreeDiagram {
29
34
  private opts;
30
35
  private static readonly BOX_W;
31
36
  private static readonly BOX_H;
32
- private static readonly R;
33
37
  private static readonly PAD;
34
38
  private static readonly TITLE_H;
35
39
  /** Distance between successive depth columns/rows (center-to-center). */
@@ -40,8 +44,10 @@ export declare class TreeDiagram {
40
44
  private layout;
41
45
  private flatten;
42
46
  private connectorPath;
47
+ private build;
43
48
  generate(): string;
44
49
  /** Write the SVG to a file, creating parent directories as needed. */
45
50
  save(outputPath: string): string;
46
51
  }
47
52
  export default TreeDiagram;
53
+ export { measureText };
@@ -1,14 +1,13 @@
1
1
  "use strict";
2
2
  /**
3
- * TreeDiagram renders a recursive hierarchical tree / mind-map as SVG.
3
+ * TreeDiagram - renders a recursive hierarchical tree / mind-map as SVG.
4
4
  *
5
5
  * A `TreeNode` tree of arbitrary depth is laid out with a classic "tidy tree"
6
6
  * algorithm: each node's cross-axis span equals the number of its leaf
7
7
  * descendants, so siblings never overlap. The main axis is driven by depth
8
8
  * (columns for `horizontal`, rows for `vertical`). Parents connect to children
9
- * with smooth cubic-Bezier <path> connectors. Nodes are rounded label boxes,
10
- * colored by depth from a rotated accent palette; the canvas/text use the
11
- * light/dark theme.
9
+ * with cubic-Bezier <path> connectors. Nodes are square hairline label boxes;
10
+ * the root is distinguished with a heavier stroke and a wash fill.
12
11
  *
13
12
  * Usage:
14
13
  * const diag = new TreeDiagram({ root: { name: 'db', children: [...] } });
@@ -48,20 +47,13 @@ var __importStar = (this && this.__importStar) || (function () {
48
47
  };
49
48
  })();
50
49
  Object.defineProperty(exports, "__esModule", { value: true });
51
- exports.TreeDiagram = void 0;
50
+ exports.measureText = exports.TreeDiagram = void 0;
52
51
  const fs = __importStar(require("fs"));
53
52
  const path = __importStar(require("path"));
54
- const palette_1 = require("./palette");
55
- const svg_dom_1 = require("./svg-dom");
56
- // ─── Industry design system ────────────────────────────────────────────────
57
- // Barlow / JetBrains Mono typography, hairline borders and square "blueprint"
58
- // corners are fixed by the Industry spec; accent + surface colours still route
59
- // through resolveAccent / resolveTheme so --color / --theme keep working.
60
- const IND_FONT_HEAD = '"Barlow Condensed", system-ui, sans-serif';
61
- const IND_FONT_BODY = '"Barlow", system-ui, sans-serif';
62
- const IND_FONT_MONO = 'ui-monospace, "JetBrains Mono", "SF Mono", Menlo, monospace';
63
- const IND_HAIRLINE = 'rgba(29,31,32,0.16)';
64
- 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');";
53
+ const svg_1 = require("./core/svg");
54
+ const theme_1 = require("./core/theme");
55
+ const layout_1 = require("./core/layout");
56
+ Object.defineProperty(exports, "measureText", { enumerable: true, get: function () { return layout_1.measureText; } });
65
57
  class TreeDiagram {
66
58
  constructor(options) {
67
59
  this.opts = {
@@ -72,8 +64,8 @@ class TreeDiagram {
72
64
  ...options,
73
65
  };
74
66
  }
75
- // ── Recursive subtree-height layout ──────────────────────────────────────
76
- // A node's cross span = the sum of its leaf descendants. `nextLeaf` tracks
67
+ // -- Recursive subtree-height layout --------------------------------------
68
+ // A node's cross span = the sum of its leaf descendants. `cursor` tracks
77
69
  // the running leaf-slot cursor so siblings tile without overlap.
78
70
  layout(node, depth, cursor) {
79
71
  const kids = node.children ?? [];
@@ -93,7 +85,7 @@ class TreeDiagram {
93
85
  for (const c of n.children)
94
86
  this.flatten(c, out);
95
87
  }
96
- // ── Smooth cubic-Bezier connector between two centers ─────────────────────
88
+ // -- Cubic-Bezier connector between two centers ---------------------------
97
89
  connectorPath(parent, child, horizontal) {
98
90
  if (horizontal) {
99
91
  const x1 = parent.x + TreeDiagram.BOX_W / 2;
@@ -110,15 +102,11 @@ class TreeDiagram {
110
102
  const my = (y1 + y2) / 2;
111
103
  return `M ${x1} ${y1} C ${x1} ${my}, ${x2} ${my}, ${x2} ${y2}`;
112
104
  }
113
- generate() {
114
- const { root, title, theme, color, direction } = this.opts;
105
+ build() {
106
+ const { root, title, direction } = this.opts;
115
107
  const horizontal = direction !== 'vertical';
116
- const accent = (0, palette_1.resolveAccent)(color);
117
- const t = (0, palette_1.resolveTheme)(theme);
118
- const palettes = (0, palette_1.rotatedPalettes)(color);
119
108
  const BOX_W = TreeDiagram.BOX_W;
120
109
  const BOX_H = TreeDiagram.BOX_H;
121
- const R = TreeDiagram.R;
122
110
  const PAD = TreeDiagram.PAD;
123
111
  const DEPTH_GAP = TreeDiagram.DEPTH_GAP;
124
112
  const LEAF_GAP = TreeDiagram.LEAF_GAP;
@@ -129,7 +117,7 @@ class TreeDiagram {
129
117
  this.flatten(tree, nodes);
130
118
  const maxDepth = nodes.reduce((m, n) => Math.max(m, n.depth), 0);
131
119
  const totalLeaves = tree.leaves;
132
- // 2. Map abstract coords pixels.
120
+ // 2. Map abstract coords to pixels.
133
121
  const originX = PAD + BOX_W / 2;
134
122
  const originY = PAD + titleH + BOX_H / 2;
135
123
  for (const n of nodes) {
@@ -147,75 +135,62 @@ class TreeDiagram {
147
135
  // 3. Auto-size viewBox.
148
136
  const spanDepth = maxDepth * DEPTH_GAP;
149
137
  const spanCross = Math.max(0, totalLeaves - 1) * LEAF_GAP;
150
- const svgW = horizontal
151
- ? 2 * PAD + BOX_W + spanDepth
152
- : 2 * PAD + BOX_W + spanCross;
138
+ const svgW = horizontal ? 2 * PAD + BOX_W + spanDepth : 2 * PAD + BOX_W + spanCross;
153
139
  const svgH = horizontal
154
140
  ? 2 * PAD + titleH + BOX_H + spanCross
155
141
  : 2 * PAD + titleH + BOX_H + spanDepth;
156
- const doc = new svg_dom_1.SvgDocument(svgW, svgH);
142
+ const doc = new svg_1.SvgDocument(svgW, svgH);
157
143
  const svg = doc.root;
158
- // ── Background + embedded Industry web-fonts ──────────────────────────
159
- svg.child('rect', { width: svgW, height: svgH, fill: t.canvasBg });
160
- svg.child('style').text(IND_FONT_IMPORT);
161
- // ── Title ────────────────────────────────────────────────────────────
144
+ svg.child('rect', { width: svgW, height: svgH, fill: theme_1.INK.ground });
162
145
  if (title) {
163
146
  svg
164
147
  .child('text', {
165
148
  x: PAD,
166
149
  y: PAD + 24,
167
- 'font-family': IND_FONT_HEAD,
168
- 'font-size': 20,
169
- 'font-weight': 600,
170
- fill: t.textPrimary,
150
+ 'font-family': theme_1.FONT.family,
151
+ 'font-size': theme_1.FONT.title + 3,
152
+ 'font-weight': 'bold',
153
+ fill: theme_1.INK.line,
171
154
  })
172
155
  .text(title);
173
156
  }
174
- // ── Connectors (drawn first so boxes sit on top) ─────────────────────
157
+ // Connectors drawn first so boxes sit on top.
175
158
  const drawConnectors = (n) => {
176
- const depthPalette = palettes[(n.depth + 1) % palettes.length];
177
159
  for (const c of n.children) {
178
160
  svg.child('path', {
179
161
  d: this.connectorPath(n, c, horizontal),
180
162
  fill: 'none',
181
- stroke: depthPalette.mid,
182
- 'stroke-width': 1,
183
- 'stroke-opacity': 0.55,
184
- 'stroke-linecap': 'round',
163
+ stroke: theme_1.INK.line,
164
+ 'stroke-width': theme_1.STROKE.hair,
185
165
  });
186
166
  drawConnectors(c);
187
167
  }
188
168
  };
189
169
  drawConnectors(tree);
190
- // ── Node boxes ───────────────────────────────────────────────────────
170
+ // Node boxes: square hairline frames; the root gets a heavier stroke and
171
+ // a wash fill to stand out without introducing colour.
191
172
  for (const n of nodes) {
192
- const pal = palettes[n.depth % palettes.length];
193
173
  const x = n.x - BOX_W / 2;
194
174
  const y = n.y - BOX_H / 2;
195
- // Root box uses the primary accent's gradient-ish solid; deeper nodes use
196
- // their depth palette. `light`/`text` keep contrast readable per theme.
197
175
  const isRoot = n.depth === 0;
198
- const boxFill = isRoot ? accent.mid : pal.light;
199
- const boxStroke = isRoot ? accent.from : pal.mid;
200
- const labelFill = isRoot ? '#FFFFFF' : pal.text;
201
176
  svg.child('rect', {
202
177
  x,
203
178
  y,
204
179
  width: BOX_W,
205
180
  height: BOX_H,
206
- fill: boxFill,
207
- stroke: boxStroke,
208
- 'stroke-width': 1,
181
+ fill: isRoot ? theme_1.INK.wash : theme_1.INK.ground,
182
+ stroke: theme_1.INK.line,
183
+ 'stroke-width': isRoot ? theme_1.STROKE.heavy : theme_1.STROKE.hair,
209
184
  });
210
- const label = n.node.name.length > 20 ? n.node.name.slice(0, 19) + '…' : n.node.name;
185
+ const label = (0, layout_1.truncate)(n.node.name, BOX_W - theme_1.SPACE.lg, theme_1.FONT.body);
211
186
  svg
212
187
  .child('text', {
213
188
  x: n.x,
214
189
  y: n.y + (n.node.badge ? -1 : 5),
215
- 'font-family': IND_FONT_HEAD,
216
- 'font-size': 14,
217
- 'font-weight': 700,
218
- fill: labelFill,
190
+ 'font-family': theme_1.FONT.family,
191
+ 'font-size': theme_1.FONT.body,
192
+ 'font-weight': 'bold',
193
+ fill: theme_1.INK.line,
219
194
  'text-anchor': 'middle',
220
195
  })
221
196
  .text(label);
@@ -224,16 +199,18 @@ class TreeDiagram {
224
199
  .child('text', {
225
200
  x: n.x,
226
201
  y: n.y + 15,
227
- 'font-family': IND_FONT_MONO,
228
- 'font-size': 10,
229
- 'font-weight': 600,
230
- fill: isRoot ? 'rgba(255,255,255,0.8)' : pal.mid,
202
+ 'font-family': theme_1.FONT.mono,
203
+ 'font-size': theme_1.FONT.small,
204
+ fill: theme_1.INK.muted,
231
205
  'text-anchor': 'middle',
232
206
  })
233
207
  .text(n.node.badge);
234
208
  }
235
209
  }
236
- return doc.toString('Generated by ts-prorm-orm TreeDiagram');
210
+ return doc;
211
+ }
212
+ generate() {
213
+ return this.build().toString('Generated by ts-prorm-orm TreeDiagram');
237
214
  }
238
215
  /** Write the SVG to a file, creating parent directories as needed. */
239
216
  save(outputPath) {
@@ -249,7 +226,6 @@ exports.TreeDiagram = TreeDiagram;
249
226
  // Layout constants (px)
250
227
  TreeDiagram.BOX_W = 168;
251
228
  TreeDiagram.BOX_H = 46;
252
- TreeDiagram.R = 12;
253
229
  TreeDiagram.PAD = 40;
254
230
  TreeDiagram.TITLE_H = 44;
255
231
  /** Distance between successive depth columns/rows (center-to-center). */