ts-prorm-orm 1.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 +1111 -0
- package/LICENSE +21 -0
- package/README.md +573 -0
- package/dist/audit/history-query.js +180 -0
- package/dist/audit/index.js +23 -0
- package/dist/audit/logger.js +236 -0
- package/dist/cache/cache-manager.js +84 -0
- package/dist/cache/index.js +16 -0
- package/dist/cache/redis-cluster-cache.js +557 -0
- package/dist/cli.js +2200 -0
- package/dist/compliance/audit-trail.js +68 -0
- package/dist/compliance/backup-verification.js +685 -0
- package/dist/compliance/breach-detector.js +505 -0
- package/dist/compliance/consent-record.js +227 -0
- package/dist/compliance/consent-versioning.js +331 -0
- package/dist/compliance/cross-border-log.js +530 -0
- package/dist/compliance/data-classifier.js +258 -0
- package/dist/compliance/data-lineage.js +565 -0
- package/dist/compliance/data-masker.js +303 -0
- package/dist/compliance/data-portability.js +265 -0
- package/dist/compliance/data-retention.js +195 -0
- package/dist/compliance/dsar-workflow.js +342 -0
- package/dist/compliance/field-encryption.js +223 -0
- package/dist/compliance/immutable-record.js +148 -0
- package/dist/compliance/index.js +260 -0
- package/dist/compliance/privacy-impact-assessment.js +364 -0
- package/dist/compliance/pseudonymization.js +269 -0
- package/dist/compliance/query-firewall.js +1182 -0
- package/dist/compliance/rate-limiter.js +580 -0
- package/dist/compliance/right-to-erasure.js +117 -0
- package/dist/compliance/row-level-security.js +246 -0
- package/dist/compliance/security-decorator.js +574 -0
- package/dist/compliance/security-monitor.js +525 -0
- package/dist/compliance/sensitive-data-discovery.js +476 -0
- package/dist/compliance/session-isolation.js +472 -0
- package/dist/compliance/tls-enforcer.js +108 -0
- package/dist/compliance/worm-storage.js +712 -0
- package/dist/connection-manager.js +198 -0
- package/dist/connection-pool.js +519 -0
- package/dist/decorators/audit.js +136 -0
- package/dist/decorators/belongs-to-many.js +115 -0
- package/dist/decorators/belongs-to.js +115 -0
- package/dist/decorators/check.js +435 -0
- package/dist/decorators/collate.js +329 -0
- package/dist/decorators/comment.js +205 -0
- package/dist/decorators/database-settings.js +236 -0
- package/dist/decorators/default.js +244 -0
- package/dist/decorators/encryption.js +235 -0
- package/dist/decorators/engine.js +97 -0
- package/dist/decorators/fk-constraints.js +594 -0
- package/dist/decorators/foreign-table.js +136 -0
- package/dist/decorators/generated.js +274 -0
- package/dist/decorators/has-many.js +127 -0
- package/dist/decorators/has-one.js +116 -0
- package/dist/decorators/hstore.js +129 -0
- package/dist/decorators/index.js +355 -0
- package/dist/decorators/json-column.js +83 -0
- package/dist/decorators/jsonb.js +101 -0
- package/dist/decorators/orm-decorators.js +425 -0
- package/dist/decorators/permissions.js +294 -0
- package/dist/decorators/procedure.js +210 -0
- package/dist/decorators/query-options.js +556 -0
- package/dist/decorators/range.js +167 -0
- package/dist/decorators/set-column.js +83 -0
- package/dist/decorators/spatial.js +114 -0
- package/dist/decorators/storage.js +580 -0
- package/dist/decorators/timezone.js +512 -0
- package/dist/decorators/trigger.js +90 -0
- package/dist/decorators/uuid.js +135 -0
- package/dist/decorators/view.js +258 -0
- package/dist/diagrams/chen-diagram.js +354 -0
- package/dist/diagrams/class-diagram.js +384 -0
- package/dist/diagrams/dependency-diagram.js +432 -0
- package/dist/diagrams/er-diagram.js +605 -0
- package/dist/diagrams/flow-diagram.js +394 -0
- package/dist/diagrams/gantt-diagram.js +411 -0
- package/dist/diagrams/index-diagram.js +353 -0
- package/dist/diagrams/index.js +184 -0
- package/dist/diagrams/migration-diagram.js +316 -0
- package/dist/diagrams/model-diagram.js +616 -0
- package/dist/diagrams/package-diagram.js +376 -0
- package/dist/diagrams/palette.js +85 -0
- package/dist/diagrams/relational-diagram.js +455 -0
- package/dist/diagrams/schemadoc-diagram.js +309 -0
- package/dist/diagrams/sequence-diagram.js +307 -0
- package/dist/diagrams/state-diagram.js +344 -0
- package/dist/diagrams/svg-dom.js +111 -0
- package/dist/diagrams/tree-diagram.js +250 -0
- package/dist/dialects/clickhouse/index.js +1742 -0
- package/dist/dialects/cockroachdb/index.js +4677 -0
- package/dist/dialects/cratedb/index.js +441 -0
- package/dist/dialects/databricks/index.js +517 -0
- package/dist/dialects/db2/index.js +2225 -0
- package/dist/dialects/dialect.js +720 -0
- package/dist/dialects/duckdb/index.js +2014 -0
- package/dist/dialects/exasol/index.js +357 -0
- package/dist/dialects/firebird/index.js +495 -0
- package/dist/dialects/greenplum/index.js +457 -0
- package/dist/dialects/hana/index.js +1741 -0
- package/dist/dialects/mariadb/index.js +3590 -0
- package/dist/dialects/mssql/index.js +2296 -0
- package/dist/dialects/mysql/index.js +4058 -0
- package/dist/dialects/oracle/index.js +2999 -0
- package/dist/dialects/postgres/index.js +5319 -0
- package/dist/dialects/query-stream-helper.js +152 -0
- package/dist/dialects/questdb/index.js +433 -0
- package/dist/dialects/redshift/index.js +2277 -0
- package/dist/dialects/singlestore/index.js +354 -0
- package/dist/dialects/snowflake/index.js +2082 -0
- package/dist/dialects/spanner/index.js +1768 -0
- package/dist/dialects/sqlite/index.js +3382 -0
- package/dist/dialects/tidb/index.js +377 -0
- package/dist/dialects/timescaledb/index.js +164 -0
- package/dist/dialects/trino/index.js +420 -0
- package/dist/dialects/turso/index.js +227 -0
- package/dist/dialects/vertica/index.js +317 -0
- package/dist/dialects/yugabytedb/index.js +424 -0
- package/dist/errors/index.js +472 -0
- package/dist/errors/utils.js +340 -0
- package/dist/errors.js +21 -0
- package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
- package/dist/extensions/catalog/mssql-features.js +147 -0
- package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
- package/dist/extensions/catalog/oracle-db2-features.js +196 -0
- package/dist/extensions/catalog/postgres-extensions.js +516 -0
- package/dist/extensions/index.js +71 -0
- package/dist/extensions/types.js +13 -0
- package/dist/foreign-data.js +173 -0
- package/dist/hooks/hooks-manager.js +350 -0
- package/dist/hooks/index.js +37 -0
- package/dist/index.js +463 -0
- package/dist/logging.js +335 -0
- package/dist/migrations/index.js +40 -0
- package/dist/migrations/migration.js +196 -0
- package/dist/migrations/migrator.js +411 -0
- package/dist/migrations/prormmigration.js +275 -0
- package/dist/migrations/query-interface.js +435 -0
- package/dist/migrations/seeder.js +353 -0
- package/dist/models/associations.js +852 -0
- package/dist/models/constraints.js +288 -0
- package/dist/models/data-types.js +2518 -0
- package/dist/models/decorators.js +445 -0
- package/dist/models/index.js +33 -0
- package/dist/models/indexes.js +531 -0
- package/dist/models/methods.js +382 -0
- package/dist/models/model-manager.js +103 -0
- package/dist/models/model.js +5349 -0
- package/dist/models/operators.js +67 -0
- package/dist/models/scopes.js +189 -0
- package/dist/models/typescript-types.js +26 -0
- package/dist/nosql/aerospike/index.js +205 -0
- package/dist/nosql/allegrograph/index.js +169 -0
- package/dist/nosql/arangodb/index.js +364 -0
- package/dist/nosql/azure-blob/index.js +206 -0
- package/dist/nosql/beanstalkd/index.js +231 -0
- package/dist/nosql/beequeue/index.js +210 -0
- package/dist/nosql/bigchaindb/index.js +195 -0
- package/dist/nosql/bigtable/index.js +224 -0
- package/dist/nosql/blazegraph/index.js +173 -0
- package/dist/nosql/bullmq/index.js +191 -0
- package/dist/nosql/cassandra/index.js +174 -0
- package/dist/nosql/chroma/index.js +190 -0
- package/dist/nosql/cloudflare-kv/index.js +220 -0
- package/dist/nosql/coherence/index.js +200 -0
- package/dist/nosql/cosmosdb/index.js +157 -0
- package/dist/nosql/couchbase/index.js +213 -0
- package/dist/nosql/dax/index.js +212 -0
- package/dist/nosql/deno-kv/index.js +206 -0
- package/dist/nosql/dgraph/index.js +171 -0
- package/dist/nosql/doris/index.js +169 -0
- package/dist/nosql/druid/index.js +162 -0
- package/dist/nosql/dynamodb/index.js +937 -0
- package/dist/nosql/elasticsearch/index.js +377 -0
- package/dist/nosql/etcd/index.js +502 -0
- package/dist/nosql/eventhubs/index.js +213 -0
- package/dist/nosql/eventstore/index.js +254 -0
- package/dist/nosql/faunadb/index.js +188 -0
- package/dist/nosql/firestore/index.js +177 -0
- package/dist/nosql/fluree/index.js +148 -0
- package/dist/nosql/fuseki/index.js +170 -0
- package/dist/nosql/gcs/index.js +172 -0
- package/dist/nosql/gearman/index.js +160 -0
- package/dist/nosql/geode/index.js +196 -0
- package/dist/nosql/graphdb/index.js +169 -0
- package/dist/nosql/graylog/index.js +188 -0
- package/dist/nosql/gridgain/index.js +171 -0
- package/dist/nosql/hazelcast/index.js +162 -0
- package/dist/nosql/hbase/index.js +230 -0
- package/dist/nosql/ignite/index.js +173 -0
- package/dist/nosql/immudb/index.js +184 -0
- package/dist/nosql/index.js +232 -0
- package/dist/nosql/infinispan/index.js +200 -0
- package/dist/nosql/influxdb/index.js +0 -0
- package/dist/nosql/kafka/index.js +234 -0
- package/dist/nosql/keyspaces/index.js +189 -0
- package/dist/nosql/kinesis/index.js +253 -0
- package/dist/nosql/leveldb/index.js +153 -0
- package/dist/nosql/lmdb/index.js +160 -0
- package/dist/nosql/loki/index.js +201 -0
- package/dist/nosql/marklogic/index.js +204 -0
- package/dist/nosql/materialize/index.js +145 -0
- package/dist/nosql/meilisearch/index.js +154 -0
- package/dist/nosql/memcached/index.js +223 -0
- package/dist/nosql/milvus/index.js +410 -0
- package/dist/nosql/minio/index.js +265 -0
- package/dist/nosql/momento/index.js +179 -0
- package/dist/nosql/mongodb/index.js +461 -0
- package/dist/nosql/nats/index.js +247 -0
- package/dist/nosql/nedb/index.js +164 -0
- package/dist/nosql/neo4j/index.js +450 -0
- package/dist/nosql/neptune/index.js +470 -0
- package/dist/nosql/nsq/index.js +200 -0
- package/dist/nosql/opensearch/index.js +186 -0
- package/dist/nosql/orientdb/index.js +175 -0
- package/dist/nosql/papertrail/index.js +200 -0
- package/dist/nosql/pinecone/index.js +0 -0
- package/dist/nosql/pinot/index.js +133 -0
- package/dist/nosql/pouchdb/index.js +172 -0
- package/dist/nosql/prometheus/index.js +174 -0
- package/dist/nosql/provendb/index.js +147 -0
- package/dist/nosql/pubsub/index.js +187 -0
- package/dist/nosql/pulsar/index.js +232 -0
- package/dist/nosql/qdrant/index.js +295 -0
- package/dist/nosql/qldb/index.js +192 -0
- package/dist/nosql/r2/index.js +281 -0
- package/dist/nosql/rabbitmq/index.js +237 -0
- package/dist/nosql/ravendb/index.js +175 -0
- package/dist/nosql/redis/index.js +607 -0
- package/dist/nosql/redpanda/index.js +237 -0
- package/dist/nosql/resque/index.js +203 -0
- package/dist/nosql/rethinkdb/index.js +232 -0
- package/dist/nosql/rocksdb/index.js +152 -0
- package/dist/nosql/rockset/index.js +126 -0
- package/dist/nosql/s3/index.js +298 -0
- package/dist/nosql/scylladb/index.js +178 -0
- package/dist/nosql/signoz/index.js +227 -0
- package/dist/nosql/sns/index.js +201 -0
- package/dist/nosql/solr/index.js +231 -0
- package/dist/nosql/splunk/index.js +227 -0
- package/dist/nosql/sqs/index.js +246 -0
- package/dist/nosql/stardog/index.js +169 -0
- package/dist/nosql/starrocks/index.js +170 -0
- package/dist/nosql/store.js +2 -0
- package/dist/nosql/sumologic/index.js +213 -0
- package/dist/nosql/surrealdb/index.js +179 -0
- package/dist/nosql/terminusdb/index.js +151 -0
- package/dist/nosql/tigergraph/index.js +469 -0
- package/dist/nosql/typesense/index.js +148 -0
- package/dist/nosql/unqlite/index.js +157 -0
- package/dist/nosql/upstash/index.js +167 -0
- package/dist/nosql/vercel-kv/index.js +166 -0
- package/dist/nosql/victoriametrics/index.js +213 -0
- package/dist/nosql/virtuoso/index.js +169 -0
- package/dist/nosql/weaviate/index.js +276 -0
- package/dist/operators/index.js +108 -0
- package/dist/operators.js +2690 -0
- package/dist/prisma-migrate/index.js +38 -0
- package/dist/prisma-migrate/migration-generator.js +125 -0
- package/dist/prisma-migrate/model-generator.js +172 -0
- package/dist/prisma-migrate/relations.js +100 -0
- package/dist/prisma-migrate/schema-parser.js +167 -0
- package/dist/prisma-migrate/type-mapper.js +40 -0
- package/dist/prorm.js +6832 -0
- package/dist/query-builders/cte-builder.js +80 -0
- package/dist/query-builders/functions/aggregate.js +390 -0
- package/dist/query-builders/functions/conditional.js +503 -0
- package/dist/query-builders/functions/datetime.js +695 -0
- package/dist/query-builders/functions/fulltext.js +439 -0
- package/dist/query-builders/functions/index.js +93 -0
- package/dist/query-builders/functions/json.js +427 -0
- package/dist/query-builders/functions/math.js +399 -0
- package/dist/query-builders/functions/string.js +518 -0
- package/dist/query-builders/functions/window.js +328 -0
- package/dist/query-builders/include-builder.js +323 -0
- package/dist/query-builders/index-expression-builder.js +242 -0
- package/dist/query-builders/index.js +161 -0
- package/dist/query-builders/insert-builder.js +164 -0
- package/dist/query-builders/model-helpers.js +38 -0
- package/dist/query-builders/order-limit-builder.js +239 -0
- package/dist/query-builders/sql-compiler.js +2040 -0
- package/dist/query-builders/subquery-builder.js +152 -0
- package/dist/query-builders/update-builder.js +182 -0
- package/dist/query-builders/view-builder.js +218 -0
- package/dist/query-builders/where-builder.js +1532 -0
- package/dist/query-interface.js +622 -0
- package/dist/query-optimizers/batch-optimizer.js +426 -0
- package/dist/query-optimizers/explain-plans.js +415 -0
- package/dist/query-optimizers/index.js +51 -0
- package/dist/query-optimizers/prepared-statement-cache.js +423 -0
- package/dist/query-optimizers/query-hints.js +438 -0
- package/dist/query-optimizers/query-optimizer.js +278 -0
- package/dist/query-optimizers/slow-query-logger.js +271 -0
- package/dist/replica-manager.js +507 -0
- package/dist/schema/index.js +15 -0
- package/dist/schema/migration-generator.js +374 -0
- package/dist/schema/schema-differ.js +549 -0
- package/dist/schema/types.js +6 -0
- package/dist/sql-constants.js +300 -0
- package/dist/sqlite-advanced.js +1047 -0
- package/dist/streams/index.js +12 -0
- package/dist/streams/transforms.js +178 -0
- package/dist/transaction.js +456 -0
- package/dist/types/index.js +180 -0
- package/dist/user-management.js +127 -0
- package/dist/utils/date.js +300 -0
- package/dist/utils/index.js +1079 -0
- package/dist/utils/string.js +161 -0
- package/dist/validators/index.js +19 -0
- package/dist/validators/validator.js +911 -0
- package/package.json +190 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IndexDiagram — an INDEX & CONSTRAINT MAP for a single table.
|
|
4
|
+
*
|
|
5
|
+
* A table's columns are laid out as a horizontal strip of "column chips".
|
|
6
|
+
* Below the strip, every index/constraint is drawn as a labeled "bracket" that
|
|
7
|
+
* spans the column chips it covers — so composite indexes visibly span multiple
|
|
8
|
+
* columns and overlapping coverage is obvious at a glance.
|
|
9
|
+
*
|
|
10
|
+
* Index kinds (PRIMARY / UNIQUE / INDEX / FULLTEXT / FOREIGN KEY / CHECK) are
|
|
11
|
+
* distinguished by color + a short badge; each row also shows the index name,
|
|
12
|
+
* its access method (btree/hash/gin…) and whether it is unique.
|
|
13
|
+
*
|
|
14
|
+
* `--theme light|dark` drives the canvas/text colors and `--color <name|hex>`
|
|
15
|
+
* drives the accent used for the header and the PRIMARY index — both genuinely
|
|
16
|
+
* change fill/stroke values in the generated SVG.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* const diag = new IndexDiagram({ table: 'users', columns: [...], indexes: [...] });
|
|
20
|
+
* diag.save('./diagrams/users-indexes.svg');
|
|
21
|
+
* // or:
|
|
22
|
+
* const svg = diag.generate();
|
|
23
|
+
*/
|
|
24
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
27
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
28
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
29
|
+
}
|
|
30
|
+
Object.defineProperty(o, k2, desc);
|
|
31
|
+
}) : (function(o, m, k, k2) {
|
|
32
|
+
if (k2 === undefined) k2 = k;
|
|
33
|
+
o[k2] = m[k];
|
|
34
|
+
}));
|
|
35
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
36
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
37
|
+
}) : function(o, v) {
|
|
38
|
+
o["default"] = v;
|
|
39
|
+
});
|
|
40
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
41
|
+
var ownKeys = function(o) {
|
|
42
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
43
|
+
var ar = [];
|
|
44
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
45
|
+
return ar;
|
|
46
|
+
};
|
|
47
|
+
return ownKeys(o);
|
|
48
|
+
};
|
|
49
|
+
return function (mod) {
|
|
50
|
+
if (mod && mod.__esModule) return mod;
|
|
51
|
+
var result = {};
|
|
52
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
53
|
+
__setModuleDefault(result, mod);
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
})();
|
|
57
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
+
exports.IndexDiagram = void 0;
|
|
59
|
+
const fs = __importStar(require("fs"));
|
|
60
|
+
const path = __importStar(require("path"));
|
|
61
|
+
const palette_1 = require("./palette");
|
|
62
|
+
const svg_dom_1 = require("./svg-dom");
|
|
63
|
+
const KIND_STYLES = {
|
|
64
|
+
PRIMARY: { badge: 'PK', color: '#92400E', bg: '#FEF3C7' },
|
|
65
|
+
UNIQUE: { badge: 'UQ', color: '#5B21B6', bg: '#EDE9FE' },
|
|
66
|
+
INDEX: { badge: 'IX', color: '#0369A1', bg: '#E0F2FE' },
|
|
67
|
+
FULLTEXT: { badge: 'FT', color: '#065F46', bg: '#D1FAE5' },
|
|
68
|
+
'FOREIGN KEY': { badge: 'FK', color: '#1E3A8A', bg: '#DBEAFE' },
|
|
69
|
+
CHECK: { badge: 'CK', color: '#9F1239', bg: '#FFE4E6' },
|
|
70
|
+
};
|
|
71
|
+
function kindStyle(kind) {
|
|
72
|
+
return KIND_STYLES[kind ?? 'INDEX'] ?? KIND_STYLES.INDEX;
|
|
73
|
+
}
|
|
74
|
+
// ─── Main class ──────────────────────────────────────────────────────────────
|
|
75
|
+
class IndexDiagram {
|
|
76
|
+
constructor(options) {
|
|
77
|
+
this.opts = {
|
|
78
|
+
title: options.title ?? '',
|
|
79
|
+
theme: options.theme ?? 'light',
|
|
80
|
+
color: options.color ?? '',
|
|
81
|
+
...options,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
chipWidth() {
|
|
85
|
+
const label = this.opts.columns.map((c) => `${c.name} ${c.type ?? ''}`.trim());
|
|
86
|
+
const longest = label.reduce((m, s) => Math.max(m, s.length), 4);
|
|
87
|
+
return Math.max(IndexDiagram.MIN_CHIP_W, longest * 8 + 24);
|
|
88
|
+
}
|
|
89
|
+
generate() {
|
|
90
|
+
const { table, columns, indexes, title, theme, color } = this.opts;
|
|
91
|
+
const accent = (0, palette_1.resolveAccent)(color);
|
|
92
|
+
const t = (0, palette_1.resolveTheme)(theme);
|
|
93
|
+
const PAD = IndexDiagram.PAD;
|
|
94
|
+
const HDR = IndexDiagram.HDR;
|
|
95
|
+
const CHIP_H = IndexDiagram.CHIP_H;
|
|
96
|
+
const CHIP_GAP = IndexDiagram.CHIP_GAP;
|
|
97
|
+
const STRIP_LABEL = IndexDiagram.STRIP_LABEL;
|
|
98
|
+
const GAP_AFTER_STRIP = IndexDiagram.GAP_AFTER_STRIP;
|
|
99
|
+
const ROW_H = IndexDiagram.ROW_H;
|
|
100
|
+
const LABEL_W = IndexDiagram.LABEL_W;
|
|
101
|
+
const R = IndexDiagram.R;
|
|
102
|
+
const chipW = this.chipWidth();
|
|
103
|
+
const nCols = Math.max(columns.length, 1);
|
|
104
|
+
// Geometry of the column strip.
|
|
105
|
+
const stripX = PAD + LABEL_W;
|
|
106
|
+
const stripY = PAD + HDR + STRIP_LABEL;
|
|
107
|
+
const chipStride = chipW + CHIP_GAP;
|
|
108
|
+
const stripW = nCols * chipStride - CHIP_GAP;
|
|
109
|
+
// Center X of each column chip, keyed by column name.
|
|
110
|
+
const colCenter = {};
|
|
111
|
+
columns.forEach((c, i) => {
|
|
112
|
+
colCenter[c.name] = stripX + i * chipStride + chipW / 2;
|
|
113
|
+
});
|
|
114
|
+
// Overall canvas size.
|
|
115
|
+
const contentW = stripX + stripW;
|
|
116
|
+
const svgW = contentW + PAD;
|
|
117
|
+
const rowsTop = stripY + CHIP_H + GAP_AFTER_STRIP;
|
|
118
|
+
const svgH = rowsTop + indexes.length * ROW_H + PAD;
|
|
119
|
+
const uid = table.replace(/\W/g, '') || 'tbl';
|
|
120
|
+
const doc = new svg_dom_1.SvgDocument(svgW, svgH);
|
|
121
|
+
const svg = doc.root;
|
|
122
|
+
// ── Background ──────────────────────────────────────────────────────────
|
|
123
|
+
svg.child('rect', { width: svgW, height: svgH, fill: t.canvasBg });
|
|
124
|
+
// ── Defs: header gradient ───────────────────────────────────────────────
|
|
125
|
+
doc.linearGradient(`hg${uid}`, [
|
|
126
|
+
[0, accent.from],
|
|
127
|
+
[55, accent.mid],
|
|
128
|
+
[100, accent.to],
|
|
129
|
+
]);
|
|
130
|
+
// ── Header bar ──────────────────────────────────────────────────────────
|
|
131
|
+
svg.child('rect', { x: PAD, y: PAD, width: contentW - PAD, height: HDR, rx: R, fill: `url(#hg${uid})` });
|
|
132
|
+
svg
|
|
133
|
+
.child('text', {
|
|
134
|
+
x: PAD + 18,
|
|
135
|
+
y: PAD + 27,
|
|
136
|
+
'font-family': 'system-ui,-apple-system,sans-serif',
|
|
137
|
+
'font-size': 20,
|
|
138
|
+
'font-weight': 800,
|
|
139
|
+
fill: '#FFFFFF',
|
|
140
|
+
})
|
|
141
|
+
.text(title || `Index Map · ${table}`);
|
|
142
|
+
svg
|
|
143
|
+
.child('text', {
|
|
144
|
+
x: PAD + 18,
|
|
145
|
+
y: PAD + 47,
|
|
146
|
+
'font-family': "'SF Mono','Fira Code',monospace",
|
|
147
|
+
'font-size': 11,
|
|
148
|
+
fill: 'rgba(255,255,255,0.8)',
|
|
149
|
+
})
|
|
150
|
+
.text(`${columns.length} columns · ${indexes.length} indexes`);
|
|
151
|
+
// "TABLE" pill on the right of the header.
|
|
152
|
+
svg
|
|
153
|
+
.child('text', {
|
|
154
|
+
x: contentW - 16,
|
|
155
|
+
y: PAD + 33,
|
|
156
|
+
'font-family': "'SF Mono',monospace",
|
|
157
|
+
'font-size': 12,
|
|
158
|
+
'font-weight': 700,
|
|
159
|
+
fill: 'rgba(255,255,255,0.92)',
|
|
160
|
+
'text-anchor': 'end',
|
|
161
|
+
})
|
|
162
|
+
.text(table);
|
|
163
|
+
// ── Column strip label ──────────────────────────────────────────────────
|
|
164
|
+
svg
|
|
165
|
+
.child('text', {
|
|
166
|
+
x: stripX,
|
|
167
|
+
y: stripY - 8,
|
|
168
|
+
'font-family': 'system-ui,sans-serif',
|
|
169
|
+
'font-size': 11,
|
|
170
|
+
'font-weight': 700,
|
|
171
|
+
'letter-spacing': 1,
|
|
172
|
+
fill: t.textSecondary,
|
|
173
|
+
})
|
|
174
|
+
.text('COLUMNS');
|
|
175
|
+
// ── Column chips ────────────────────────────────────────────────────────
|
|
176
|
+
columns.forEach((c, i) => {
|
|
177
|
+
const x = stripX + i * chipStride;
|
|
178
|
+
svg.child('rect', {
|
|
179
|
+
x,
|
|
180
|
+
y: stripY,
|
|
181
|
+
width: chipW,
|
|
182
|
+
height: CHIP_H,
|
|
183
|
+
rx: 9,
|
|
184
|
+
fill: t.cardBg,
|
|
185
|
+
stroke: t.border,
|
|
186
|
+
'stroke-width': 1.5,
|
|
187
|
+
});
|
|
188
|
+
svg
|
|
189
|
+
.child('text', {
|
|
190
|
+
x: x + chipW / 2,
|
|
191
|
+
y: stripY + 20,
|
|
192
|
+
'font-family': "'SF Mono','Fira Code',monospace",
|
|
193
|
+
'font-size': 13,
|
|
194
|
+
'font-weight': 700,
|
|
195
|
+
fill: t.textPrimary,
|
|
196
|
+
'text-anchor': 'middle',
|
|
197
|
+
})
|
|
198
|
+
.text(c.name);
|
|
199
|
+
if (c.type) {
|
|
200
|
+
svg
|
|
201
|
+
.child('text', {
|
|
202
|
+
x: x + chipW / 2,
|
|
203
|
+
y: stripY + 37,
|
|
204
|
+
'font-family': "'SF Mono',monospace",
|
|
205
|
+
'font-size': 10,
|
|
206
|
+
fill: t.textSecondary,
|
|
207
|
+
'text-anchor': 'middle',
|
|
208
|
+
})
|
|
209
|
+
.text(c.type);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
// ── Index / constraint rows with spanning brackets ──────────────────────
|
|
213
|
+
// Each row draws: left label block (badge + name + method) and a spanning
|
|
214
|
+
// bracket that connects to every covered column chip via connector lines.
|
|
215
|
+
const chipBottom = stripY + CHIP_H;
|
|
216
|
+
indexes.forEach((idx, i) => {
|
|
217
|
+
const rowY = rowsTop + i * ROW_H;
|
|
218
|
+
const rowMid = rowY + ROW_H / 2;
|
|
219
|
+
const style = kindStyle(idx.kind);
|
|
220
|
+
const isPrimary = idx.kind === 'PRIMARY';
|
|
221
|
+
// The PRIMARY index adopts the accent color so --color is visibly wired in.
|
|
222
|
+
const lineColor = isPrimary ? accent.mid : style.color;
|
|
223
|
+
// Alternating row background band.
|
|
224
|
+
if (i % 2 === 1) {
|
|
225
|
+
svg.child('rect', {
|
|
226
|
+
x: PAD,
|
|
227
|
+
y: rowY,
|
|
228
|
+
width: contentW - PAD,
|
|
229
|
+
height: ROW_H,
|
|
230
|
+
rx: 8,
|
|
231
|
+
fill: t.rowAlt,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
// ── Left label block ──
|
|
235
|
+
// Badge chip.
|
|
236
|
+
const badgeBg = isPrimary ? accent.light : style.bg;
|
|
237
|
+
const badgeFg = isPrimary ? accent.text : style.color;
|
|
238
|
+
svg.child('rect', { x: PAD + 8, y: rowMid - 12, width: 30, height: 24, rx: 6, fill: badgeBg });
|
|
239
|
+
svg
|
|
240
|
+
.child('text', {
|
|
241
|
+
x: PAD + 8 + 15,
|
|
242
|
+
y: rowMid + 5,
|
|
243
|
+
'font-family': "'SF Mono',monospace",
|
|
244
|
+
'font-size': 11,
|
|
245
|
+
'font-weight': 800,
|
|
246
|
+
fill: badgeFg,
|
|
247
|
+
'text-anchor': 'middle',
|
|
248
|
+
})
|
|
249
|
+
.text(style.badge);
|
|
250
|
+
// Index name.
|
|
251
|
+
svg
|
|
252
|
+
.child('text', {
|
|
253
|
+
x: PAD + 48,
|
|
254
|
+
y: rowMid - 2,
|
|
255
|
+
'font-family': "'SF Mono','Fira Code',monospace",
|
|
256
|
+
'font-size': 12,
|
|
257
|
+
'font-weight': 700,
|
|
258
|
+
fill: t.textPrimary,
|
|
259
|
+
})
|
|
260
|
+
.text(idx.name);
|
|
261
|
+
// Method + unique subtitle.
|
|
262
|
+
const meta = [];
|
|
263
|
+
meta.push((idx.kind ?? 'INDEX').toLowerCase());
|
|
264
|
+
if (idx.method)
|
|
265
|
+
meta.push(idx.method);
|
|
266
|
+
if (idx.unique || idx.kind === 'PRIMARY' || idx.kind === 'UNIQUE')
|
|
267
|
+
meta.push('unique');
|
|
268
|
+
svg
|
|
269
|
+
.child('text', {
|
|
270
|
+
x: PAD + 48,
|
|
271
|
+
y: rowMid + 13,
|
|
272
|
+
'font-family': "'SF Mono',monospace",
|
|
273
|
+
'font-size': 10,
|
|
274
|
+
fill: t.textSecondary,
|
|
275
|
+
})
|
|
276
|
+
.text(meta.join(' · '));
|
|
277
|
+
// ── Spanning bracket over covered columns ──
|
|
278
|
+
const covered = idx.columns
|
|
279
|
+
.map((cn) => colCenter[cn])
|
|
280
|
+
.filter((v) => typeof v === 'number')
|
|
281
|
+
.sort((a, b) => a - b);
|
|
282
|
+
if (covered.length > 0) {
|
|
283
|
+
const first = covered[0];
|
|
284
|
+
const last = covered[covered.length - 1];
|
|
285
|
+
const bracketY = rowMid;
|
|
286
|
+
// Horizontal spine of the bracket across the covered span.
|
|
287
|
+
svg.child('line', {
|
|
288
|
+
x1: first,
|
|
289
|
+
y1: bracketY,
|
|
290
|
+
x2: last,
|
|
291
|
+
y2: bracketY,
|
|
292
|
+
stroke: lineColor,
|
|
293
|
+
'stroke-width': isPrimary ? 3 : 2,
|
|
294
|
+
'stroke-linecap': 'round',
|
|
295
|
+
});
|
|
296
|
+
// A connector path from each covered column chip down to the spine.
|
|
297
|
+
covered.forEach((cxp) => {
|
|
298
|
+
// Curved connector from the bottom of the chip to the spine node.
|
|
299
|
+
const d = `M ${cxp} ${chipBottom} C ${cxp} ${(chipBottom + bracketY) / 2}, ${cxp} ${(chipBottom + bracketY) / 2}, ${cxp} ${bracketY}`;
|
|
300
|
+
svg.child('path', {
|
|
301
|
+
d,
|
|
302
|
+
stroke: lineColor,
|
|
303
|
+
'stroke-width': 1.5,
|
|
304
|
+
fill: 'none',
|
|
305
|
+
opacity: 0.85,
|
|
306
|
+
});
|
|
307
|
+
// Node dot where the connector meets the spine.
|
|
308
|
+
svg.child('circle', { cx: cxp, cy: bracketY, r: isPrimary ? 5 : 4, fill: lineColor });
|
|
309
|
+
});
|
|
310
|
+
// Order labels (1,2,3…) for composite indexes so column order reads.
|
|
311
|
+
if (covered.length > 1) {
|
|
312
|
+
idx.columns.forEach((cn, ord) => {
|
|
313
|
+
const cxp = colCenter[cn];
|
|
314
|
+
if (typeof cxp !== 'number')
|
|
315
|
+
return;
|
|
316
|
+
svg
|
|
317
|
+
.child('text', {
|
|
318
|
+
x: cxp + 8,
|
|
319
|
+
y: bracketY - 8,
|
|
320
|
+
'font-family': "'SF Mono',monospace",
|
|
321
|
+
'font-size': 9,
|
|
322
|
+
'font-weight': 700,
|
|
323
|
+
fill: lineColor,
|
|
324
|
+
})
|
|
325
|
+
.text(String(ord + 1));
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
return doc.toString('Generated by ts-prorm-orm IndexDiagram');
|
|
331
|
+
}
|
|
332
|
+
/** Write the SVG to a file. Creates parent directories if needed. */
|
|
333
|
+
save(outputPath) {
|
|
334
|
+
const resolved = path.resolve(outputPath);
|
|
335
|
+
const dir = path.dirname(resolved);
|
|
336
|
+
if (!fs.existsSync(dir))
|
|
337
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
338
|
+
fs.writeFileSync(resolved, this.generate(), 'utf-8');
|
|
339
|
+
return resolved;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
exports.IndexDiagram = IndexDiagram;
|
|
343
|
+
// Layout constants (px)
|
|
344
|
+
IndexDiagram.PAD = 28;
|
|
345
|
+
IndexDiagram.HDR = 60;
|
|
346
|
+
IndexDiagram.CHIP_H = 46;
|
|
347
|
+
IndexDiagram.CHIP_GAP = 12;
|
|
348
|
+
IndexDiagram.STRIP_LABEL = 26;
|
|
349
|
+
IndexDiagram.GAP_AFTER_STRIP = 46;
|
|
350
|
+
IndexDiagram.ROW_H = 54;
|
|
351
|
+
IndexDiagram.LABEL_W = 250; // left column: badge + name + method
|
|
352
|
+
IndexDiagram.MIN_CHIP_W = 96;
|
|
353
|
+
IndexDiagram.R = 12;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module diagrams
|
|
4
|
+
*
|
|
5
|
+
* SVG diagram generators for ORM models and ER schemas.
|
|
6
|
+
*
|
|
7
|
+
* ─── Quick-start ────────────────────────────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* 1) Single-model card
|
|
10
|
+
* ─────────────────
|
|
11
|
+
* import { ModelDiagram } from './diagrams';
|
|
12
|
+
*
|
|
13
|
+
* const diag = new ModelDiagram({
|
|
14
|
+
* name: 'User',
|
|
15
|
+
* tableName: 'users',
|
|
16
|
+
* fields: {
|
|
17
|
+
* id: { type: 'INTEGER', primaryKey: true, autoIncrement: true },
|
|
18
|
+
* name: { type: 'VARCHAR(100)', allowNull: false },
|
|
19
|
+
* email: { type: 'VARCHAR(255)', unique: true, allowNull: false },
|
|
20
|
+
* role: { type: 'ENUM', enum: ['admin','user'], defaultValue: 'user' },
|
|
21
|
+
* createdAt: { type: 'DATE' },
|
|
22
|
+
* },
|
|
23
|
+
* associations: [
|
|
24
|
+
* { type: 'hasMany', target: 'Post', foreignKey: 'userId', as: 'posts' },
|
|
25
|
+
* { type: 'hasOne', target: 'Profile', foreignKey: 'userId' },
|
|
26
|
+
* { type: 'belongsToMany', target: 'Team', through: 'UserTeam' },
|
|
27
|
+
* ],
|
|
28
|
+
* timestamps: true,
|
|
29
|
+
* comment: 'Application users',
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* diag.save('./diagrams/User.svg');
|
|
33
|
+
* // or get SVG string: const svg = diag.generate();
|
|
34
|
+
*
|
|
35
|
+
*
|
|
36
|
+
* 2) Full ER diagram
|
|
37
|
+
* ────────────────
|
|
38
|
+
* import { ERDiagram } from './diagrams';
|
|
39
|
+
*
|
|
40
|
+
* const er = new ERDiagram({
|
|
41
|
+
* title: 'E-Commerce Schema',
|
|
42
|
+
* columns: 3,
|
|
43
|
+
* models: [ userModel, productModel, orderModel, orderItemModel ],
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* er.save('./diagrams/schema.svg');
|
|
47
|
+
*
|
|
48
|
+
*
|
|
49
|
+
* 3) CLI
|
|
50
|
+
* ────
|
|
51
|
+
* # Single model (from JSON spec)
|
|
52
|
+
* cli diagram:model --file ./User.json --out ./diagrams/User.svg
|
|
53
|
+
*
|
|
54
|
+
* # Full ER diagram (from schema JSON)
|
|
55
|
+
* cli diagram:er --file ./schema.json --out ./diagrams/er.svg
|
|
56
|
+
*
|
|
57
|
+
* # Inline model
|
|
58
|
+
* cli diagram:model --name User \
|
|
59
|
+
* --fields "id:INTEGER:pk,name:VARCHAR(100):nn,email:VARCHAR(255):uq nn" \
|
|
60
|
+
* --assoc "hasMany:Post:userId" \
|
|
61
|
+
* --out ./diagrams/User.svg
|
|
62
|
+
*
|
|
63
|
+
* ─── JSON spec format ───────────────────────────────────────────────────
|
|
64
|
+
*
|
|
65
|
+
* Single model file:
|
|
66
|
+
* {
|
|
67
|
+
* "name": "User",
|
|
68
|
+
* "tableName": "users",
|
|
69
|
+
* "fields": {
|
|
70
|
+
* "id": { "type": "INTEGER", "primaryKey": true, "autoIncrement": true },
|
|
71
|
+
* "email": { "type": "VARCHAR(255)", "unique": true, "allowNull": false }
|
|
72
|
+
* },
|
|
73
|
+
* "associations": [
|
|
74
|
+
* { "type": "hasMany", "target": "Post", "foreignKey": "userId" }
|
|
75
|
+
* ],
|
|
76
|
+
* "timestamps": true
|
|
77
|
+
* }
|
|
78
|
+
*
|
|
79
|
+
* ER schema file:
|
|
80
|
+
* {
|
|
81
|
+
* "title": "My App Schema",
|
|
82
|
+
* "columns": 3,
|
|
83
|
+
* "models": [ <model-spec>, <model-spec>, … ]
|
|
84
|
+
* }
|
|
85
|
+
*/
|
|
86
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
87
|
+
exports.ACCENT_PALETTES = exports.rotatedPalettes = exports.resolveTheme = exports.resolveAccent = exports.El = exports.SvgDocument = exports.GanttDiagram = exports.PackageDiagram = exports.ChenDiagram = exports.TreeDiagram = exports.FlowDiagram = exports.IndexDiagram = exports.SchemaDocDiagram = exports.DependencyDiagram = exports.StateDiagram = exports.SequenceDiagram = exports.RelationalDiagram = exports.ClassDiagram = exports.MigrationDiagram = exports.ERDiagram = exports.ModelDiagram = void 0;
|
|
88
|
+
exports.generateModelDiagram = generateModelDiagram;
|
|
89
|
+
exports.generateERDiagram = generateERDiagram;
|
|
90
|
+
exports.generateModelDiagramFromFile = generateModelDiagramFromFile;
|
|
91
|
+
exports.generateERDiagramFromFile = generateERDiagramFromFile;
|
|
92
|
+
var model_diagram_1 = require("./model-diagram");
|
|
93
|
+
Object.defineProperty(exports, "ModelDiagram", { enumerable: true, get: function () { return model_diagram_1.ModelDiagram; } });
|
|
94
|
+
var er_diagram_1 = require("./er-diagram");
|
|
95
|
+
Object.defineProperty(exports, "ERDiagram", { enumerable: true, get: function () { return er_diagram_1.ERDiagram; } });
|
|
96
|
+
var migration_diagram_1 = require("./migration-diagram");
|
|
97
|
+
Object.defineProperty(exports, "MigrationDiagram", { enumerable: true, get: function () { return migration_diagram_1.MigrationDiagram; } });
|
|
98
|
+
// ─── Extended diagram generators (all built on the shared DOM SVG builder) ──
|
|
99
|
+
var class_diagram_1 = require("./class-diagram");
|
|
100
|
+
Object.defineProperty(exports, "ClassDiagram", { enumerable: true, get: function () { return class_diagram_1.ClassDiagram; } });
|
|
101
|
+
var relational_diagram_1 = require("./relational-diagram");
|
|
102
|
+
Object.defineProperty(exports, "RelationalDiagram", { enumerable: true, get: function () { return relational_diagram_1.RelationalDiagram; } });
|
|
103
|
+
var sequence_diagram_1 = require("./sequence-diagram");
|
|
104
|
+
Object.defineProperty(exports, "SequenceDiagram", { enumerable: true, get: function () { return sequence_diagram_1.SequenceDiagram; } });
|
|
105
|
+
var state_diagram_1 = require("./state-diagram");
|
|
106
|
+
Object.defineProperty(exports, "StateDiagram", { enumerable: true, get: function () { return state_diagram_1.StateDiagram; } });
|
|
107
|
+
var dependency_diagram_1 = require("./dependency-diagram");
|
|
108
|
+
Object.defineProperty(exports, "DependencyDiagram", { enumerable: true, get: function () { return dependency_diagram_1.DependencyDiagram; } });
|
|
109
|
+
var schemadoc_diagram_1 = require("./schemadoc-diagram");
|
|
110
|
+
Object.defineProperty(exports, "SchemaDocDiagram", { enumerable: true, get: function () { return schemadoc_diagram_1.SchemaDocDiagram; } });
|
|
111
|
+
var index_diagram_1 = require("./index-diagram");
|
|
112
|
+
Object.defineProperty(exports, "IndexDiagram", { enumerable: true, get: function () { return index_diagram_1.IndexDiagram; } });
|
|
113
|
+
var flow_diagram_1 = require("./flow-diagram");
|
|
114
|
+
Object.defineProperty(exports, "FlowDiagram", { enumerable: true, get: function () { return flow_diagram_1.FlowDiagram; } });
|
|
115
|
+
var tree_diagram_1 = require("./tree-diagram");
|
|
116
|
+
Object.defineProperty(exports, "TreeDiagram", { enumerable: true, get: function () { return tree_diagram_1.TreeDiagram; } });
|
|
117
|
+
var chen_diagram_1 = require("./chen-diagram");
|
|
118
|
+
Object.defineProperty(exports, "ChenDiagram", { enumerable: true, get: function () { return chen_diagram_1.ChenDiagram; } });
|
|
119
|
+
var package_diagram_1 = require("./package-diagram");
|
|
120
|
+
Object.defineProperty(exports, "PackageDiagram", { enumerable: true, get: function () { return package_diagram_1.PackageDiagram; } });
|
|
121
|
+
var gantt_diagram_1 = require("./gantt-diagram");
|
|
122
|
+
Object.defineProperty(exports, "GanttDiagram", { enumerable: true, get: function () { return gantt_diagram_1.GanttDiagram; } });
|
|
123
|
+
// Shared DOM SVG builder + palette (exposed for custom generators)
|
|
124
|
+
var svg_dom_1 = require("./svg-dom");
|
|
125
|
+
Object.defineProperty(exports, "SvgDocument", { enumerable: true, get: function () { return svg_dom_1.SvgDocument; } });
|
|
126
|
+
Object.defineProperty(exports, "El", { enumerable: true, get: function () { return svg_dom_1.El; } });
|
|
127
|
+
var palette_1 = require("./palette");
|
|
128
|
+
Object.defineProperty(exports, "resolveAccent", { enumerable: true, get: function () { return palette_1.resolveAccent; } });
|
|
129
|
+
Object.defineProperty(exports, "resolveTheme", { enumerable: true, get: function () { return palette_1.resolveTheme; } });
|
|
130
|
+
Object.defineProperty(exports, "rotatedPalettes", { enumerable: true, get: function () { return palette_1.rotatedPalettes; } });
|
|
131
|
+
Object.defineProperty(exports, "ACCENT_PALETTES", { enumerable: true, get: function () { return palette_1.ACCENT_PALETTES; } });
|
|
132
|
+
// ─── Convenience factory functions ──────────────────────────────────────────
|
|
133
|
+
const model_diagram_2 = require("./model-diagram");
|
|
134
|
+
const er_diagram_2 = require("./er-diagram");
|
|
135
|
+
/**
|
|
136
|
+
* Create and immediately save a model SVG diagram.
|
|
137
|
+
*
|
|
138
|
+
* @param options Model definition
|
|
139
|
+
* @param outPath Output SVG file path
|
|
140
|
+
* @returns Resolved output path
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* generateModelDiagram(
|
|
144
|
+
* { name:'User', fields:{ id:{type:'INTEGER',primaryKey:true} } },
|
|
145
|
+
* './diagrams/User.svg'
|
|
146
|
+
* );
|
|
147
|
+
*/
|
|
148
|
+
function generateModelDiagram(options, outPath) {
|
|
149
|
+
return new model_diagram_2.ModelDiagram(options).save(outPath);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Create and immediately save an ER diagram.
|
|
153
|
+
*
|
|
154
|
+
* @param options ER diagram options (title + models array)
|
|
155
|
+
* @param outPath Output SVG file path
|
|
156
|
+
* @returns Resolved output path
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* generateERDiagram(
|
|
160
|
+
* { title:'My Schema', models:[userDef, postDef] },
|
|
161
|
+
* './diagrams/schema.svg'
|
|
162
|
+
* );
|
|
163
|
+
*/
|
|
164
|
+
function generateERDiagram(options, outPath) {
|
|
165
|
+
return new er_diagram_2.ERDiagram(options).save(outPath);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Load a model definition from a JSON file and generate its SVG diagram.
|
|
169
|
+
*/
|
|
170
|
+
function generateModelDiagramFromFile(specPath, outPath) {
|
|
171
|
+
const raw = require('fs').readFileSync(specPath, 'utf-8');
|
|
172
|
+
const options = JSON.parse(raw);
|
|
173
|
+
const dest = outPath ?? specPath.replace(/\.json$/, '.svg');
|
|
174
|
+
return generateModelDiagram(options, dest);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Load an ER schema from a JSON file and generate the SVG diagram.
|
|
178
|
+
*/
|
|
179
|
+
function generateERDiagramFromFile(schemaPath, outPath) {
|
|
180
|
+
const raw = require('fs').readFileSync(schemaPath, 'utf-8');
|
|
181
|
+
const options = JSON.parse(raw);
|
|
182
|
+
const dest = outPath ?? schemaPath.replace(/\.json$/, '.svg');
|
|
183
|
+
return generateERDiagram(options, dest);
|
|
184
|
+
}
|