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.
Files changed (310) hide show
  1. package/CHANGELOG.md +1111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +573 -0
  4. package/dist/audit/history-query.js +180 -0
  5. package/dist/audit/index.js +23 -0
  6. package/dist/audit/logger.js +236 -0
  7. package/dist/cache/cache-manager.js +84 -0
  8. package/dist/cache/index.js +16 -0
  9. package/dist/cache/redis-cluster-cache.js +557 -0
  10. package/dist/cli.js +2200 -0
  11. package/dist/compliance/audit-trail.js +68 -0
  12. package/dist/compliance/backup-verification.js +685 -0
  13. package/dist/compliance/breach-detector.js +505 -0
  14. package/dist/compliance/consent-record.js +227 -0
  15. package/dist/compliance/consent-versioning.js +331 -0
  16. package/dist/compliance/cross-border-log.js +530 -0
  17. package/dist/compliance/data-classifier.js +258 -0
  18. package/dist/compliance/data-lineage.js +565 -0
  19. package/dist/compliance/data-masker.js +303 -0
  20. package/dist/compliance/data-portability.js +265 -0
  21. package/dist/compliance/data-retention.js +195 -0
  22. package/dist/compliance/dsar-workflow.js +342 -0
  23. package/dist/compliance/field-encryption.js +223 -0
  24. package/dist/compliance/immutable-record.js +148 -0
  25. package/dist/compliance/index.js +260 -0
  26. package/dist/compliance/privacy-impact-assessment.js +364 -0
  27. package/dist/compliance/pseudonymization.js +269 -0
  28. package/dist/compliance/query-firewall.js +1182 -0
  29. package/dist/compliance/rate-limiter.js +580 -0
  30. package/dist/compliance/right-to-erasure.js +117 -0
  31. package/dist/compliance/row-level-security.js +246 -0
  32. package/dist/compliance/security-decorator.js +574 -0
  33. package/dist/compliance/security-monitor.js +525 -0
  34. package/dist/compliance/sensitive-data-discovery.js +476 -0
  35. package/dist/compliance/session-isolation.js +472 -0
  36. package/dist/compliance/tls-enforcer.js +108 -0
  37. package/dist/compliance/worm-storage.js +712 -0
  38. package/dist/connection-manager.js +198 -0
  39. package/dist/connection-pool.js +519 -0
  40. package/dist/decorators/audit.js +136 -0
  41. package/dist/decorators/belongs-to-many.js +115 -0
  42. package/dist/decorators/belongs-to.js +115 -0
  43. package/dist/decorators/check.js +435 -0
  44. package/dist/decorators/collate.js +329 -0
  45. package/dist/decorators/comment.js +205 -0
  46. package/dist/decorators/database-settings.js +236 -0
  47. package/dist/decorators/default.js +244 -0
  48. package/dist/decorators/encryption.js +235 -0
  49. package/dist/decorators/engine.js +97 -0
  50. package/dist/decorators/fk-constraints.js +594 -0
  51. package/dist/decorators/foreign-table.js +136 -0
  52. package/dist/decorators/generated.js +274 -0
  53. package/dist/decorators/has-many.js +127 -0
  54. package/dist/decorators/has-one.js +116 -0
  55. package/dist/decorators/hstore.js +129 -0
  56. package/dist/decorators/index.js +355 -0
  57. package/dist/decorators/json-column.js +83 -0
  58. package/dist/decorators/jsonb.js +101 -0
  59. package/dist/decorators/orm-decorators.js +425 -0
  60. package/dist/decorators/permissions.js +294 -0
  61. package/dist/decorators/procedure.js +210 -0
  62. package/dist/decorators/query-options.js +556 -0
  63. package/dist/decorators/range.js +167 -0
  64. package/dist/decorators/set-column.js +83 -0
  65. package/dist/decorators/spatial.js +114 -0
  66. package/dist/decorators/storage.js +580 -0
  67. package/dist/decorators/timezone.js +512 -0
  68. package/dist/decorators/trigger.js +90 -0
  69. package/dist/decorators/uuid.js +135 -0
  70. package/dist/decorators/view.js +258 -0
  71. package/dist/diagrams/chen-diagram.js +354 -0
  72. package/dist/diagrams/class-diagram.js +384 -0
  73. package/dist/diagrams/dependency-diagram.js +432 -0
  74. package/dist/diagrams/er-diagram.js +605 -0
  75. package/dist/diagrams/flow-diagram.js +394 -0
  76. package/dist/diagrams/gantt-diagram.js +411 -0
  77. package/dist/diagrams/index-diagram.js +353 -0
  78. package/dist/diagrams/index.js +184 -0
  79. package/dist/diagrams/migration-diagram.js +316 -0
  80. package/dist/diagrams/model-diagram.js +616 -0
  81. package/dist/diagrams/package-diagram.js +376 -0
  82. package/dist/diagrams/palette.js +85 -0
  83. package/dist/diagrams/relational-diagram.js +455 -0
  84. package/dist/diagrams/schemadoc-diagram.js +309 -0
  85. package/dist/diagrams/sequence-diagram.js +307 -0
  86. package/dist/diagrams/state-diagram.js +344 -0
  87. package/dist/diagrams/svg-dom.js +111 -0
  88. package/dist/diagrams/tree-diagram.js +250 -0
  89. package/dist/dialects/clickhouse/index.js +1742 -0
  90. package/dist/dialects/cockroachdb/index.js +4677 -0
  91. package/dist/dialects/cratedb/index.js +441 -0
  92. package/dist/dialects/databricks/index.js +517 -0
  93. package/dist/dialects/db2/index.js +2225 -0
  94. package/dist/dialects/dialect.js +720 -0
  95. package/dist/dialects/duckdb/index.js +2014 -0
  96. package/dist/dialects/exasol/index.js +357 -0
  97. package/dist/dialects/firebird/index.js +495 -0
  98. package/dist/dialects/greenplum/index.js +457 -0
  99. package/dist/dialects/hana/index.js +1741 -0
  100. package/dist/dialects/mariadb/index.js +3590 -0
  101. package/dist/dialects/mssql/index.js +2296 -0
  102. package/dist/dialects/mysql/index.js +4058 -0
  103. package/dist/dialects/oracle/index.js +2999 -0
  104. package/dist/dialects/postgres/index.js +5319 -0
  105. package/dist/dialects/query-stream-helper.js +152 -0
  106. package/dist/dialects/questdb/index.js +433 -0
  107. package/dist/dialects/redshift/index.js +2277 -0
  108. package/dist/dialects/singlestore/index.js +354 -0
  109. package/dist/dialects/snowflake/index.js +2082 -0
  110. package/dist/dialects/spanner/index.js +1768 -0
  111. package/dist/dialects/sqlite/index.js +3382 -0
  112. package/dist/dialects/tidb/index.js +377 -0
  113. package/dist/dialects/timescaledb/index.js +164 -0
  114. package/dist/dialects/trino/index.js +420 -0
  115. package/dist/dialects/turso/index.js +227 -0
  116. package/dist/dialects/vertica/index.js +317 -0
  117. package/dist/dialects/yugabytedb/index.js +424 -0
  118. package/dist/errors/index.js +472 -0
  119. package/dist/errors/utils.js +340 -0
  120. package/dist/errors.js +21 -0
  121. package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
  122. package/dist/extensions/catalog/mssql-features.js +147 -0
  123. package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
  124. package/dist/extensions/catalog/oracle-db2-features.js +196 -0
  125. package/dist/extensions/catalog/postgres-extensions.js +516 -0
  126. package/dist/extensions/index.js +71 -0
  127. package/dist/extensions/types.js +13 -0
  128. package/dist/foreign-data.js +173 -0
  129. package/dist/hooks/hooks-manager.js +350 -0
  130. package/dist/hooks/index.js +37 -0
  131. package/dist/index.js +463 -0
  132. package/dist/logging.js +335 -0
  133. package/dist/migrations/index.js +40 -0
  134. package/dist/migrations/migration.js +196 -0
  135. package/dist/migrations/migrator.js +411 -0
  136. package/dist/migrations/prormmigration.js +275 -0
  137. package/dist/migrations/query-interface.js +435 -0
  138. package/dist/migrations/seeder.js +353 -0
  139. package/dist/models/associations.js +852 -0
  140. package/dist/models/constraints.js +288 -0
  141. package/dist/models/data-types.js +2518 -0
  142. package/dist/models/decorators.js +445 -0
  143. package/dist/models/index.js +33 -0
  144. package/dist/models/indexes.js +531 -0
  145. package/dist/models/methods.js +382 -0
  146. package/dist/models/model-manager.js +103 -0
  147. package/dist/models/model.js +5349 -0
  148. package/dist/models/operators.js +67 -0
  149. package/dist/models/scopes.js +189 -0
  150. package/dist/models/typescript-types.js +26 -0
  151. package/dist/nosql/aerospike/index.js +205 -0
  152. package/dist/nosql/allegrograph/index.js +169 -0
  153. package/dist/nosql/arangodb/index.js +364 -0
  154. package/dist/nosql/azure-blob/index.js +206 -0
  155. package/dist/nosql/beanstalkd/index.js +231 -0
  156. package/dist/nosql/beequeue/index.js +210 -0
  157. package/dist/nosql/bigchaindb/index.js +195 -0
  158. package/dist/nosql/bigtable/index.js +224 -0
  159. package/dist/nosql/blazegraph/index.js +173 -0
  160. package/dist/nosql/bullmq/index.js +191 -0
  161. package/dist/nosql/cassandra/index.js +174 -0
  162. package/dist/nosql/chroma/index.js +190 -0
  163. package/dist/nosql/cloudflare-kv/index.js +220 -0
  164. package/dist/nosql/coherence/index.js +200 -0
  165. package/dist/nosql/cosmosdb/index.js +157 -0
  166. package/dist/nosql/couchbase/index.js +213 -0
  167. package/dist/nosql/dax/index.js +212 -0
  168. package/dist/nosql/deno-kv/index.js +206 -0
  169. package/dist/nosql/dgraph/index.js +171 -0
  170. package/dist/nosql/doris/index.js +169 -0
  171. package/dist/nosql/druid/index.js +162 -0
  172. package/dist/nosql/dynamodb/index.js +937 -0
  173. package/dist/nosql/elasticsearch/index.js +377 -0
  174. package/dist/nosql/etcd/index.js +502 -0
  175. package/dist/nosql/eventhubs/index.js +213 -0
  176. package/dist/nosql/eventstore/index.js +254 -0
  177. package/dist/nosql/faunadb/index.js +188 -0
  178. package/dist/nosql/firestore/index.js +177 -0
  179. package/dist/nosql/fluree/index.js +148 -0
  180. package/dist/nosql/fuseki/index.js +170 -0
  181. package/dist/nosql/gcs/index.js +172 -0
  182. package/dist/nosql/gearman/index.js +160 -0
  183. package/dist/nosql/geode/index.js +196 -0
  184. package/dist/nosql/graphdb/index.js +169 -0
  185. package/dist/nosql/graylog/index.js +188 -0
  186. package/dist/nosql/gridgain/index.js +171 -0
  187. package/dist/nosql/hazelcast/index.js +162 -0
  188. package/dist/nosql/hbase/index.js +230 -0
  189. package/dist/nosql/ignite/index.js +173 -0
  190. package/dist/nosql/immudb/index.js +184 -0
  191. package/dist/nosql/index.js +232 -0
  192. package/dist/nosql/infinispan/index.js +200 -0
  193. package/dist/nosql/influxdb/index.js +0 -0
  194. package/dist/nosql/kafka/index.js +234 -0
  195. package/dist/nosql/keyspaces/index.js +189 -0
  196. package/dist/nosql/kinesis/index.js +253 -0
  197. package/dist/nosql/leveldb/index.js +153 -0
  198. package/dist/nosql/lmdb/index.js +160 -0
  199. package/dist/nosql/loki/index.js +201 -0
  200. package/dist/nosql/marklogic/index.js +204 -0
  201. package/dist/nosql/materialize/index.js +145 -0
  202. package/dist/nosql/meilisearch/index.js +154 -0
  203. package/dist/nosql/memcached/index.js +223 -0
  204. package/dist/nosql/milvus/index.js +410 -0
  205. package/dist/nosql/minio/index.js +265 -0
  206. package/dist/nosql/momento/index.js +179 -0
  207. package/dist/nosql/mongodb/index.js +461 -0
  208. package/dist/nosql/nats/index.js +247 -0
  209. package/dist/nosql/nedb/index.js +164 -0
  210. package/dist/nosql/neo4j/index.js +450 -0
  211. package/dist/nosql/neptune/index.js +470 -0
  212. package/dist/nosql/nsq/index.js +200 -0
  213. package/dist/nosql/opensearch/index.js +186 -0
  214. package/dist/nosql/orientdb/index.js +175 -0
  215. package/dist/nosql/papertrail/index.js +200 -0
  216. package/dist/nosql/pinecone/index.js +0 -0
  217. package/dist/nosql/pinot/index.js +133 -0
  218. package/dist/nosql/pouchdb/index.js +172 -0
  219. package/dist/nosql/prometheus/index.js +174 -0
  220. package/dist/nosql/provendb/index.js +147 -0
  221. package/dist/nosql/pubsub/index.js +187 -0
  222. package/dist/nosql/pulsar/index.js +232 -0
  223. package/dist/nosql/qdrant/index.js +295 -0
  224. package/dist/nosql/qldb/index.js +192 -0
  225. package/dist/nosql/r2/index.js +281 -0
  226. package/dist/nosql/rabbitmq/index.js +237 -0
  227. package/dist/nosql/ravendb/index.js +175 -0
  228. package/dist/nosql/redis/index.js +607 -0
  229. package/dist/nosql/redpanda/index.js +237 -0
  230. package/dist/nosql/resque/index.js +203 -0
  231. package/dist/nosql/rethinkdb/index.js +232 -0
  232. package/dist/nosql/rocksdb/index.js +152 -0
  233. package/dist/nosql/rockset/index.js +126 -0
  234. package/dist/nosql/s3/index.js +298 -0
  235. package/dist/nosql/scylladb/index.js +178 -0
  236. package/dist/nosql/signoz/index.js +227 -0
  237. package/dist/nosql/sns/index.js +201 -0
  238. package/dist/nosql/solr/index.js +231 -0
  239. package/dist/nosql/splunk/index.js +227 -0
  240. package/dist/nosql/sqs/index.js +246 -0
  241. package/dist/nosql/stardog/index.js +169 -0
  242. package/dist/nosql/starrocks/index.js +170 -0
  243. package/dist/nosql/store.js +2 -0
  244. package/dist/nosql/sumologic/index.js +213 -0
  245. package/dist/nosql/surrealdb/index.js +179 -0
  246. package/dist/nosql/terminusdb/index.js +151 -0
  247. package/dist/nosql/tigergraph/index.js +469 -0
  248. package/dist/nosql/typesense/index.js +148 -0
  249. package/dist/nosql/unqlite/index.js +157 -0
  250. package/dist/nosql/upstash/index.js +167 -0
  251. package/dist/nosql/vercel-kv/index.js +166 -0
  252. package/dist/nosql/victoriametrics/index.js +213 -0
  253. package/dist/nosql/virtuoso/index.js +169 -0
  254. package/dist/nosql/weaviate/index.js +276 -0
  255. package/dist/operators/index.js +108 -0
  256. package/dist/operators.js +2690 -0
  257. package/dist/prisma-migrate/index.js +38 -0
  258. package/dist/prisma-migrate/migration-generator.js +125 -0
  259. package/dist/prisma-migrate/model-generator.js +172 -0
  260. package/dist/prisma-migrate/relations.js +100 -0
  261. package/dist/prisma-migrate/schema-parser.js +167 -0
  262. package/dist/prisma-migrate/type-mapper.js +40 -0
  263. package/dist/prorm.js +6832 -0
  264. package/dist/query-builders/cte-builder.js +80 -0
  265. package/dist/query-builders/functions/aggregate.js +390 -0
  266. package/dist/query-builders/functions/conditional.js +503 -0
  267. package/dist/query-builders/functions/datetime.js +695 -0
  268. package/dist/query-builders/functions/fulltext.js +439 -0
  269. package/dist/query-builders/functions/index.js +93 -0
  270. package/dist/query-builders/functions/json.js +427 -0
  271. package/dist/query-builders/functions/math.js +399 -0
  272. package/dist/query-builders/functions/string.js +518 -0
  273. package/dist/query-builders/functions/window.js +328 -0
  274. package/dist/query-builders/include-builder.js +323 -0
  275. package/dist/query-builders/index-expression-builder.js +242 -0
  276. package/dist/query-builders/index.js +161 -0
  277. package/dist/query-builders/insert-builder.js +164 -0
  278. package/dist/query-builders/model-helpers.js +38 -0
  279. package/dist/query-builders/order-limit-builder.js +239 -0
  280. package/dist/query-builders/sql-compiler.js +2040 -0
  281. package/dist/query-builders/subquery-builder.js +152 -0
  282. package/dist/query-builders/update-builder.js +182 -0
  283. package/dist/query-builders/view-builder.js +218 -0
  284. package/dist/query-builders/where-builder.js +1532 -0
  285. package/dist/query-interface.js +622 -0
  286. package/dist/query-optimizers/batch-optimizer.js +426 -0
  287. package/dist/query-optimizers/explain-plans.js +415 -0
  288. package/dist/query-optimizers/index.js +51 -0
  289. package/dist/query-optimizers/prepared-statement-cache.js +423 -0
  290. package/dist/query-optimizers/query-hints.js +438 -0
  291. package/dist/query-optimizers/query-optimizer.js +278 -0
  292. package/dist/query-optimizers/slow-query-logger.js +271 -0
  293. package/dist/replica-manager.js +507 -0
  294. package/dist/schema/index.js +15 -0
  295. package/dist/schema/migration-generator.js +374 -0
  296. package/dist/schema/schema-differ.js +549 -0
  297. package/dist/schema/types.js +6 -0
  298. package/dist/sql-constants.js +300 -0
  299. package/dist/sqlite-advanced.js +1047 -0
  300. package/dist/streams/index.js +12 -0
  301. package/dist/streams/transforms.js +178 -0
  302. package/dist/transaction.js +456 -0
  303. package/dist/types/index.js +180 -0
  304. package/dist/user-management.js +127 -0
  305. package/dist/utils/date.js +300 -0
  306. package/dist/utils/index.js +1079 -0
  307. package/dist/utils/string.js +161 -0
  308. package/dist/validators/index.js +19 -0
  309. package/dist/validators/validator.js +911 -0
  310. package/package.json +190 -0
