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,135 @@
1
+ "use strict";
2
+ /**
3
+ * UUID Decorator for the ORM
4
+ *
5
+ * Provides PostgreSQL UUID type support with automatic extension management.
6
+ * Requires: CREATE EXTENSION IF NOT EXISTS "uuid-ossp"
7
+ *
8
+ * Usage:
9
+ *
10
+ * // Auto-generate UUID using gen_random_uuid() (PostgreSQL 13+)
11
+ * @UUID()
12
+ * id: string;
13
+ *
14
+ * // Use uuid_generate_v4() (requires uuid-ossp extension)
15
+ * @UUID({ defaultValue: 'uuid_generate_v4' })
16
+ * id: string;
17
+ *
18
+ * // With custom default
19
+ * @UUID({ defaultValue: 'gen_random_uuid' })
20
+ * id: string;
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.UUID = UUID;
24
+ exports.getUUIDMetadata = getUUIDMetadata;
25
+ exports.getAllUUIDMetadata = getAllUUIDMetadata;
26
+ exports.isUUIDColumn = isUUIDColumn;
27
+ exports.clearUUIDMetadata = clearUUIDMetadata;
28
+ exports.getUUIDExtensionSQL = getUUIDExtensionSQL;
29
+ exports.buildUUIDDefaultSQL = buildUUIDDefaultSQL;
30
+ // ==================== Registry ====================
31
+ const uuidMetadataMap = new Map();
32
+ /**
33
+ * UUID decorator for PostgreSQL UUID columns
34
+ *
35
+ * @param options - Optional UUID column options
36
+ *
37
+ * @example
38
+ * // Auto-generate UUID
39
+ * class User extends Model {
40
+ * @UUID()
41
+ * id: string;
42
+ * }
43
+ *
44
+ * // With specific default
45
+ * class User extends Model {
46
+ * @UUID({ defaultValue: 'uuid_generate_v4' })
47
+ * id: string;
48
+ * }
49
+ */
50
+ function UUID(options) {
51
+ return function (target, propertyKey) {
52
+ const decoratorOptions = {
53
+ allowNull: false,
54
+ defaultValue: 'gen_random_uuid',
55
+ ...options,
56
+ };
57
+ // Get or create metadata map for this class
58
+ if (!uuidMetadataMap.has(target.constructor)) {
59
+ uuidMetadataMap.set(target.constructor, new Map());
60
+ }
61
+ const metadataMap = uuidMetadataMap.get(target.constructor);
62
+ // Store metadata
63
+ metadataMap.set(propertyKey, {
64
+ options: decoratorOptions,
65
+ });
66
+ };
67
+ }
68
+ /**
69
+ * Get UUID metadata for a property
70
+ *
71
+ * @param target - The target class
72
+ * @param propertyKey - The property name
73
+ * @returns UUID metadata or undefined if not found
74
+ */
75
+ function getUUIDMetadata(target, propertyKey) {
76
+ const metadataMap = uuidMetadataMap.get(target.constructor);
77
+ if (!metadataMap) {
78
+ return undefined;
79
+ }
80
+ return metadataMap.get(propertyKey);
81
+ }
82
+ /**
83
+ * Get all UUID metadata for a class
84
+ *
85
+ * @param target - The target class
86
+ * @returns Map of property names to UUID metadata
87
+ */
88
+ function getAllUUIDMetadata(target) {
89
+ return uuidMetadataMap.get(target.constructor) || new Map();
90
+ }
91
+ /**
92
+ * Check if a property is a UUID column
93
+ *
94
+ * @param target - The target class
95
+ * @param propertyKey - The property name
96
+ * @returns True if the property is a UUID column
97
+ */
98
+ function isUUIDColumn(target, propertyKey) {
99
+ const metadata = getUUIDMetadata(target, propertyKey);
100
+ return metadata !== undefined;
101
+ }
102
+ /**
103
+ * Clear UUID metadata (useful for testing)
104
+ */
105
+ function clearUUIDMetadata() {
106
+ uuidMetadataMap.clear();
107
+ }
108
+ /**
109
+ * Get the SQL to create the UUID extension
110
+ *
111
+ * @returns SQL to create the uuid-ossp extension
112
+ */
113
+ function getUUIDExtensionSQL() {
114
+ return 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"';
115
+ }
116
+ /**
117
+ * Build the default value SQL for UUID
118
+ *
119
+ * @param options - UUID decorator options
120
+ * @returns SQL for the default value
121
+ */
122
+ function buildUUIDDefaultSQL(options) {
123
+ if (!options.defaultValue) {
124
+ return undefined;
125
+ }
126
+ switch (options.defaultValue) {
127
+ case 'gen_random_uuid':
128
+ return 'gen_random_uuid()';
129
+ case 'uuid_generate_v4':
130
+ return 'uuid_generate_v4()';
131
+ default:
132
+ // Custom SQL expression
133
+ return options.defaultValue;
134
+ }
135
+ }
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ /**
3
+ * @View class decorator — annotate a Model class so it maps to a database view
4
+ * instead of a base table. The ORM stores the view definition and can generate
5
+ * the CREATE VIEW DDL for you.
6
+ *
7
+ * Example:
8
+ *
9
+ * @View({
10
+ * name: 'active_users_view',
11
+ * query: `
12
+ * SELECT id, name, email, created_at
13
+ * FROM users
14
+ * WHERE status = 'active'
15
+ * `,
16
+ * replace: true,
17
+ * })
18
+ * class ActiveUser extends Model<ActiveUserAttributes> {
19
+ * declare id: number;
20
+ * declare name: string;
21
+ * declare email: string;
22
+ * declare createdAt: Date;
23
+ * }
24
+ *
25
+ * // After Model.init() — generate and create the view:
26
+ * const sql = ViewRegistry.getSQL(ActiveUser);
27
+ * await prorm.query(sql);
28
+ *
29
+ * // Or let the ORM create it automatically:
30
+ * await ViewRegistry.createView(prorm, ActiveUser);
31
+ *
32
+ * // Query it just like a normal model:
33
+ * const users = await ActiveUser.findAll({ where: { name: 'Alice' } });
34
+ */
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MaterializedViewRegistry = exports.ViewRegistry = void 0;
37
+ exports.getViewOptions = getViewOptions;
38
+ exports.View = View;
39
+ exports.getMaterializedViewOptions = getMaterializedViewOptions;
40
+ exports.MaterializedView = MaterializedView;
41
+ // ==================== Registry ====================
42
+ const VIEW_OPTIONS_KEY = '__orm_view_options__';
43
+ /**
44
+ * Read the @View options attached to a class.
45
+ * Returns undefined if the class has no @View decorator.
46
+ */
47
+ function getViewOptions(target) {
48
+ return target[VIEW_OPTIONS_KEY];
49
+ }
50
+ // ==================== Decorator ====================
51
+ /**
52
+ * Mark a Model subclass as a database view.
53
+ *
54
+ * - Sets the `tableName` option to the view name so findAll() etc. work correctly.
55
+ * - Registers view metadata so the ORM can generate CREATE VIEW DDL.
56
+ *
57
+ * @View({ name: 'active_users_view', query: 'SELECT ...' })
58
+ * class ActiveUser extends Model { ... }
59
+ */
60
+ function View(options) {
61
+ return function (target) {
62
+ // Resolve view name — default: class name converted to snake_case
63
+ const name = options.name ?? toSnakeCase(target.name);
64
+ const resolved = {
65
+ dialect: 'mysql',
66
+ replace: false,
67
+ ...options,
68
+ name,
69
+ };
70
+ target[VIEW_OPTIONS_KEY] = resolved;
71
+ };
72
+ }
73
+ // ==================== SQL Generation ====================
74
+ function qualifiedName(name, schema, dialect) {
75
+ if (!schema)
76
+ return dialect === 'postgres' ? `"${name}"` : `\`${name}\``;
77
+ return dialect === 'postgres' ? `"${schema}"."${name}"` : `\`${schema}\`.\`${name}\``;
78
+ }
79
+ function buildViewSQL(opts) {
80
+ const query = opts.queryFn ? opts.queryFn() : opts.query;
81
+ if (!query)
82
+ throw new Error('[ORM] @View requires either a `query` or `queryFn` option.');
83
+ const dialect = opts.dialect ?? 'mysql';
84
+ const name = qualifiedName(opts.name, opts.schema, dialect);
85
+ const materialized = opts.materialized ? 'MATERIALIZED ' : '';
86
+ const orReplace = opts.replace && !opts.materialized ? 'OR REPLACE ' : '';
87
+ if (dialect === 'postgres') {
88
+ let sql = `CREATE ${orReplace}${materialized}VIEW ${name} AS\n${query.trim()}`;
89
+ if (opts.checkOption && !opts.materialized) {
90
+ const check = opts.checkOption === true ? 'CASCADED' : opts.checkOption;
91
+ sql += `\nWITH ${check} CHECK OPTION`;
92
+ }
93
+ return sql;
94
+ }
95
+ // MySQL / MariaDB / SQLite
96
+ return `CREATE ${orReplace}VIEW ${name} AS\n${query.trim()}`;
97
+ }
98
+ // ==================== Public Registry API ====================
99
+ exports.ViewRegistry = {
100
+ /**
101
+ * Generate the CREATE VIEW SQL for a @View-annotated class.
102
+ */
103
+ getSQL(target, dialectOverride) {
104
+ const opts = getViewOptions(target);
105
+ if (!opts)
106
+ throw new Error(`[ORM] Class "${target.name}" does not have a @View decorator.`);
107
+ return buildViewSQL({ ...opts, ...(dialectOverride ? { dialect: dialectOverride } : {}) });
108
+ },
109
+ /**
110
+ * Execute the CREATE VIEW statement for a @View-annotated model class.
111
+ */
112
+ async createView(prorm, target, dialectOverride) {
113
+ const sql = exports.ViewRegistry.getSQL(target, dialectOverride);
114
+ await prorm.query(sql);
115
+ },
116
+ /**
117
+ * Drop the view for a @View-annotated class.
118
+ * @param ifExists - Emit IF EXISTS (default: true)
119
+ */
120
+ async dropView(prorm, target, ifExists = true) {
121
+ const opts = getViewOptions(target);
122
+ if (!opts)
123
+ throw new Error(`[ORM] Class "${target.name}" does not have a @View decorator.`);
124
+ const dialect = opts.dialect ?? 'mysql';
125
+ const name = qualifiedName(opts.name, opts.schema, dialect);
126
+ const ifExistsClause = ifExists ? 'IF EXISTS ' : '';
127
+ const materialized = opts.materialized ? 'MATERIALIZED ' : '';
128
+ await prorm.query(`DROP ${materialized}VIEW ${ifExistsClause}${name}`);
129
+ },
130
+ };
131
+ const MATERIALIZED_VIEW_OPTIONS_KEY = '__orm_materialized_view_options__';
132
+ /**
133
+ * Read the @MaterializedView options attached to a class.
134
+ * Returns undefined if the class has no @MaterializedView decorator.
135
+ */
136
+ function getMaterializedViewOptions(target) {
137
+ return target[MATERIALIZED_VIEW_OPTIONS_KEY];
138
+ }
139
+ /**
140
+ * Mark a Model subclass as a database materialized view.
141
+ *
142
+ * - Sets the `tableName` option to the view name so findAll() etc. work correctly.
143
+ * - Registers materialized view metadata so the ORM can generate CREATE MATERIALIZED VIEW DDL.
144
+ * - Adds a `refresh()` static method for refreshing the view data.
145
+ *
146
+ * @MaterializedView({
147
+ * name: 'user_stats_view',
148
+ * query: `
149
+ * SELECT user_id, COUNT(*) as order_count
150
+ * FROM orders
151
+ * GROUP BY user_id
152
+ * `,
153
+ * uniqueIndex: 'user_stats_view_user_id_key',
154
+ * })
155
+ * class UserStats extends Model<UserStatsAttributes> {
156
+ * declare userId: number;
157
+ * declare orderCount: number;
158
+ * }
159
+ *
160
+ * // After Model.init() — generate and create the materialized view:
161
+ * const sql = MaterializedViewRegistry.getSQL(UserStats);
162
+ * await prorm.query(sql);
163
+ *
164
+ * // Or let the ORM create it automatically:
165
+ * await MaterializedViewRegistry.createMaterializedView(prorm, UserStats);
166
+ *
167
+ * // Query it just like a normal model:
168
+ * const stats = await UserStats.findAll();
169
+ *
170
+ * // Refresh the materialized view:
171
+ * await UserStats.refresh();
172
+ * // Or concurrently (requires unique index):
173
+ * await UserStats.refresh({ concurrently: true });
174
+ */
175
+ function MaterializedView(options) {
176
+ return function (target) {
177
+ // Resolve view name — default: class name converted to snake_case
178
+ const name = options.name ?? toSnakeCase(target.name);
179
+ const resolved = {
180
+ refreshStrategy: 'ON DEMAND',
181
+ withData: true,
182
+ replace: false,
183
+ ifNotExists: false,
184
+ ...options,
185
+ name,
186
+ };
187
+ target[MATERIALIZED_VIEW_OPTIONS_KEY] = resolved;
188
+ // Mark as materialized view for type checking
189
+ target.isMaterializedView = true;
190
+ };
191
+ }
192
+ // ==================== SQL Generation for Materialized Views ====================
193
+ function buildMaterializedViewSQL(opts) {
194
+ const query = opts.queryFn ? opts.queryFn() : opts.query;
195
+ if (!query)
196
+ throw new Error('[ORM] @MaterializedView requires either a `query` or `queryFn` option.');
197
+ const name = qualifiedName(opts.name, opts.schema, 'postgres');
198
+ let sql = 'CREATE MATERIALIZED VIEW';
199
+ if (opts.replace) {
200
+ sql = 'CREATE OR REPLACE MATERIALIZED VIEW';
201
+ }
202
+ else if (opts.ifNotExists) {
203
+ sql = 'CREATE MATERIALIZED VIEW IF NOT EXISTS';
204
+ }
205
+ sql += ` ${name} AS\n${query.trim()}`;
206
+ if (!opts.withData) {
207
+ sql += ' WITH NO DATA';
208
+ }
209
+ return sql;
210
+ }
211
+ // ==================== Materialized View Registry ====================
212
+ exports.MaterializedViewRegistry = {
213
+ /**
214
+ * Generate the CREATE MATERIALIZED VIEW SQL for a @MaterializedView-annotated class.
215
+ */
216
+ getSQL(target, dialectOverride) {
217
+ const opts = getMaterializedViewOptions(target);
218
+ if (!opts)
219
+ throw new Error(`[ORM] Class "${target.name}" does not have a @MaterializedView decorator.`);
220
+ return buildMaterializedViewSQL({
221
+ ...opts,
222
+ ...(dialectOverride ? { schema: dialectOverride } : {}),
223
+ });
224
+ },
225
+ /**
226
+ * Execute the CREATE MATERIALIZED VIEW statement for a @MaterializedView-annotated model class.
227
+ */
228
+ async createMaterializedView(prorm, target, dialectOverride) {
229
+ const sql = exports.MaterializedViewRegistry.getSQL(target, dialectOverride);
230
+ await prorm.query(sql);
231
+ // Create unique index if provided (required for CONCURRENTLY refresh)
232
+ const opts = getMaterializedViewOptions(target);
233
+ if (opts?.uniqueIndex) {
234
+ const name = qualifiedName(opts.name, opts.schema, 'postgres');
235
+ const indexSql = `CREATE UNIQUE INDEX ${opts.uniqueIndex} ON ${name} (${opts.uniqueIndex.replace(/_key$/, '')})`;
236
+ await prorm.query(indexSql);
237
+ }
238
+ },
239
+ /**
240
+ * Drop the materialized view for a @MaterializedView-annotated class.
241
+ * @param ifExists - Emit IF EXISTS (default: true)
242
+ */
243
+ async dropMaterializedView(prorm, target, ifExists = true) {
244
+ const opts = getMaterializedViewOptions(target);
245
+ if (!opts)
246
+ throw new Error(`[ORM] Class "${target.name}" does not have a @MaterializedView decorator.`);
247
+ const name = qualifiedName(opts.name, opts.schema, 'postgres');
248
+ const ifExistsClause = ifExists ? 'IF EXISTS ' : '';
249
+ await prorm.query(`DROP MATERIALIZED VIEW ${ifExistsClause}${name}`);
250
+ },
251
+ };
252
+ // ==================== Internal Helpers ====================
253
+ function toSnakeCase(str) {
254
+ return str
255
+ .replace(/([A-Z])/g, '_$1')
256
+ .toLowerCase()
257
+ .replace(/^_/, '');
258
+ }