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
|
@@ -55,3 +55,5 @@ export { HStore, getHStoreMetadata, getAllHStoreMetadata, isHStoreColumn, clearH
|
|
|
55
55
|
export type { HStoreDecoratorOptions, HStoreMetadata } from './hstore';
|
|
56
56
|
export { Range, getRangeMetadata, getAllRangeMetadata, isRangeColumn, clearRangeMetadata, buildRangeLiteral, getRangeContainedBySQL, getRangeOverlapSQL, } from './range';
|
|
57
57
|
export type { RangeSubtype, RangeDecoratorOptions, RangeMetadata } from './range';
|
|
58
|
+
export { Audit, getAuditLog, clearAuditLog, getAuditOptions } from './audit';
|
|
59
|
+
export type { AuditOptions, AuditEntry } from './audit';
|
package/dist/decorators/index.js
CHANGED
|
@@ -15,7 +15,7 @@ exports.generateIndexCommentSQL = exports.generateCommentSQL = exports.getAllCon
|
|
|
15
15
|
exports.getIdentityMetadataForeignKey = exports.getAllAutoIncrementMetadata = exports.getAutoIncrementMetadata = exports.getAllUniqueMetadata = exports.getUniqueMetadata = exports.getAllForeignKeyMetadata = exports.getForeignKeyMetadata = exports.Exclusion = exports.GeneratedAlways = exports.IdentityDecorator = exports.AutoIncrement = exports.Unique = exports.Deferrable = exports.References = exports.OnUpdate = exports.OnDelete = exports.applyTimezoneHooks = exports.convertInstanceOnWrite = exports.convertInstanceOnRead = exports.getAllTimezoneFields = exports.getDefaultTimezone = exports.getTableTimezone = exports.getTimezoneForField = exports.getTimezoneFields = exports.getEffectiveTimezone = exports.convertWhereToTimezone = exports.applyTimezoneToQuery = exports.convertOnWrite = exports.convertOnRead = exports.parseDate = exports.formatDateTimezone = exports.convertFromTimezone = exports.convertToTimezone = exports.resolveTimezoneFromContext = exports.clearTimezoneContext = exports.getTimezoneContext = exports.setTimezoneContext = exports.TimezoneEnum = exports.Timezone = exports.computedDefault = exports.randomIntDefault = exports.nowDefault = exports.uuidDefault = exports.applyDefaultHooks = exports.applyDefaultValues = exports.toPrormDefault = exports.getDefaultForField = exports.getDefaultFields = exports.Default = exports.generateConstraintCommentSQL = void 0;
|
|
16
16
|
exports.WithLock = exports.DistinctOn = exports.Distinct = exports.Tablesample = exports.IgnoreIndex = exports.ForceIndex = exports.UseIndex = exports.generatePartitionBoundSQL = exports.generatePartitionSQL = exports.getPartitionOptions = exports.Partition = exports.generateInheritsSQL = exports.generateStatisticsSQL = exports.generateReplicaIdentitySQL = exports.generateCompressionSQL = exports.generateClusteredSQL = exports.generateTablespaceSQL = exports.generateStorageSQL = exports.getColumnStorageOptions = exports.getInheritsOptions = exports.getOnCommitOption = exports.getStatisticsOptions = exports.getReplicaIdentityOptions = exports.getCompressionOptions = exports.getClusteredOptions = exports.getTablespaceOptions = exports.getStorageOptions = exports.ColumnStorage = exports.Inherits = exports.OnCommit = exports.Statistics = exports.ReplicaIdentity = exports.Compression = exports.Clustered = exports.TablespaceOptionsFn = exports.Tablespace = exports.Storage = exports.buildExclusionSQL = exports.buildGeneratedAlwaysSQL = exports.buildIdentitySQL = exports.buildAutoIncrementSQL = exports.buildDeferrableSQL = exports.buildReferencesSQL = exports.buildOnUpdateSQL = exports.buildOnDeleteSQL = exports.getAllExclusionMetadata = exports.getExclusionMetadata = exports.getAllGeneratedAlwaysMetadata = exports.getGeneratedAlwaysMetadata = exports.getAllIdentityMetadataForeignKey = void 0;
|
|
17
17
|
exports.isJSONBColumn = exports.getAllJSONBMetadata = exports.getJSONBMetadata = exports.JSONB = exports.buildUUIDDefaultSQL = exports.getUUIDExtensionSQL = exports.clearUUIDMetadata = exports.isUUIDColumn = exports.getAllUUIDMetadata = exports.getUUIDMetadata = exports.UUID = exports.generateSetFindInSetSQL = exports.isSetColumn = exports.getAllSetColumnMetadata = exports.getSetColumnMetadata = exports.SetColumnWithOptions = exports.SetColumn = exports.generateJSONRemoveSQL = exports.generateJSONSetSQL = exports.generateJSONExtractSQL = exports.isJSONColumn = exports.getAllJSONColumnMetadata = exports.getJSONColumnMetadata = exports.JSONColumn = exports.generateSpatialIndexSQL = exports.isSpatialColumn = exports.getAllSpatialMetadata = exports.getSpatialMetadata = exports.Spatial = exports.generateCursorSQL = exports.generateDistinctOnSQL = exports.generateTablesampleSQL = exports.generateIdleInTransactionTimeoutSQL = exports.generateStatementTimeoutSQL = exports.generateLockSQL = exports.generateIndexHintSQL = exports.isDistinctEnabled = exports.getTablesampleOptions = exports.getDistinctOnColumns = exports.getFetchOptions = exports.getCursorOptions = exports.getIdleInTransactionTimeout = exports.getStatementTimeout = exports.getLockOptions = exports.getQueryHints = exports.FetchWith = exports.Fetch = exports.Cursor = exports.IdleInTransactionTimeout = exports.StatementTimeout = void 0;
|
|
18
|
-
exports.getRangeOverlapSQL = exports.getRangeContainedBySQL = exports.buildRangeLiteral = exports.clearRangeMetadata = exports.isRangeColumn = exports.getAllRangeMetadata = exports.getRangeMetadata = exports.Range = exports.buildHStoreDefaultSQL = exports.getHStoreExtensionSQL = exports.clearHStoreMetadata = exports.isHStoreColumn = exports.getAllHStoreMetadata = exports.getHStoreMetadata = exports.HStore = exports.clearJSONBMetadata = void 0;
|
|
18
|
+
exports.getAuditOptions = exports.clearAuditLog = exports.getAuditLog = exports.Audit = exports.getRangeOverlapSQL = exports.getRangeContainedBySQL = exports.buildRangeLiteral = exports.clearRangeMetadata = exports.isRangeColumn = exports.getAllRangeMetadata = exports.getRangeMetadata = exports.Range = exports.buildHStoreDefaultSQL = exports.getHStoreExtensionSQL = exports.clearHStoreMetadata = exports.isHStoreColumn = exports.getAllHStoreMetadata = exports.getHStoreMetadata = exports.HStore = exports.clearJSONBMetadata = void 0;
|
|
19
19
|
// ── Encryption ─────────────────────────────────────────────────────────────
|
|
20
20
|
var encryption_1 = require("./encryption");
|
|
21
21
|
Object.defineProperty(exports, "Secure", { enumerable: true, get: function () { return encryption_1.Secure; } });
|
|
@@ -337,3 +337,13 @@ Object.defineProperty(exports, "clearRangeMetadata", { enumerable: true, get: fu
|
|
|
337
337
|
Object.defineProperty(exports, "buildRangeLiteral", { enumerable: true, get: function () { return range_1.buildRangeLiteral; } });
|
|
338
338
|
Object.defineProperty(exports, "getRangeContainedBySQL", { enumerable: true, get: function () { return range_1.getRangeContainedBySQL; } });
|
|
339
339
|
Object.defineProperty(exports, "getRangeOverlapSQL", { enumerable: true, get: function () { return range_1.getRangeOverlapSQL; } });
|
|
340
|
+
// ── Audit ───────────────────────────────────────────────────────────────────
|
|
341
|
+
// The @Audit class decorator and its in-memory change log. Distinct from
|
|
342
|
+
// `src/audit/**` (AuditLogger — persists model changes to a database table)
|
|
343
|
+
// and from `ComplianceAuditTrail` in `src/compliance/**`; this one records
|
|
344
|
+
// decorated-model mutations in memory for inspection during a process.
|
|
345
|
+
var audit_1 = require("./audit");
|
|
346
|
+
Object.defineProperty(exports, "Audit", { enumerable: true, get: function () { return audit_1.Audit; } });
|
|
347
|
+
Object.defineProperty(exports, "getAuditLog", { enumerable: true, get: function () { return audit_1.getAuditLog; } });
|
|
348
|
+
Object.defineProperty(exports, "clearAuditLog", { enumerable: true, get: function () { return audit_1.clearAuditLog; } });
|
|
349
|
+
Object.defineProperty(exports, "getAuditOptions", { enumerable: true, get: function () { return audit_1.getAuditOptions; } });
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ChenDiagram
|
|
3
|
-
* as SVG, built against a real DOM document
|
|
4
|
-
* concatenated markup.
|
|
2
|
+
* ChenDiagram - renders a classic Chen-notation Entity-Relationship diagram
|
|
3
|
+
* as SVG, built against a real DOM document rather than concatenated markup.
|
|
5
4
|
*
|
|
6
5
|
* Chen notation (distinct from crow's-foot):
|
|
7
|
-
* - Entities
|
|
8
|
-
* - Relationships
|
|
9
|
-
*
|
|
10
|
-
* - Attributes
|
|
11
|
-
*
|
|
12
|
-
*
|
|
6
|
+
* - Entities -> rectangles (weak entities get a double border)
|
|
7
|
+
* - Relationships -> diamonds placed between the two entities they connect,
|
|
8
|
+
* with cardinality labels (1, N, M) on the connecting lines
|
|
9
|
+
* - Attributes -> ellipses connected to their entity by a line; key
|
|
10
|
+
* attributes have underlined text, multivalued get a
|
|
11
|
+
* double ellipse, derived get a dashed ellipse.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
* entities/diamonds) via resolveTheme/resolveAccent, so both flags change the
|
|
16
|
-
* generated output. The viewBox is auto-sized to the laid-out geometry.
|
|
13
|
+
* The viewBox is auto-sized to the laid-out geometry.
|
|
17
14
|
*
|
|
18
15
|
* Usage:
|
|
19
16
|
* const diag = new ChenDiagram({ entities: [...], relationships: [...] });
|
|
@@ -41,7 +38,12 @@ export interface ChenDiagramOptions {
|
|
|
41
38
|
entities: ChenEntity[];
|
|
42
39
|
relationships?: ChenRelationship[];
|
|
43
40
|
title?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Accepted for backward compatibility and ignored: diagrams render in a
|
|
43
|
+
* single monochrome theme.
|
|
44
|
+
*/
|
|
44
45
|
theme?: 'light' | 'dark';
|
|
46
|
+
/** Accepted for backward compatibility and ignored. */
|
|
45
47
|
color?: string;
|
|
46
48
|
}
|
|
47
49
|
export declare class ChenDiagram {
|
|
@@ -62,6 +64,7 @@ export declare class ChenDiagram {
|
|
|
62
64
|
private drawAttribute;
|
|
63
65
|
private drawEntity;
|
|
64
66
|
private drawRelationship;
|
|
67
|
+
private build;
|
|
65
68
|
generate(): string;
|
|
66
69
|
/**
|
|
67
70
|
* Write the SVG to a file. Creates parent directories if needed.
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* ChenDiagram
|
|
4
|
-
* as SVG, built against a real DOM document
|
|
5
|
-
* concatenated markup.
|
|
3
|
+
* ChenDiagram - renders a classic Chen-notation Entity-Relationship diagram
|
|
4
|
+
* as SVG, built against a real DOM document rather than concatenated markup.
|
|
6
5
|
*
|
|
7
6
|
* Chen notation (distinct from crow's-foot):
|
|
8
|
-
* - Entities
|
|
9
|
-
* - Relationships
|
|
10
|
-
*
|
|
11
|
-
* - Attributes
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* - Entities -> rectangles (weak entities get a double border)
|
|
8
|
+
* - Relationships -> diamonds placed between the two entities they connect,
|
|
9
|
+
* with cardinality labels (1, N, M) on the connecting lines
|
|
10
|
+
* - Attributes -> ellipses connected to their entity by a line; key
|
|
11
|
+
* attributes have underlined text, multivalued get a
|
|
12
|
+
* double ellipse, derived get a dashed ellipse.
|
|
14
13
|
*
|
|
15
|
-
*
|
|
16
|
-
* entities/diamonds) via resolveTheme/resolveAccent, so both flags change the
|
|
17
|
-
* generated output. The viewBox is auto-sized to the laid-out geometry.
|
|
14
|
+
* The viewBox is auto-sized to the laid-out geometry.
|
|
18
15
|
*
|
|
19
16
|
* Usage:
|
|
20
17
|
* const diag = new ChenDiagram({ entities: [...], relationships: [...] });
|
|
@@ -57,8 +54,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
57
54
|
exports.ChenDiagram = void 0;
|
|
58
55
|
const fs = __importStar(require("fs"));
|
|
59
56
|
const path = __importStar(require("path"));
|
|
60
|
-
const
|
|
61
|
-
const
|
|
57
|
+
const svg_1 = require("./core/svg");
|
|
58
|
+
const theme_1 = require("./core/theme");
|
|
59
|
+
const layout_1 = require("./core/layout");
|
|
62
60
|
class ChenDiagram {
|
|
63
61
|
constructor(options) {
|
|
64
62
|
this.opts = {
|
|
@@ -69,7 +67,7 @@ class ChenDiagram {
|
|
|
69
67
|
color: options.color ?? '',
|
|
70
68
|
};
|
|
71
69
|
}
|
|
72
|
-
//
|
|
70
|
+
// -- Attribute anchor positions radially around an entity center ------------
|
|
73
71
|
attributePositions(center, count) {
|
|
74
72
|
const D = ChenDiagram.ATTR_DIST;
|
|
75
73
|
const pts = [];
|
|
@@ -86,15 +84,15 @@ class ChenDiagram {
|
|
|
86
84
|
}
|
|
87
85
|
return pts;
|
|
88
86
|
}
|
|
89
|
-
drawAttribute(svg, from, at, attr
|
|
90
|
-
// connector line entity
|
|
87
|
+
drawAttribute(svg, from, at, attr) {
|
|
88
|
+
// connector line entity -> attribute
|
|
91
89
|
svg.child('line', {
|
|
92
90
|
x1: from.x,
|
|
93
91
|
y1: from.y,
|
|
94
92
|
x2: at.x,
|
|
95
93
|
y2: at.y,
|
|
96
|
-
stroke:
|
|
97
|
-
'stroke-width':
|
|
94
|
+
stroke: theme_1.INK.line,
|
|
95
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
98
96
|
});
|
|
99
97
|
const rx = ChenDiagram.ATTR_RX;
|
|
100
98
|
const ry = ChenDiagram.ATTR_RY;
|
|
@@ -108,8 +106,8 @@ class ChenDiagram {
|
|
|
108
106
|
rx: rx + 5,
|
|
109
107
|
ry: ry + 5,
|
|
110
108
|
fill: 'none',
|
|
111
|
-
stroke:
|
|
112
|
-
'stroke-width':
|
|
109
|
+
stroke: theme_1.INK.line,
|
|
110
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
113
111
|
'stroke-dasharray': strokeDash,
|
|
114
112
|
});
|
|
115
113
|
}
|
|
@@ -118,42 +116,40 @@ class ChenDiagram {
|
|
|
118
116
|
cy: at.y,
|
|
119
117
|
rx,
|
|
120
118
|
ry,
|
|
121
|
-
fill:
|
|
122
|
-
stroke:
|
|
123
|
-
'stroke-width':
|
|
119
|
+
fill: theme_1.INK.ground,
|
|
120
|
+
stroke: theme_1.INK.line,
|
|
121
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
124
122
|
'stroke-dasharray': strokeDash,
|
|
125
123
|
});
|
|
126
|
-
const label = attr.name.length > 14 ? attr.name.slice(0, 13) + '…' : attr.name;
|
|
127
124
|
svg
|
|
128
125
|
.child('text', {
|
|
129
126
|
x: at.x,
|
|
130
127
|
y: at.y + 4,
|
|
131
|
-
'font-family':
|
|
132
|
-
'font-size':
|
|
128
|
+
'font-family': theme_1.FONT.family,
|
|
129
|
+
'font-size': theme_1.FONT.body + 1,
|
|
133
130
|
'font-weight': attr.key ? 600 : 400,
|
|
134
|
-
fill:
|
|
131
|
+
fill: theme_1.INK.line,
|
|
135
132
|
'text-anchor': 'middle',
|
|
136
133
|
// key attributes are underlined in Chen notation
|
|
137
134
|
'text-decoration': attr.key ? 'underline' : undefined,
|
|
138
135
|
})
|
|
139
|
-
.text(
|
|
136
|
+
.text((0, layout_1.truncate)(attr.name, rx * 2 - 8, theme_1.FONT.body + 1));
|
|
140
137
|
}
|
|
141
|
-
drawEntity(svg, p
|
|
138
|
+
drawEntity(svg, p) {
|
|
142
139
|
const W = ChenDiagram.ENT_W;
|
|
143
140
|
const H = ChenDiagram.ENT_H;
|
|
144
141
|
const x = p.center.x - W / 2;
|
|
145
142
|
const y = p.center.y - H / 2;
|
|
146
|
-
// weak entities
|
|
143
|
+
// weak entities -> double rectangle border
|
|
147
144
|
if (p.entity.weak) {
|
|
148
145
|
svg.child('rect', {
|
|
149
146
|
x: x - 5,
|
|
150
147
|
y: y - 5,
|
|
151
148
|
width: W + 10,
|
|
152
149
|
height: H + 10,
|
|
153
|
-
rx: 0,
|
|
154
150
|
fill: 'none',
|
|
155
|
-
stroke:
|
|
156
|
-
'stroke-width':
|
|
151
|
+
stroke: theme_1.INK.line,
|
|
152
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
157
153
|
});
|
|
158
154
|
}
|
|
159
155
|
svg.child('rect', {
|
|
@@ -161,45 +157,44 @@ class ChenDiagram {
|
|
|
161
157
|
y,
|
|
162
158
|
width: W,
|
|
163
159
|
height: H,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
stroke:
|
|
167
|
-
'stroke-width': 1.6,
|
|
160
|
+
fill: theme_1.INK.wash,
|
|
161
|
+
stroke: theme_1.INK.line,
|
|
162
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
168
163
|
});
|
|
169
164
|
svg
|
|
170
165
|
.child('text', {
|
|
171
166
|
x: p.center.x,
|
|
172
167
|
y: p.center.y + 5,
|
|
173
|
-
'font-family':
|
|
174
|
-
'font-size':
|
|
175
|
-
'font-weight':
|
|
176
|
-
fill:
|
|
168
|
+
'font-family': theme_1.FONT.family,
|
|
169
|
+
'font-size': theme_1.FONT.title + 4,
|
|
170
|
+
'font-weight': 'bold',
|
|
171
|
+
fill: theme_1.INK.line,
|
|
177
172
|
'text-anchor': 'middle',
|
|
178
173
|
})
|
|
179
174
|
.text(p.entity.name);
|
|
180
175
|
}
|
|
181
|
-
drawRelationship(svg, rel, a, b
|
|
176
|
+
drawRelationship(svg, rel, a, b) {
|
|
182
177
|
const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
183
178
|
const DW = ChenDiagram.DIA_W;
|
|
184
179
|
const DH = ChenDiagram.DIA_H;
|
|
185
|
-
// connecting lines: entity-a
|
|
180
|
+
// connecting lines: entity-a -> diamond -> entity-b
|
|
186
181
|
svg.child('line', {
|
|
187
182
|
x1: a.x,
|
|
188
183
|
y1: a.y,
|
|
189
184
|
x2: mid.x,
|
|
190
185
|
y2: mid.y,
|
|
191
|
-
stroke:
|
|
192
|
-
'stroke-width':
|
|
186
|
+
stroke: theme_1.INK.line,
|
|
187
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
193
188
|
});
|
|
194
189
|
svg.child('line', {
|
|
195
190
|
x1: mid.x,
|
|
196
191
|
y1: mid.y,
|
|
197
192
|
x2: b.x,
|
|
198
193
|
y2: b.y,
|
|
199
|
-
stroke:
|
|
200
|
-
'stroke-width':
|
|
194
|
+
stroke: theme_1.INK.line,
|
|
195
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
201
196
|
});
|
|
202
|
-
// diamond (polygon) centered on mid
|
|
197
|
+
// diamond (polygon) centered on mid.
|
|
203
198
|
const pts = [
|
|
204
199
|
`${mid.x},${mid.y - DH / 2}`,
|
|
205
200
|
`${mid.x + DW / 2},${mid.y}`,
|
|
@@ -208,18 +203,18 @@ class ChenDiagram {
|
|
|
208
203
|
].join(' ');
|
|
209
204
|
svg.child('polygon', {
|
|
210
205
|
points: pts,
|
|
211
|
-
fill:
|
|
212
|
-
stroke:
|
|
213
|
-
'stroke-width':
|
|
206
|
+
fill: theme_1.INK.wash,
|
|
207
|
+
stroke: theme_1.INK.line,
|
|
208
|
+
'stroke-width': theme_1.STROKE.hair,
|
|
214
209
|
});
|
|
215
210
|
svg
|
|
216
211
|
.child('text', {
|
|
217
212
|
x: mid.x,
|
|
218
213
|
y: mid.y + 5,
|
|
219
|
-
'font-family':
|
|
220
|
-
'font-size':
|
|
221
|
-
'font-weight':
|
|
222
|
-
fill:
|
|
214
|
+
'font-family': theme_1.FONT.family,
|
|
215
|
+
'font-size': theme_1.FONT.body + 3,
|
|
216
|
+
'font-weight': 'bold',
|
|
217
|
+
fill: theme_1.INK.line,
|
|
223
218
|
'text-anchor': 'middle',
|
|
224
219
|
})
|
|
225
220
|
.text(rel.name);
|
|
@@ -233,10 +228,10 @@ class ChenDiagram {
|
|
|
233
228
|
.child('text', {
|
|
234
229
|
x: lx,
|
|
235
230
|
y: ly,
|
|
236
|
-
'font-family':
|
|
237
|
-
'font-size':
|
|
238
|
-
'font-weight':
|
|
239
|
-
fill:
|
|
231
|
+
'font-family': theme_1.FONT.mono,
|
|
232
|
+
'font-size': theme_1.FONT.body + 2,
|
|
233
|
+
'font-weight': 'bold',
|
|
234
|
+
fill: theme_1.INK.line,
|
|
240
235
|
'text-anchor': 'middle',
|
|
241
236
|
})
|
|
242
237
|
.text(card);
|
|
@@ -244,15 +239,12 @@ class ChenDiagram {
|
|
|
244
239
|
label(a, rel.fromCardinality);
|
|
245
240
|
label(b, rel.toCardinality);
|
|
246
241
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const { entities, relationships, title, theme, color } = this.opts;
|
|
250
|
-
const accent = (0, palette_1.resolveAccent)(color);
|
|
251
|
-
const t = (0, palette_1.resolveTheme)(theme);
|
|
242
|
+
build() {
|
|
243
|
+
const { entities, relationships, title } = this.opts;
|
|
252
244
|
const PAD = ChenDiagram.PAD;
|
|
253
245
|
const COL_GAP = ChenDiagram.COL_GAP;
|
|
254
246
|
const ROW_GAP = ChenDiagram.ROW_GAP;
|
|
255
|
-
//
|
|
247
|
+
// Place entities on a grid (2 per row).
|
|
256
248
|
const perRow = Math.min(2, Math.max(1, entities.length));
|
|
257
249
|
const originX = PAD + COL_GAP / 2;
|
|
258
250
|
const originY = PAD + (title ? ChenDiagram.TITLE_H : 0) + ROW_GAP / 2;
|
|
@@ -267,7 +259,7 @@ class ChenDiagram {
|
|
|
267
259
|
const byName = new Map();
|
|
268
260
|
for (const p of placed)
|
|
269
261
|
byName.set(p.entity.name, p);
|
|
270
|
-
//
|
|
262
|
+
// Compute bounds (attributes extend furthest).
|
|
271
263
|
let maxX = 0;
|
|
272
264
|
let maxY = 0;
|
|
273
265
|
const attrTargets = [];
|
|
@@ -294,40 +286,39 @@ class ChenDiagram {
|
|
|
294
286
|
}
|
|
295
287
|
const svgW = Math.ceil(maxX + PAD);
|
|
296
288
|
const svgH = Math.ceil(maxY + PAD);
|
|
297
|
-
const doc = new
|
|
289
|
+
const doc = new svg_1.SvgDocument(svgW, svgH);
|
|
298
290
|
const svg = doc.root;
|
|
299
|
-
|
|
300
|
-
doc.style(palette_1.FONT_IMPORT);
|
|
301
|
-
// ── Ground ──────────────────────────────────────────────────────────
|
|
302
|
-
svg.child('rect', { width: svgW, height: svgH, fill: t.canvasBg });
|
|
303
|
-
// ── Title ───────────────────────────────────────────────────────────
|
|
291
|
+
svg.child('rect', { width: svgW, height: svgH, fill: theme_1.INK.ground });
|
|
304
292
|
if (title) {
|
|
305
293
|
svg
|
|
306
294
|
.child('text', {
|
|
307
295
|
x: PAD,
|
|
308
296
|
y: PAD,
|
|
309
|
-
'font-family':
|
|
310
|
-
'font-size':
|
|
311
|
-
'font-weight':
|
|
312
|
-
fill:
|
|
297
|
+
'font-family': theme_1.FONT.family,
|
|
298
|
+
'font-size': theme_1.FONT.title + 13,
|
|
299
|
+
'font-weight': 'bold',
|
|
300
|
+
fill: theme_1.INK.line,
|
|
313
301
|
})
|
|
314
302
|
.text(title);
|
|
315
303
|
}
|
|
316
|
-
//
|
|
304
|
+
// Relationships first, so lines/diamonds sit under entities.
|
|
317
305
|
for (const rel of relationships) {
|
|
318
306
|
const A = byName.get(rel.from);
|
|
319
307
|
const B = byName.get(rel.to);
|
|
320
308
|
if (A && B)
|
|
321
|
-
this.drawRelationship(svg, rel, A.center, B.center
|
|
309
|
+
this.drawRelationship(svg, rel, A.center, B.center);
|
|
322
310
|
}
|
|
323
|
-
//
|
|
311
|
+
// Attributes (connectors + ellipses).
|
|
324
312
|
for (const target of attrTargets) {
|
|
325
|
-
this.drawAttribute(svg, target.from, target.at, target.attr
|
|
313
|
+
this.drawAttribute(svg, target.from, target.at, target.attr);
|
|
326
314
|
}
|
|
327
|
-
//
|
|
315
|
+
// Entities on top.
|
|
328
316
|
for (const p of placed)
|
|
329
|
-
this.drawEntity(svg, p
|
|
330
|
-
return doc
|
|
317
|
+
this.drawEntity(svg, p);
|
|
318
|
+
return doc;
|
|
319
|
+
}
|
|
320
|
+
generate() {
|
|
321
|
+
return this.build().toString('Generated by ts-prorm-orm ChenDiagram');
|
|
331
322
|
}
|
|
332
323
|
/**
|
|
333
324
|
* Write the SVG to a file. Creates parent directories if needed.
|
|
@@ -351,6 +342,6 @@ ChenDiagram.DIA_W = 130;
|
|
|
351
342
|
ChenDiagram.DIA_H = 74;
|
|
352
343
|
ChenDiagram.ATTR_RX = 52;
|
|
353
344
|
ChenDiagram.ATTR_RY = 24;
|
|
354
|
-
ChenDiagram.ATTR_DIST = 96; // center-of-entity
|
|
345
|
+
ChenDiagram.ATTR_DIST = 96; // center-of-entity to center-of-attribute
|
|
355
346
|
ChenDiagram.COL_GAP = 300; // horizontal spacing between entity centers
|
|
356
347
|
ChenDiagram.ROW_GAP = 320; // vertical spacing between entity rows
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ClassDiagram
|
|
2
|
+
* ClassDiagram - renders one or more classes as UML class boxes.
|
|
3
3
|
*
|
|
4
4
|
* Each class box has three compartments:
|
|
5
|
-
* - a title bar (class name + optional
|
|
5
|
+
* - a title bar (class name + optional <<stereotype>>),
|
|
6
6
|
* - an attributes compartment (`+ name: type`, with +/-/# visibility markers),
|
|
7
7
|
* - a methods compartment (`+ name(args): returnType`).
|
|
8
8
|
*
|
|
@@ -11,12 +11,8 @@
|
|
|
11
11
|
* (hollow triangle arrowhead) is drawn to its parent; when it declares plain
|
|
12
12
|
* associations, a simple line connector is drawn instead.
|
|
13
13
|
*
|
|
14
|
-
* `--theme light|dark` drives canvas/box/text colors and `--color <name|hex>`
|
|
15
|
-
* drives the accent used for title bars — both genuinely change fill/stroke
|
|
16
|
-
* values in the generated SVG.
|
|
17
|
-
*
|
|
18
14
|
* Usage:
|
|
19
|
-
* const diag = new ClassDiagram({ classes: [
|
|
15
|
+
* const diag = new ClassDiagram({ classes: [...] });
|
|
20
16
|
* diag.save('./diagrams/classes.svg');
|
|
21
17
|
* // or:
|
|
22
18
|
* const svgString = diag.generate();
|
|
@@ -46,8 +42,12 @@ export interface UmlClass {
|
|
|
46
42
|
export interface ClassDiagramOptions {
|
|
47
43
|
classes: UmlClass[];
|
|
48
44
|
title?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Accepted for backward compatibility and ignored: diagrams render in a
|
|
47
|
+
* single monochrome theme.
|
|
48
|
+
*/
|
|
49
49
|
theme?: 'light' | 'dark';
|
|
50
|
-
/**
|
|
50
|
+
/** Accepted for backward compatibility and ignored. */
|
|
51
51
|
color?: string;
|
|
52
52
|
/** Number of columns before wrapping. Defaults to an auto value. */
|
|
53
53
|
columns?: number;
|
|
@@ -66,6 +66,7 @@ export declare class ClassDiagram {
|
|
|
66
66
|
constructor(options: ClassDiagramOptions);
|
|
67
67
|
private boxHeight;
|
|
68
68
|
private layout;
|
|
69
|
+
private build;
|
|
69
70
|
generate(): string;
|
|
70
71
|
private center;
|
|
71
72
|
private drawAssociation;
|