@@ -0,0 +1,309 @@
1
+ "use strict";
2
+ /**
3
+ * SchemaDocDiagram — generates a print-friendly "data dictionary" / schema
4
+ * documentation sheet as SVG.
5
+ *
6
+ * Where ERDiagram / ModelDiagram render the *visual* shape of a schema, this
7
+ * generator renders the *reference* counterpart: for every table a titled
8
+ * section followed by a tabular grid with one row per column, listing
9
+ * Column · Type · Nullable · Key · Default · Description. Rows are
10
+ * zebra-striped and each grid's header row is painted in the accent color.
11
+ * A document title banner and a summary line ("N tables, M columns") top the
12
+ * sheet.
13
+ *
14
+ * All markup is built against a real DOM document (see ./svg-dom) — never by
15
+ * concatenating strings — and both `--theme` and `--color` genuinely change
16
+ * fill/stroke values in the output.
17
+ *
18
+ * Usage:
19
+ * const doc = new SchemaDocDiagram({ tables: [...], title: 'My Schema' });
20
+ * doc.save('./diagrams/schema.svg');
21
+ * // or:
22
+ * const svgString = doc.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.SchemaDocDiagram = 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
+ // ─── Layout constants (px) ──────────────────────────────────────────────────
64
+ const W = 820; // content width
65
+ const PAD = 28; // outer canvas padding
66
+ const BANNER_H = 78; // title banner height
67
+ const SUMMARY_H = 34; // summary line strip
68
+ const SECTION_TITLE_H = 40; // per-table section title bar
69
+ const COL_HDR_H = 30; // grid header row
70
+ const ROW_H = 28; // grid data row
71
+ const SECTION_GAP = 22; // space between tables
72
+ const R = 12; // border radius
73
+ // Column layout: [label, x offset, width]
74
+ const COLS = [
75
+ { label: 'Column', x: 0, w: 170 },
76
+ { label: 'Type', x: 170, w: 140 },
77
+ { label: 'Nullable', x: 310, w: 80 },
78
+ { label: 'Key', x: 390, w: 60 },
79
+ { label: 'Default', x: 450, w: 130 },
80
+ { label: 'Description', x: 580, w: 240 },
81
+ ];
82
+ const FONT_SANS = 'system-ui,-apple-system,sans-serif';
83
+ const FONT_MONO = "'SF Mono','Fira Code',monospace";
84
+ // ─── Helpers ────────────────────────────────────────────────────────────────
85
+ /** Truncate text to roughly fit `width` px at the given font size. */
86
+ function truncate(text, width, fontSize) {
87
+ const maxChars = Math.max(1, Math.floor(width / (fontSize * 0.6)));
88
+ if (text.length <= maxChars)
89
+ return text;
90
+ if (maxChars <= 1)
91
+ return '…';
92
+ return text.slice(0, maxChars - 1) + '…';
93
+ }
94
+ // ─── Main class ────────────────────────────────────────────────────────────
95
+ class SchemaDocDiagram {
96
+ constructor(options) {
97
+ this.opts = {
98
+ tables: options.tables ?? [],
99
+ title: options.title ?? 'Schema Documentation',
100
+ theme: options.theme ?? 'light',
101
+ color: options.color ?? '',
102
+ };
103
+ }
104
+ /** Total column count across all tables. */
105
+ totalColumns() {
106
+ return this.opts.tables.reduce((n, t) => n + (t.columns?.length ?? 0), 0);
107
+ }
108
+ /** Height of one table's rendered section. */
109
+ sectionHeight(table) {
110
+ return SECTION_TITLE_H + COL_HDR_H + (table.columns?.length ?? 0) * ROW_H;
111
+ }
112
+ generate() {
113
+ const { tables, title, theme, color } = this.opts;
114
+ const accent = (0, palette_1.resolveAccent)(color);
115
+ const t = (0, palette_1.resolveTheme)(theme);
116
+ // ── Compute total height (auto-size viewBox) ────────────────────────
117
+ let contentH = BANNER_H + SUMMARY_H + 16;
118
+ tables.forEach((tbl, i) => {
119
+ contentH += this.sectionHeight(tbl);
120
+ if (i < tables.length - 1)
121
+ contentH += SECTION_GAP;
122
+ });
123
+ const svgW = W + 2 * PAD;
124
+ const svgH = contentH + 2 * PAD;
125
+ const cx = PAD;
126
+ const doc = new svg_dom_1.SvgDocument(svgW, svgH);
127
+ const svg = doc.root;
128
+ // ── Canvas background (theme) ───────────────────────────────────────
129
+ svg.child('rect', { width: svgW, height: svgH, fill: t.canvasBg });
130
+ // ── Title banner (accent) ───────────────────────────────────────────
131
+ const uid = 'sd';
132
+ doc.linearGradient(`bg${uid}`, [
133
+ [0, accent.from],
134
+ [100, accent.mid],
135
+ ]);
136
+ svg.child('rect', {
137
+ x: cx,
138
+ y: PAD,
139
+ width: W,
140
+ height: BANNER_H,
141
+ rx: R,
142
+ fill: `url(#bg${uid})`,
143
+ });
144
+ svg
145
+ .child('text', {
146
+ x: cx + 22,
147
+ y: PAD + 34,
148
+ 'font-family': FONT_SANS,
149
+ 'font-size': 24,
150
+ 'font-weight': 800,
151
+ fill: '#FFFFFF',
152
+ })
153
+ .text(truncate(title, W - 44, 24));
154
+ svg
155
+ .child('text', {
156
+ x: cx + 22,
157
+ y: PAD + 58,
158
+ 'font-family': FONT_SANS,
159
+ 'font-size': 12,
160
+ 'font-weight': 600,
161
+ fill: 'rgba(255,255,255,0.85)',
162
+ 'letter-spacing': 1,
163
+ })
164
+ .text('DATA DICTIONARY');
165
+ // ── Summary line ────────────────────────────────────────────────────
166
+ const summaryY = PAD + BANNER_H + 8;
167
+ const tableCount = tables.length;
168
+ const colCount = this.totalColumns();
169
+ svg
170
+ .child('text', {
171
+ x: cx + 4,
172
+ y: summaryY + 22,
173
+ 'font-family': FONT_SANS,
174
+ 'font-size': 13,
175
+ 'font-weight': 600,
176
+ fill: t.textSecondary,
177
+ })
178
+ .text(`${tableCount} table${tableCount !== 1 ? 's' : ''}, ${colCount} column${colCount !== 1 ? 's' : ''}`);
179
+ // ── Table sections ──────────────────────────────────────────────────
180
+ let y = summaryY + SUMMARY_H + 8;
181
+ tables.forEach((table) => {
182
+ y = this.drawTable(doc, svg, table, cx, y, accent, t);
183
+ y += SECTION_GAP;
184
+ });
185
+ return doc.toString('Generated by ts-prorm-orm SchemaDocDiagram');
186
+ }
187
+ /** Draw one table section starting at `y`; returns the y after the section. */
188
+ drawTable(doc, svg, table, cx, y, accent, t) {
189
+ const columns = table.columns ?? [];
190
+ // ── Section title bar ─────────────────────────────────────────────
191
+ svg.child('rect', {
192
+ x: cx,
193
+ y,
194
+ width: W,
195
+ height: SECTION_TITLE_H,
196
+ rx: 8,
197
+ fill: t.colHeaderBg,
198
+ });
199
+ svg.child('rect', { x: cx, y, width: 5, height: SECTION_TITLE_H, fill: accent.mid });
200
+ svg
201
+ .child('text', {
202
+ x: cx + 18,
203
+ y: y + 26,
204
+ 'font-family': FONT_MONO,
205
+ 'font-size': 16,
206
+ 'font-weight': 700,
207
+ fill: t.textPrimary,
208
+ })
209
+ .text(truncate(table.name, 420, 16));
210
+ if (table.comment) {
211
+ svg
212
+ .child('text', {
213
+ x: cx + W - 14,
214
+ y: y + 26,
215
+ 'font-family': FONT_SANS,
216
+ 'font-size': 11,
217
+ fill: t.textSecondary,
218
+ 'text-anchor': 'end',
219
+ })
220
+ .text(truncate(table.comment, 340, 11));
221
+ }
222
+ // ── Grid header row (accent) ──────────────────────────────────────
223
+ const gridX = cx;
224
+ let rowY = y + SECTION_TITLE_H;
225
+ svg.child('rect', {
226
+ x: gridX,
227
+ y: rowY,
228
+ width: W,
229
+ height: COL_HDR_H,
230
+ fill: accent.from,
231
+ });
232
+ COLS.forEach((c) => {
233
+ svg
234
+ .child('text', {
235
+ x: gridX + c.x + 10,
236
+ y: rowY + 20,
237
+ 'font-family': FONT_SANS,
238
+ 'font-size': 11,
239
+ 'font-weight': 700,
240
+ fill: '#FFFFFF',
241
+ 'letter-spacing': 0.4,
242
+ })
243
+ .text(c.label);
244
+ });
245
+ // ── Data rows (zebra) ─────────────────────────────────────────────
246
+ rowY += COL_HDR_H;
247
+ columns.forEach((col, i) => {
248
+ const rowBg = i % 2 === 0 ? t.cardBg : t.rowAlt;
249
+ svg.child('rect', { x: gridX, y: rowY, width: W, height: ROW_H, fill: rowBg });
250
+ const baseY = rowY + 18;
251
+ const cell = (idx, value, opts) => {
252
+ const c = COLS[idx];
253
+ const fs = 12;
254
+ svg
255
+ .child('text', {
256
+ x: gridX + c.x + 10,
257
+ y: baseY,
258
+ 'font-family': opts?.mono ? FONT_MONO : FONT_SANS,
259
+ 'font-size': fs,
260
+ fill: opts?.fill ?? t.textPrimary,
261
+ })
262
+ .text(truncate(value, c.w - 16, fs));
263
+ };
264
+ cell(0, col.name, { mono: true, fill: t.textPrimary });
265
+ cell(1, col.type, { mono: true, fill: t.textSecondary });
266
+ cell(2, col.nullable === false ? 'NO' : 'YES', {
267
+ fill: col.nullable === false ? accent.mid : t.textSecondary,
268
+ });
269
+ cell(3, col.key ?? '', { mono: true, fill: accent.text });
270
+ cell(4, col.default != null ? String(col.default) : '', {
271
+ mono: true,
272
+ fill: t.textSecondary,
273
+ });
274
+ cell(5, col.description ?? '', { fill: t.textSecondary });
275
+ svg.child('line', {
276
+ x1: gridX,
277
+ y1: rowY + ROW_H,
278
+ x2: gridX + W,
279
+ y2: rowY + ROW_H,
280
+ stroke: t.border,
281
+ 'stroke-width': 1,
282
+ });
283
+ rowY += ROW_H;
284
+ });
285
+ // ── Grid outline ──────────────────────────────────────────────────
286
+ svg.child('rect', {
287
+ x: gridX,
288
+ y: y + SECTION_TITLE_H,
289
+ width: W,
290
+ height: COL_HDR_H + columns.length * ROW_H,
291
+ fill: 'none',
292
+ stroke: t.border,
293
+ 'stroke-width': 1,
294
+ });
295
+ return y + this.sectionHeight(table);
296
+ }
297
+ /**
298
+ * Write the SVG to a file. Creates parent directories if needed.
299
+ */
300
+ save(outputPath) {
301
+ const resolved = path.resolve(outputPath);
302
+ const dir = path.dirname(resolved);
303
+ if (!fs.existsSync(dir))
304
+ fs.mkdirSync(dir, { recursive: true });
305
+ fs.writeFileSync(resolved, this.generate(), 'utf-8');
306
+ return resolved;
307
+ }
308
+ }
309
+ exports.SchemaDocDiagram = SchemaDocDiagram;
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ /**
3
+ * SequenceDiagram — generates a UML sequence diagram as an SVG.
4
+ *
5
+ * Renders participants (actors / objects / databases) as header boxes across
6
+ * the top, each dropping a vertical dashed lifeline. Messages are drawn as
7
+ * numbered horizontal arrows between lifelines in order: a solid arrow is a
8
+ * synchronous call, a dashed arrow is a return / async message. Activation
9
+ * bars (thin rectangles) are drawn on a lifeline while it is active.
10
+ *
11
+ * The accent color (via resolveAccent) drives participant header boxes and
12
+ * arrowheads; the theme (via resolveTheme) drives the canvas, lifelines and
13
+ * text. Both `theme` and `color` genuinely change fill/stroke values in the
14
+ * generated SVG. The viewBox is auto-sized to fit all content.
15
+ *
16
+ * Usage:
17
+ * const diag = new SequenceDiagram({ participants: […], messages: […] });
18
+ * diag.save('./diagrams/flow.svg');
19
+ * // or:
20
+ * const svgString = diag.generate();
21
+ */
22
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ var desc = Object.getOwnPropertyDescriptor(m, k);
25
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
26
+ desc = { enumerable: true, get: function() { return m[k]; } };
27
+ }
28
+ Object.defineProperty(o, k2, desc);
29
+ }) : (function(o, m, k, k2) {
30
+ if (k2 === undefined) k2 = k;
31
+ o[k2] = m[k];
32
+ }));
33
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
34
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
35
+ }) : function(o, v) {
36
+ o["default"] = v;
37
+ });
38
+ var __importStar = (this && this.__importStar) || (function () {
39
+ var ownKeys = function(o) {
40
+ ownKeys = Object.getOwnPropertyNames || function (o) {
41
+ var ar = [];
42
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
43
+ return ar;
44
+ };
45
+ return ownKeys(o);
46
+ };
47
+ return function (mod) {
48
+ if (mod && mod.__esModule) return mod;
49
+ var result = {};
50
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
51
+ __setModuleDefault(result, mod);
52
+ return result;
53
+ };
54
+ })();
55
+ Object.defineProperty(exports, "__esModule", { value: true });
56
+ exports.SequenceDiagram = void 0;
57
+ const fs = __importStar(require("fs"));
58
+ const path = __importStar(require("path"));
59
+ const palette_1 = require("./palette");
60
+ const svg_dom_1 = require("./svg-dom");
61
+ // ─── Main class ────────────────────────────────────────────────────────────
62
+ class SequenceDiagram {
63
+ constructor(options) {
64
+ this.opts = {
65
+ participants: options.participants ?? [],
66
+ messages: options.messages ?? [],
67
+ title: options.title ?? '',
68
+ theme: options.theme ?? 'light',
69
+ color: options.color ?? '',
70
+ };
71
+ }
72
+ /** Kind glyph drawn inside a participant header. */
73
+ kindGlyph(kind) {
74
+ if (kind === 'actor')
75
+ return '☺';
76
+ if (kind === 'database')
77
+ return '⛁';
78
+ return '▭';
79
+ }
80
+ generate() {
81
+ const { participants, messages, title, theme, color } = this.opts;
82
+ const accent = (0, palette_1.resolveAccent)(color);
83
+ const t = (0, palette_1.resolveTheme)(theme);
84
+ const PAD = SequenceDiagram.PAD;
85
+ const LANE = SequenceDiagram.LANE;
86
+ const HDR_W = SequenceDiagram.HDR_W;
87
+ const HDR_H = SequenceDiagram.HDR_H;
88
+ const TITLE_H = title ? SequenceDiagram.TITLE_H : 0;
89
+ const MSG_GAP = SequenceDiagram.MSG_GAP;
90
+ const TOP_GAP = SequenceDiagram.TOP_GAP;
91
+ const BOT_GAP = SequenceDiagram.BOT_GAP;
92
+ const ACT_W = SequenceDiagram.ACT_W;
93
+ const n = Math.max(participants.length, 1);
94
+ const m = messages.length;
95
+ // Lifeline x-centers.
96
+ const laneX = (i) => PAD + HDR_W / 2 + i * LANE;
97
+ const indexOf = (name) => {
98
+ const idx = participants.findIndex((p) => p.name === name);
99
+ return idx < 0 ? 0 : idx;
100
+ };
101
+ // Vertical geometry.
102
+ const headerTop = PAD + TITLE_H;
103
+ const headerBottom = headerTop + HDR_H;
104
+ const firstMsgY = headerBottom + TOP_GAP;
105
+ const lifelineBottom = firstMsgY + m * MSG_GAP + BOT_GAP;
106
+ const svgW = PAD * 2 + HDR_W + (n - 1) * LANE;
107
+ const svgH = lifelineBottom + PAD;
108
+ const doc = new svg_dom_1.SvgDocument(svgW, svgH);
109
+ const svg = doc.root;
110
+ // ── Canvas background (theme-driven) ────────────────────────────────
111
+ svg.child('rect', { width: svgW, height: svgH, fill: t.canvasBg });
112
+ // ── Arrowhead marker (accent-colored) ───────────────────────────────
113
+ const headId = `seqhead${accent.name.replace(/\W/g, '')}`;
114
+ const marker = doc.defs().child('marker', {
115
+ id: headId,
116
+ markerWidth: 10,
117
+ markerHeight: 10,
118
+ refX: 8,
119
+ refY: 4,
120
+ orient: 'auto',
121
+ markerUnits: 'userSpaceOnUse',
122
+ });
123
+ marker.child('path', { d: 'M0,0 L8,4 L0,8 Z', fill: accent.mid });
124
+ // ── Title ───────────────────────────────────────────────────────────
125
+ if (title) {
126
+ svg
127
+ .child('text', {
128
+ x: svgW / 2,
129
+ y: PAD + 24,
130
+ 'font-family': 'system-ui,-apple-system,sans-serif',
131
+ 'font-size': 20,
132
+ 'font-weight': 800,
133
+ fill: t.textPrimary,
134
+ 'text-anchor': 'middle',
135
+ })
136
+ .text(title);
137
+ }
138
+ // ── Lifelines (dashed, theme-colored) ───────────────────────────────
139
+ participants.forEach((_p, i) => {
140
+ const x = laneX(i);
141
+ svg.child('line', {
142
+ x1: x,
143
+ y1: headerBottom,
144
+ x2: x,
145
+ y2: lifelineBottom,
146
+ stroke: t.border,
147
+ 'stroke-width': 1.5,
148
+ 'stroke-dasharray': '6 5',
149
+ class: 'lifeline',
150
+ });
151
+ });
152
+ // ── Activation bars (drawn under arrows so arrows sit on top edge) ──
153
+ messages.forEach((msg, i) => {
154
+ if (!msg.activate)
155
+ return;
156
+ const y = firstMsgY + i * MSG_GAP;
157
+ const x = laneX(indexOf(msg.to));
158
+ // Extend the bar to the next message (or to the lifeline end).
159
+ const endY = i + 1 < m ? firstMsgY + (i + 1) * MSG_GAP : y + MSG_GAP;
160
+ svg.child('rect', {
161
+ x: x - ACT_W / 2,
162
+ y,
163
+ width: ACT_W,
164
+ height: Math.max(endY - y, MSG_GAP / 2),
165
+ fill: accent.light,
166
+ stroke: accent.mid,
167
+ 'stroke-width': 1,
168
+ class: 'activation',
169
+ });
170
+ });
171
+ // ── Participant header boxes (accent-colored) ───────────────────────
172
+ participants.forEach((p, i) => {
173
+ const cxLine = laneX(i);
174
+ const boxX = cxLine - HDR_W / 2;
175
+ svg.child('rect', {
176
+ x: boxX,
177
+ y: headerTop,
178
+ width: HDR_W,
179
+ height: HDR_H,
180
+ rx: 8,
181
+ fill: accent.from,
182
+ stroke: accent.mid,
183
+ 'stroke-width': 1.5,
184
+ class: 'participant',
185
+ });
186
+ svg
187
+ .child('text', {
188
+ x: cxLine,
189
+ y: headerTop + 20,
190
+ 'font-family': 'system-ui,-apple-system,sans-serif',
191
+ 'font-size': 13,
192
+ fill: '#FFFFFF',
193
+ 'text-anchor': 'middle',
194
+ })
195
+ .text(this.kindGlyph(p.kind));
196
+ svg
197
+ .child('text', {
198
+ x: cxLine,
199
+ y: headerTop + 38,
200
+ 'font-family': "'SF Mono','Fira Code',monospace",
201
+ 'font-size': 13,
202
+ 'font-weight': 700,
203
+ fill: '#FFFFFF',
204
+ 'text-anchor': 'middle',
205
+ })
206
+ .text(p.name.length > 16 ? p.name.slice(0, 15) + '…' : p.name);
207
+ });
208
+ // ── Messages (numbered arrows) ──────────────────────────────────────
209
+ messages.forEach((msg, i) => {
210
+ const y = firstMsgY + i * MSG_GAP;
211
+ const fromI = indexOf(msg.from);
212
+ const toI = indexOf(msg.to);
213
+ let x1 = laneX(fromI);
214
+ let x2 = laneX(toI);
215
+ const isReturn = !!msg.return;
216
+ const rightward = x2 >= x1;
217
+ // Nudge endpoints off activation bars so arrowheads stay visible.
218
+ if (x1 !== x2) {
219
+ x1 += rightward ? ACT_W / 2 : -ACT_W / 2;
220
+ x2 += rightward ? -ACT_W / 2 : ACT_W / 2;
221
+ }
222
+ if (fromI === toI) {
223
+ // Self-message: a small loop back to the same lifeline.
224
+ const w = 60;
225
+ const yb = y + 22;
226
+ svg.child('path', {
227
+ d: `M${x1},${y} h${w} v${yb - y} h-${w}`,
228
+ fill: 'none',
229
+ stroke: accent.mid,
230
+ 'stroke-width': 1.6,
231
+ 'stroke-dasharray': isReturn ? '5 4' : undefined,
232
+ 'marker-end': `url(#${headId})`,
233
+ class: isReturn ? 'message message-return' : 'message message-call',
234
+ });
235
+ }
236
+ else {
237
+ svg.child('line', {
238
+ x1,
239
+ y1: y,
240
+ x2,
241
+ y2: y,
242
+ stroke: accent.mid,
243
+ 'stroke-width': 1.6,
244
+ 'stroke-dasharray': isReturn ? '5 4' : undefined,
245
+ 'marker-end': `url(#${headId})`,
246
+ class: isReturn ? 'message message-return' : 'message message-call',
247
+ });
248
+ }
249
+ // Sequence number badge on the source side.
250
+ const badgeX = rightward ? Math.min(x1, x2) + 11 : Math.max(x1, x2) - 11;
251
+ svg.child('circle', {
252
+ cx: badgeX,
253
+ cy: y - 12,
254
+ r: 9,
255
+ fill: accent.mid,
256
+ class: 'seq-num',
257
+ });
258
+ svg
259
+ .child('text', {
260
+ x: badgeX,
261
+ y: y - 8,
262
+ 'font-family': "'SF Mono',monospace",
263
+ 'font-size': 10,
264
+ 'font-weight': 700,
265
+ fill: '#FFFFFF',
266
+ 'text-anchor': 'middle',
267
+ })
268
+ .text(i + 1);
269
+ // Message label above the arrow.
270
+ const midX = (x1 + x2) / 2;
271
+ svg
272
+ .child('text', {
273
+ x: fromI === toI ? x1 + 66 : midX,
274
+ y: y - 8,
275
+ 'font-family': 'system-ui,-apple-system,sans-serif',
276
+ 'font-size': 12,
277
+ 'font-weight': 600,
278
+ fill: t.textPrimary,
279
+ 'text-anchor': fromI === toI ? 'start' : 'middle',
280
+ })
281
+ .text(msg.label);
282
+ });
283
+ return doc.toString('Generated by ts-prorm-orm SequenceDiagram');
284
+ }
285
+ /**
286
+ * Write the SVG to a file. Creates parent directories if needed.
287
+ */
288
+ save(outputPath) {
289
+ const resolved = path.resolve(outputPath);
290
+ const dir = path.dirname(resolved);
291
+ if (!fs.existsSync(dir))
292
+ fs.mkdirSync(dir, { recursive: true });
293
+ fs.writeFileSync(resolved, this.generate(), 'utf-8');
294
+ return resolved;
295
+ }
296
+ }
297
+ exports.SequenceDiagram = SequenceDiagram;
298
+ // Layout constants (px)
299
+ SequenceDiagram.PAD = 30;
300
+ SequenceDiagram.LANE = 170; // horizontal spacing between lifelines
301
+ SequenceDiagram.HDR_W = 140; // participant header box width
302
+ SequenceDiagram.HDR_H = 46; // participant header box height
303
+ SequenceDiagram.TITLE_H = 40;
304
+ SequenceDiagram.MSG_GAP = 54; // vertical spacing between messages
305
+ SequenceDiagram.TOP_GAP = 40; // gap below headers before first message
306
+ SequenceDiagram.BOT_GAP = 40; // gap below last message before lifelines end
307
+ SequenceDiagram.ACT_W = 12; // activation bar width