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,235 @@
1
+ "use strict";
2
+ /**
3
+ * Encryption decorators and adapter system for the ORM.
4
+ *
5
+ * Allows fields to be annotated with @Secure so values are automatically
6
+ * hashed before being saved. The encryption algorithm is fully swappable
7
+ * via EncryptionAdapter — default recommendation is bcrypt, but you can
8
+ * plug in argon2, scrypt, or any custom implementation.
9
+ *
10
+ * Usage:
11
+ *
12
+ * // 1. Install your preferred package, e.g. npm install bcrypt
13
+ * // 2. Wire up the adapter once at boot time:
14
+ * import bcrypt from 'bcrypt';
15
+ * setEncryptionAdapter({
16
+ * hash: (value) => bcrypt.hash(value, 12),
17
+ * verify: (plain, hashed) => bcrypt.compare(plain, hashed),
18
+ * });
19
+ *
20
+ * // 3. Annotate fields on your model class:
21
+ * class User extends Model { ... }
22
+ * User.init({
23
+ * password: { type: DataTypes.STRING, allowNull: false }
24
+ * }, { prorm });
25
+ * Secure('password')(User); // field decorator style
26
+ *
27
+ * // Or use the decorator on the class definition (requires experimentalDecorators):
28
+ * @SecureField('password')
29
+ * class User extends Model { ... }
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.Secure = void 0;
33
+ exports.setEncryptionAdapter = setEncryptionAdapter;
34
+ exports.getEncryptionAdapter = getEncryptionAdapter;
35
+ exports.getSecureFields = getSecureFields;
36
+ exports.SecureField = SecureField;
37
+ exports.hashSecureFields = hashSecureFields;
38
+ exports.verifySecureField = verifySecureField;
39
+ exports.applySecureHooks = applySecureHooks;
40
+ exports.createBcryptAdapter = createBcryptAdapter;
41
+ exports.createArgon2Adapter = createArgon2Adapter;
42
+ // ==================== Global Registry ====================
43
+ let globalAdapter = null;
44
+ /**
45
+ * Set the global encryption adapter used by all @Secure fields that
46
+ * do not specify their own adapter.
47
+ *
48
+ * Call this once during application bootstrap, e.g.:
49
+ *
50
+ * import bcrypt from 'bcrypt';
51
+ * setEncryptionAdapter({
52
+ * hash: (v) => bcrypt.hash(v, 12),
53
+ * verify: (plain, hash) => bcrypt.compare(plain, hash),
54
+ * });
55
+ */
56
+ function setEncryptionAdapter(adapter) {
57
+ globalAdapter = adapter;
58
+ }
59
+ /**
60
+ * Return the currently registered global adapter, or null if none has
61
+ * been configured.
62
+ */
63
+ function getEncryptionAdapter() {
64
+ return globalAdapter;
65
+ }
66
+ // ==================== Field Metadata ====================
67
+ const SECURE_FIELDS_KEY = '__orm_secure_fields__';
68
+ /**
69
+ * Read the list of secure-field annotations attached to a model constructor.
70
+ */
71
+ function getSecureFields(target) {
72
+ return target[SECURE_FIELDS_KEY] || [];
73
+ }
74
+ // ==================== Decorators ====================
75
+ /**
76
+ * Mark a model field so its value is automatically hashed before INSERT/UPDATE.
77
+ *
78
+ * This is a class decorator factory — pass the field name(s):
79
+ *
80
+ * @SecureField('password')
81
+ * @SecureField('pin', { algorithm: 'bcrypt', adapter: myAdapter })
82
+ * class User extends Model { ... }
83
+ *
84
+ * The ORM will call hashSecureFields(instance) in a beforeCreate /
85
+ * beforeUpdate hook to encrypt the field before it reaches the database.
86
+ */
87
+ function SecureField(field, options = {}) {
88
+ return function (target) {
89
+ if (!target[SECURE_FIELDS_KEY]) {
90
+ target[SECURE_FIELDS_KEY] = [];
91
+ }
92
+ target[SECURE_FIELDS_KEY].push({ field, options });
93
+ };
94
+ }
95
+ /**
96
+ * Alias for SecureField — preferred shorthand.
97
+ *
98
+ * @Secure('password')
99
+ * class User extends Model { ... }
100
+ */
101
+ exports.Secure = SecureField;
102
+ // ==================== Runtime Helpers ====================
103
+ /**
104
+ * Hash all @Secure-annotated fields on a model instance.
105
+ *
106
+ * Call this inside a beforeCreate / beforeUpdate hook, or let the ORM
107
+ * do it automatically when you use applySecureHooks().
108
+ *
109
+ * @param instance - The model instance whose fields should be hashed
110
+ */
111
+ async function hashSecureFields(instance) {
112
+ const ModelClass = instance.constructor;
113
+ const secureFields = getSecureFields(ModelClass);
114
+ for (const { field, options } of secureFields) {
115
+ const value = instance.getDataValue
116
+ ? instance.getDataValue(field)
117
+ : instance[field];
118
+ if (value == null || typeof value !== 'string')
119
+ continue;
120
+ // Skip if the value already looks like a hash (starts with $2b$, $argon2, etc.)
121
+ const skipIfHashed = options.skipIfHashed !== false; // default true
122
+ if (skipIfHashed && looksLikeHash(value))
123
+ continue;
124
+ const adapter = options.adapter ?? globalAdapter;
125
+ if (!adapter) {
126
+ throw new Error(`[ORM] No encryption adapter configured for field "${field}". ` +
127
+ `Call setEncryptionAdapter() at boot time, or provide an adapter in @Secure options.`);
128
+ }
129
+ const hashed = await adapter.hash(value);
130
+ if (instance.setDataValue) {
131
+ instance.setDataValue(field, hashed);
132
+ }
133
+ else {
134
+ instance[field] = hashed;
135
+ }
136
+ }
137
+ }
138
+ /**
139
+ * Verify a plain-text value against the stored hash of a @Secure field.
140
+ *
141
+ * @param instance - The model instance containing the stored hash
142
+ * @param field - The field name
143
+ * @param plainText - The candidate value to check
144
+ * @returns true if the plain-text matches the stored hash
145
+ */
146
+ async function verifySecureField(instance, field, plainText) {
147
+ const ModelClass = instance.constructor;
148
+ const secureFields = getSecureFields(ModelClass);
149
+ const meta = secureFields.find((m) => m.field === field);
150
+ const adapter = meta?.options.adapter ?? globalAdapter;
151
+ if (!adapter) {
152
+ throw new Error(`[ORM] No encryption adapter configured for field "${field}". ` +
153
+ `Call setEncryptionAdapter() at boot time.`);
154
+ }
155
+ const stored = instance.getDataValue
156
+ ? instance.getDataValue(field)
157
+ : instance[field];
158
+ if (!stored)
159
+ return false;
160
+ return adapter.verify(plainText, stored);
161
+ }
162
+ /**
163
+ * Register beforeCreate and beforeUpdate hooks on a model so that
164
+ * @Secure fields are automatically hashed whenever an instance is saved.
165
+ *
166
+ * Call once per model after Model.init():
167
+ *
168
+ * applySecureHooks(User);
169
+ *
170
+ * @param ModelClass - The model class (result of prorm.define or Model.init)
171
+ */
172
+ function applySecureHooks(ModelClass) {
173
+ const fields = getSecureFields(ModelClass);
174
+ if (fields.length === 0)
175
+ return;
176
+ // Register hooks via the ORM's addHook API
177
+ if (typeof ModelClass.addHook === 'function') {
178
+ ModelClass.addHook('beforeCreate', 'orm:secureHash', async (instance) => {
179
+ await hashSecureFields(instance);
180
+ });
181
+ ModelClass.addHook('beforeUpdate', 'orm:secureHash', async (instance) => {
182
+ await hashSecureFields(instance);
183
+ });
184
+ ModelClass.addHook('beforeSave', 'orm:secureHash', async (instance) => {
185
+ await hashSecureFields(instance);
186
+ });
187
+ }
188
+ }
189
+ // ==================== Convenience Adapters ====================
190
+ /**
191
+ * Create a bcrypt adapter.
192
+ *
193
+ * Requires `bcrypt` or `bcryptjs` to be installed:
194
+ * npm install bcrypt (native, faster)
195
+ * npm install bcryptjs (pure JS, no native build)
196
+ *
197
+ * @param saltRounds - bcrypt cost factor (default: 12)
198
+ *
199
+ * Usage:
200
+ * import bcrypt from 'bcrypt';
201
+ * setEncryptionAdapter(createBcryptAdapter(bcrypt, 12));
202
+ */
203
+ function createBcryptAdapter(bcryptLib, saltRounds = 12) {
204
+ return {
205
+ hash: (value) => bcryptLib.hash(value, saltRounds),
206
+ verify: (plain, hashed) => bcryptLib.compare(plain, hashed),
207
+ };
208
+ }
209
+ /**
210
+ * Create an argon2 adapter.
211
+ *
212
+ * Requires `argon2` to be installed:
213
+ * npm install argon2
214
+ *
215
+ * Usage:
216
+ * import argon2 from 'argon2';
217
+ * setEncryptionAdapter(createArgon2Adapter(argon2));
218
+ */
219
+ function createArgon2Adapter(argon2Lib) {
220
+ return {
221
+ hash: (value) => argon2Lib.hash(value),
222
+ verify: (plain, hashed) => argon2Lib.verify(hashed, plain),
223
+ };
224
+ }
225
+ // ==================== Internal Helpers ====================
226
+ /**
227
+ * Heuristic check — does this string look like an already-computed hash?
228
+ * Supports bcrypt ($2a$, $2b$, $2y$), argon2 ($argon2), and scrypt ($scrypt).
229
+ */
230
+ function looksLikeHash(value) {
231
+ return (/^\$2[aby]\$/.test(value) || // bcrypt
232
+ /^\$argon2/.test(value) || // argon2
233
+ /^\$scrypt\$/.test(value) // scrypt (node-scrypt-format)
234
+ );
235
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ /**
3
+ * `@Engine` — class decorator for annotating a Model with dialect-specific
4
+ * per-table storage-engine configuration, mirroring the `@View`/
5
+ * `@MaterializedView` pattern (`src/decorators/view.ts`): stores metadata on
6
+ * the class, exposed via a registry, rather than being silently read by
7
+ * `Prorm.sync()` - keeping engine selection an explicit, visible step.
8
+ *
9
+ * Built for ClickHouse's MergeTree-family engine configuration first (the
10
+ * dialect that most needs per-table engine choice - `mergeTreeEngine`/
11
+ * `orderBy`/`ttl`/`partitionBy`/`projections` are all read as loosely-typed
12
+ * extensions off `TableOptions` in `src/dialects/clickhouse/index.ts` since
13
+ * the base `Dialect` interface has no notion of storage engines), but the
14
+ * shape is generic enough for any dialect with similar per-table engine/
15
+ * storage options (e.g. MySQL's `ENGINE=InnoDB`).
16
+ *
17
+ * Example:
18
+ *
19
+ * @Engine({
20
+ * mergeTreeEngine: { type: 'ReplacingMergeTree', version: 'updatedAt' },
21
+ * orderBy: ['id', 'createdAt'],
22
+ * ttl: 'createdAt + INTERVAL 90 DAY',
23
+ * })
24
+ * class Event extends Model {
25
+ * declare id: number;
26
+ * declare createdAt: Date;
27
+ * declare updatedAt: Date;
28
+ * }
29
+ *
30
+ * // At table-creation time:
31
+ * const dialect = prorm.getDialectInstance() as ClickHouseDialect;
32
+ * await dialect.createTable('events', columns, {
33
+ * ...EngineRegistry.getTableOptions(Event),
34
+ * });
35
+ */
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.EngineRegistry = void 0;
38
+ exports.getEngineOptions = getEngineOptions;
39
+ exports.Engine = Engine;
40
+ // ==================== Registry ====================
41
+ const ENGINE_OPTIONS_KEY = '__orm_engine_options__';
42
+ /**
43
+ * Read the @Engine options attached to a class.
44
+ * Returns undefined if the class has no @Engine decorator.
45
+ */
46
+ function getEngineOptions(target) {
47
+ return target[ENGINE_OPTIONS_KEY];
48
+ }
49
+ // ==================== Decorator ====================
50
+ /**
51
+ * Annotate a Model subclass with dialect-specific storage-engine
52
+ * configuration.
53
+ *
54
+ * @Engine({ mergeTreeEngine: { type: 'AggregatingMergeTree' }, orderBy: ['id'] })
55
+ * class Metrics extends Model { ... }
56
+ */
57
+ function Engine(options) {
58
+ return function (target) {
59
+ target[ENGINE_OPTIONS_KEY] = { ...options };
60
+ };
61
+ }
62
+ // ==================== Public Registry API ====================
63
+ exports.EngineRegistry = {
64
+ /**
65
+ * Read the raw @Engine options attached to a class.
66
+ */
67
+ getOptions(target) {
68
+ return getEngineOptions(target);
69
+ },
70
+ /**
71
+ * Returns the @Engine options in the shape `createTable()` expects to be
72
+ * spread into its `options` argument (ClickHouse reads `mergeTreeEngine`/
73
+ * `orderBy`/`ttl`/`partitionBy`/`projections` as loosely-typed extensions;
74
+ * MySQL/MariaDB read `engine` directly off `TableOptions`). Returns an
75
+ * empty object (not undefined) when the class has no @Engine decorator,
76
+ * so callers can always safely spread the result.
77
+ */
78
+ getTableOptions(target) {
79
+ const opts = getEngineOptions(target);
80
+ if (!opts)
81
+ return {};
82
+ const tableOptions = {};
83
+ if (opts.engine !== undefined)
84
+ tableOptions.engine = opts.engine;
85
+ if (opts.mergeTreeEngine !== undefined)
86
+ tableOptions.mergeTreeEngine = opts.mergeTreeEngine;
87
+ if (opts.orderBy !== undefined)
88
+ tableOptions.orderBy = opts.orderBy;
89
+ if (opts.partitionBy !== undefined)
90
+ tableOptions.partitionBy = opts.partitionBy;
91
+ if (opts.ttl !== undefined)
92
+ tableOptions.ttl = opts.ttl;
93
+ if (opts.projections !== undefined)
94
+ tableOptions.projections = opts.projections;
95
+ return tableOptions;
96
+ },
97
+ };