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,344 @@
1
+ "use strict";
2
+ /**
3
+ * StateDiagram — generates a UML state-machine diagram as an SVG.
4
+ *
5
+ * Renders:
6
+ * - normal states as rounded rectangles
7
+ * - an initial pseudo-state as a filled black circle
8
+ * - a final state as a ringed (double) circle
9
+ * - transitions as arrows between states, labeled with their trigger/event
10
+ * - self-transitions as loop arrows
11
+ *
12
+ * Great for showing a record lifecycle (e.g. draft → active → archived →
13
+ * deleted). States are auto-placed left-to-right in a wrapping grid unless
14
+ * explicit x/y hints are supplied per state. The SVG viewBox is auto-sized.
15
+ *
16
+ * Both `--theme light|dark` and `--color <name|hex>` genuinely change the
17
+ * output: the accent drives state fills + arrowheads, the theme drives the
18
+ * canvas background, text and borders.
19
+ *
20
+ * Usage:
21
+ * const diag = new StateDiagram({
22
+ * states: [
23
+ * { name: 'start', initial: true },
24
+ * { name: 'draft' },
25
+ * { name: 'active' },
26
+ * { name: 'archived', final: true },
27
+ * ],
28
+ * transitions: [
29
+ * { from: 'start', to: 'draft' },
30
+ * { from: 'draft', to: 'active', event: 'publish' },
31
+ * { from: 'active', to: 'active', event: 'edit' },
32
+ * { from: 'active', to: 'archived', event: 'archive' },
33
+ * ],
34
+ * });
35
+ * diag.save('./diagrams/lifecycle.svg');
36
+ * // or:
37
+ * const svgString = diag.generate();
38
+ */
39
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
40
+ if (k2 === undefined) k2 = k;
41
+ var desc = Object.getOwnPropertyDescriptor(m, k);
42
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
43
+ desc = { enumerable: true, get: function() { return m[k]; } };
44
+ }
45
+ Object.defineProperty(o, k2, desc);
46
+ }) : (function(o, m, k, k2) {
47
+ if (k2 === undefined) k2 = k;
48
+ o[k2] = m[k];
49
+ }));
50
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
51
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
52
+ }) : function(o, v) {
53
+ o["default"] = v;
54
+ });
55
+ var __importStar = (this && this.__importStar) || (function () {
56
+ var ownKeys = function(o) {
57
+ ownKeys = Object.getOwnPropertyNames || function (o) {
58
+ var ar = [];
59
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
60
+ return ar;
61
+ };
62
+ return ownKeys(o);
63
+ };
64
+ return function (mod) {
65
+ if (mod && mod.__esModule) return mod;
66
+ var result = {};
67
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
68
+ __setModuleDefault(result, mod);
69
+ return result;
70
+ };
71
+ })();
72
+ Object.defineProperty(exports, "__esModule", { value: true });
73
+ exports.StateDiagram = void 0;
74
+ const fs = __importStar(require("fs"));
75
+ const path = __importStar(require("path"));
76
+ const palette_1 = require("./palette");
77
+ const svg_dom_1 = require("./svg-dom");
78
+ // ─── Main class ────────────────────────────────────────────────────────────
79
+ class StateDiagram {
80
+ constructor(options) {
81
+ this.opts = {
82
+ states: options.states ?? [],
83
+ transitions: options.transitions ?? [],
84
+ title: options.title ?? '',
85
+ theme: options.theme ?? 'light',
86
+ color: options.color ?? '',
87
+ };
88
+ }
89
+ // ── Auto-place states in a wrapping row/grid (honoring x/y hints) ─────────
90
+ layout() {
91
+ const { states } = this.opts;
92
+ const PAD = StateDiagram.PAD;
93
+ const TITLE_H = this.opts.title ? StateDiagram.TITLE_H : 0;
94
+ const BOX_W = StateDiagram.BOX_W;
95
+ const BOX_H = StateDiagram.BOX_H;
96
+ const GAP_X = StateDiagram.GAP_X;
97
+ const GAP_Y = StateDiagram.GAP_Y;
98
+ const PER_ROW = StateDiagram.PER_ROW;
99
+ const CELL_W = BOX_W + GAP_X;
100
+ const CELL_H = BOX_H + GAP_Y;
101
+ const topBase = PAD + TITLE_H + StateDiagram.GAP_Y / 2;
102
+ const placed = new Map();
103
+ let maxX = 0;
104
+ let maxY = 0;
105
+ states.forEach((node, i) => {
106
+ const col = i % PER_ROW;
107
+ const row = Math.floor(i / PER_ROW);
108
+ // Auto cell top-left, or explicit hint.
109
+ const boxLeft = node.x ?? PAD + col * CELL_W;
110
+ const boxTop = node.y ?? topBase + row * CELL_H;
111
+ const isMarker = !!(node.initial || node.final);
112
+ const hw = isMarker ? StateDiagram.PSEUDO_R : BOX_W / 2;
113
+ const hh = isMarker ? StateDiagram.PSEUDO_R : BOX_H / 2;
114
+ // Center within the nominal box footprint so markers align with rows.
115
+ const cx = boxLeft + BOX_W / 2;
116
+ const cy = boxTop + BOX_H / 2;
117
+ placed.set(node.name, { node, cx, cy, hw, hh });
118
+ maxX = Math.max(maxX, cx + BOX_W / 2);
119
+ maxY = Math.max(maxY, cy + BOX_H / 2);
120
+ });
121
+ const width = maxX + PAD;
122
+ const height = maxY + PAD;
123
+ return { placed, width, height };
124
+ }
125
+ // ── Compute a point on the box perimeter toward a target point ────────────
126
+ edgePoint(p, tx, ty) {
127
+ const dx = tx - p.cx;
128
+ const dy = ty - p.cy;
129
+ if (dx === 0 && dy === 0)
130
+ return { x: p.cx, y: p.cy };
131
+ const scaleX = dx !== 0 ? p.hw / Math.abs(dx) : Infinity;
132
+ const scaleY = dy !== 0 ? p.hh / Math.abs(dy) : Infinity;
133
+ const s = Math.min(scaleX, scaleY);
134
+ return { x: p.cx + dx * s, y: p.cy + dy * s };
135
+ }
136
+ // ── Generate full SVG string (built via a real DOM document) ──────────────
137
+ generate() {
138
+ const { title, theme, color } = this.opts;
139
+ const accent = (0, palette_1.resolveAccent)(color);
140
+ const t = (0, palette_1.resolveTheme)(theme);
141
+ const { placed, width, height } = this.layout();
142
+ const PAD = StateDiagram.PAD;
143
+ const R = StateDiagram.R;
144
+ const doc = new svg_dom_1.SvgDocument(width, height);
145
+ const svg = doc.root;
146
+ // ── Background ──────────────────────────────────────────────────────
147
+ svg.child('rect', { width, height, fill: t.canvasBg });
148
+ // ── Defs: arrowhead marker + state fill gradient ────────────────────
149
+ doc.linearGradient('stateFill', [
150
+ [0, accent.mid],
151
+ [100, accent.from],
152
+ ]);
153
+ const marker = doc.defs().child('marker', {
154
+ id: 'arrow',
155
+ markerWidth: 10,
156
+ markerHeight: 10,
157
+ refX: 8,
158
+ refY: 3,
159
+ orient: 'auto',
160
+ markerUnits: 'strokeWidth',
161
+ });
162
+ marker.child('path', { d: 'M0,0 L8,3 L0,6 Z', fill: accent.mid });
163
+ // ── Title ───────────────────────────────────────────────────────────
164
+ if (title) {
165
+ svg
166
+ .child('text', {
167
+ x: PAD,
168
+ y: PAD + 8,
169
+ 'font-family': 'system-ui,-apple-system,sans-serif',
170
+ 'font-size': 22,
171
+ 'font-weight': 800,
172
+ fill: t.textPrimary,
173
+ })
174
+ .text(title);
175
+ }
176
+ // ── Transitions (drawn first so states sit on top) ──────────────────
177
+ this.opts.transitions.forEach((tr) => {
178
+ const from = placed.get(tr.from);
179
+ const to = placed.get(tr.to);
180
+ if (!from || !to)
181
+ return;
182
+ if (tr.from === tr.to) {
183
+ this.drawSelfLoop(svg, from, tr.event, accent.mid, t.textSecondary);
184
+ }
185
+ else {
186
+ this.drawTransition(svg, from, to, tr.event, accent.mid, t.textSecondary);
187
+ }
188
+ });
189
+ // ── States ──────────────────────────────────────────────────────────
190
+ placed.forEach((p) => {
191
+ const node = p.node;
192
+ if (node.initial) {
193
+ // Filled black circle (initial pseudo-state).
194
+ svg.child('circle', {
195
+ cx: p.cx,
196
+ cy: p.cy,
197
+ r: StateDiagram.PSEUDO_R,
198
+ fill: '#111111',
199
+ stroke: t.border,
200
+ 'stroke-width': 1,
201
+ });
202
+ }
203
+ else if (node.final) {
204
+ // Ringed circle (final state): outer ring + filled accent core.
205
+ svg.child('circle', {
206
+ cx: p.cx,
207
+ cy: p.cy,
208
+ r: StateDiagram.PSEUDO_R,
209
+ fill: 'none',
210
+ stroke: t.textPrimary,
211
+ 'stroke-width': 2,
212
+ });
213
+ svg.child('circle', {
214
+ cx: p.cx,
215
+ cy: p.cy,
216
+ r: StateDiagram.PSEUDO_R - 6,
217
+ fill: accent.mid,
218
+ });
219
+ }
220
+ else {
221
+ // Normal state: rounded rectangle with accent fill.
222
+ svg.child('rect', {
223
+ x: p.cx - p.hw,
224
+ y: p.cy - p.hh,
225
+ width: p.hw * 2,
226
+ height: p.hh * 2,
227
+ rx: R,
228
+ fill: 'url(#stateFill)',
229
+ stroke: accent.from,
230
+ 'stroke-width': 2,
231
+ });
232
+ svg
233
+ .child('text', {
234
+ x: p.cx,
235
+ y: p.cy + 5,
236
+ 'font-family': 'system-ui,-apple-system,sans-serif',
237
+ 'font-size': 15,
238
+ 'font-weight': 700,
239
+ fill: '#FFFFFF',
240
+ 'text-anchor': 'middle',
241
+ })
242
+ .text(node.name);
243
+ }
244
+ // Label markers (initial/final) beneath the circle.
245
+ if (node.initial || node.final) {
246
+ svg
247
+ .child('text', {
248
+ x: p.cx,
249
+ y: p.cy + StateDiagram.PSEUDO_R + 16,
250
+ 'font-family': 'system-ui,sans-serif',
251
+ 'font-size': 11,
252
+ 'font-weight': 600,
253
+ fill: t.textSecondary,
254
+ 'text-anchor': 'middle',
255
+ })
256
+ .text(node.name);
257
+ }
258
+ });
259
+ return doc.toString('Generated by ts-prorm-orm StateDiagram');
260
+ }
261
+ // ── Draw a straight transition arrow with an optional event label ─────────
262
+ drawTransition(svg, from, to, event, stroke, labelColor) {
263
+ const start = this.edgePoint(from, to.cx, to.cy);
264
+ const end = this.edgePoint(to, from.cx, from.cy);
265
+ svg.child('line', {
266
+ x1: start.x,
267
+ y1: start.y,
268
+ x2: end.x,
269
+ y2: end.y,
270
+ stroke,
271
+ 'stroke-width': 2,
272
+ 'marker-end': 'url(#arrow)',
273
+ });
274
+ if (event) {
275
+ const mx = (start.x + end.x) / 2;
276
+ const my = (start.y + end.y) / 2;
277
+ this.drawEventLabel(svg, mx, my - 6, event, labelColor);
278
+ }
279
+ }
280
+ // ── Draw a self-transition loop arrow above the state ─────────────────────
281
+ drawSelfLoop(svg, p, event, stroke, labelColor) {
282
+ const topY = p.cy - p.hh;
283
+ const x1 = p.cx - p.hw * 0.4;
284
+ const x2 = p.cx + p.hw * 0.4;
285
+ const loopH = 34;
286
+ const d = `M${x1},${topY} C${x1 - 20},${topY - loopH} ${x2 + 20},${topY - loopH} ${x2},${topY}`;
287
+ svg.child('path', {
288
+ d,
289
+ fill: 'none',
290
+ stroke,
291
+ 'stroke-width': 2,
292
+ 'marker-end': 'url(#arrow)',
293
+ });
294
+ if (event) {
295
+ this.drawEventLabel(svg, p.cx, topY - loopH - 4, event, labelColor);
296
+ }
297
+ }
298
+ // ── Draw an event label with a subtle background pill for legibility ───────
299
+ drawEventLabel(svg, x, y, event, color) {
300
+ const w = event.length * 7 + 12;
301
+ svg.child('rect', {
302
+ x: x - w / 2,
303
+ y: y - 13,
304
+ width: w,
305
+ height: 18,
306
+ rx: 6,
307
+ fill: '#FFFFFF',
308
+ opacity: 0.85,
309
+ });
310
+ svg
311
+ .child('text', {
312
+ x,
313
+ y: y - 1,
314
+ 'font-family': "'SF Mono','Fira Code',monospace",
315
+ 'font-size': 11,
316
+ 'font-weight': 600,
317
+ fill: color,
318
+ 'text-anchor': 'middle',
319
+ })
320
+ .text(event);
321
+ }
322
+ /**
323
+ * Write the SVG to a file. Creates parent directories if needed.
324
+ */
325
+ save(outputPath) {
326
+ const resolved = path.resolve(outputPath);
327
+ const dir = path.dirname(resolved);
328
+ if (!fs.existsSync(dir))
329
+ fs.mkdirSync(dir, { recursive: true });
330
+ fs.writeFileSync(resolved, this.generate(), 'utf-8');
331
+ return resolved;
332
+ }
333
+ }
334
+ exports.StateDiagram = StateDiagram;
335
+ // Layout constants (px)
336
+ StateDiagram.PAD = 40;
337
+ StateDiagram.TITLE_H = 44;
338
+ StateDiagram.BOX_W = 150;
339
+ StateDiagram.BOX_H = 60;
340
+ StateDiagram.PSEUDO_R = 14; // radius for initial/final markers
341
+ StateDiagram.GAP_X = 90;
342
+ StateDiagram.GAP_Y = 80;
343
+ StateDiagram.PER_ROW = 4;
344
+ StateDiagram.R = 16; // box border-radius
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ /**
3
+ * svg-dom — a small DOM-backed SVG builder shared by every diagram generator.
4
+ *
5
+ * Diagrams are constructed against a real DOM document (via `@xmldom/xmldom`)
6
+ * using `createElement`/`setAttribute`/`appendChild`, then serialized once with
7
+ * `XMLSerializer`. This replaces hand-concatenated markup strings: attribute
8
+ * values are escaped by the serializer, element nesting can't be malformed, and
9
+ * every generator shares one construction API.
10
+ *
11
+ * The `El` wrapper is a thin fluent facade over a DOM `Element` — `.attr()`,
12
+ * `.text()`, `.child()` — so generator code reads declaratively while the
13
+ * underlying nodes remain inspectable/testable as real DOM.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.SvgDocument = exports.El = void 0;
17
+ const xmldom_1 = require("@xmldom/xmldom");
18
+ const SVG_NS = 'http://www.w3.org/2000/svg';
19
+ /** Fluent wrapper around a DOM Element. */
20
+ class El {
21
+ constructor(node, doc) {
22
+ this.node = node;
23
+ this.doc = doc;
24
+ }
25
+ /** Set one attribute (skipped when value is null/undefined). */
26
+ attr(name, value) {
27
+ if (value !== undefined && value !== null)
28
+ this.node.setAttribute(name, String(value));
29
+ return this;
30
+ }
31
+ /** Set many attributes at once. */
32
+ attrs(map) {
33
+ for (const [k, v] of Object.entries(map))
34
+ this.attr(k, v);
35
+ return this;
36
+ }
37
+ /** Append a text node (returns this for chaining). */
38
+ text(value) {
39
+ this.node.appendChild(this.doc.createTextNode(String(value)));
40
+ return this;
41
+ }
42
+ /** Create + append a child element, returning the CHILD. */
43
+ child(tag, attrs) {
44
+ const c = new El(this.doc.createElementNS(SVG_NS, tag), this.doc);
45
+ if (attrs)
46
+ c.attrs(attrs);
47
+ this.node.appendChild(c.node);
48
+ return c;
49
+ }
50
+ /** Append an already-built El as a child; returns this (the parent). */
51
+ append(...children) {
52
+ for (const c of children)
53
+ this.node.appendChild(c.node);
54
+ return this;
55
+ }
56
+ }
57
+ exports.El = El;
58
+ /** A DOM-backed SVG document builder. */
59
+ class SvgDocument {
60
+ constructor(width, height, viewBox) {
61
+ this.doc = new xmldom_1.DOMImplementation().createDocument(SVG_NS, 'svg', null);
62
+ this.root = new El(this.doc.documentElement, this.doc);
63
+ this.root.attrs({
64
+ xmlns: SVG_NS,
65
+ width,
66
+ height,
67
+ viewBox: viewBox ?? `0 0 ${width} ${height}`,
68
+ });
69
+ }
70
+ /** Create a standalone element not yet attached to the tree. */
71
+ create(tag, attrs) {
72
+ const el = new El(this.doc.createElementNS(SVG_NS, tag), this.doc);
73
+ if (attrs)
74
+ el.attrs(attrs);
75
+ return el;
76
+ }
77
+ /** Get (creating on first use) the shared <defs> block. */
78
+ defs() {
79
+ if (!this._defs) {
80
+ this._defs = this.create('defs');
81
+ // defs should be the first child so gradients/filters resolve.
82
+ this.doc.documentElement.insertBefore(this._defs.node, this.doc.documentElement.firstChild);
83
+ }
84
+ return this._defs;
85
+ }
86
+ /**
87
+ * Convenience: add a linear gradient to <defs> and return its id.
88
+ * `stops` is a list of [offsetPercent, color] pairs.
89
+ */
90
+ linearGradient(id, stops, opts) {
91
+ const g = this.defs().child('linearGradient', {
92
+ id,
93
+ x1: opts?.x1 ?? 0,
94
+ y1: opts?.y1 ?? 0,
95
+ x2: opts?.x2 ?? 1,
96
+ y2: opts?.y2 ?? 1,
97
+ gradientUnits: 'objectBoundingBox',
98
+ });
99
+ for (const [offset, color] of stops) {
100
+ g.child('stop', { offset: `${offset}%`, 'stop-color': color });
101
+ }
102
+ return id;
103
+ }
104
+ /** Serialize the whole document to an XML/SVG string (with XML prolog). */
105
+ toString(comment) {
106
+ const body = new xmldom_1.XMLSerializer().serializeToString(this.doc);
107
+ const prolog = `<?xml version="1.0" encoding="UTF-8"?>`;
108
+ return comment ? `${prolog}\n<!-- ${comment} -->\n${body}` : `${prolog}\n${body}`;
109
+ }
110
+ }
111
+ exports.SvgDocument = SvgDocument;