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,2518 @@
1
+ "use strict";
2
+ /**
3
+ * Data Types for the ORM
4
+ * Provides all standard data types with proper class implementations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.GEOMETRYCOLLECTION = exports.MULTIPOLYGON = exports.MULTILINESTRING = exports.MULTIPOINT = exports.POLYGON = exports.LINESTRING = exports.POINT = exports.GEOGRAPHY = exports.GEOMETRY = exports.DUCKDB_UNION = exports.MAP = exports.STRUCT = exports.LIST = exports.ARRAY = exports.ENUM = exports.VARBINARY = exports.BINARY = exports.LONGBLOB = exports.MEDIUMBLOB = exports.TINYBLOB = exports.BLOB = exports.JSONB = exports.JSON = exports.UUIDV4 = exports.UUIDV1 = exports.UUID = exports.TIME = exports.NOW = exports.TIMESTAMP = exports.DATETIME = exports.DATEONLY = exports.DATE = exports.BOOLEAN = exports.REAL = exports.DECIMAL = exports.DOUBLE = exports.FLOAT = exports.BIGINT = exports.MEDIUMINT = exports.SMALLINT = exports.TINYINT = exports.INTEGER = exports.LONGTEXT = exports.MEDIUMTEXT = exports.TINYTEXT = exports.TEXT = exports.CHAR = exports.VARCHAR = exports.STRING = exports.DataTypes = void 0;
8
+ exports.AbstractDataType = exports.MACADDR = exports.CIDR = exports.INET = exports.RANGE = exports.HSTORE = exports.ALGORITHM = exports.VIRTUALSTRING = exports.VIRTUAL = exports.JSONColumn = exports.SET = void 0;
9
+ /**
10
+ * Base class for all data types
11
+ */
12
+ class AbstractDataType {
13
+ toSqlString(dialect) {
14
+ return this.key;
15
+ }
16
+ toSQL() {
17
+ return this.toSqlString();
18
+ }
19
+ // Alias for toSQL for compatibility
20
+ toSql() {
21
+ return this.toSqlString();
22
+ }
23
+ /**
24
+ * Compare this DataType with another DataType for equality
25
+ * @param other - The DataType to compare with
26
+ * @returns true if the types are equal, false otherwise
27
+ */
28
+ equals(other) {
29
+ if (!other || typeof other !== 'object') {
30
+ return false;
31
+ }
32
+ return this.key === other.key;
33
+ }
34
+ /**
35
+ * Serialize a value for storage based on this DataType
36
+ * @param value - The value to serialize
37
+ * @returns The serialized value
38
+ */
39
+ serialize(value) {
40
+ return value;
41
+ }
42
+ }
43
+ exports.AbstractDataType = AbstractDataType;
44
+ // STRING types
45
+ class STRING extends AbstractDataType {
46
+ /**
47
+ * Create a STRING data type
48
+ * @param length - Optional length (1-65535). If not provided, defaults to TEXT
49
+ * @param binary - Whether to use BINARY collation
50
+ * @example
51
+ * // STRING with length (VARCHAR)
52
+ * DataTypes.STRING(100) // VARCHAR(100)
53
+ * // STRING without length (TEXT)
54
+ * DataTypes.STRING // TEXT
55
+ */
56
+ constructor(length, binary = false) {
57
+ super();
58
+ this.key = 'STRING';
59
+ this.length = length;
60
+ this.binary = binary;
61
+ }
62
+ toSqlString() {
63
+ // If no length specified, return TEXT
64
+ if (this.length === undefined || this.length === null) {
65
+ return 'TEXT';
66
+ }
67
+ const binaryStr = this.binary ? ' BINARY' : '';
68
+ return `VARCHAR(${this.length})${binaryStr}`;
69
+ }
70
+ }
71
+ exports.STRING = STRING;
72
+ class VARCHAR extends AbstractDataType {
73
+ constructor(length = 255, binary = false) {
74
+ super();
75
+ this.key = 'VARCHAR';
76
+ this.length = length;
77
+ this.binary = binary;
78
+ }
79
+ toSqlString() {
80
+ const binaryStr = this.binary ? ' BINARY' : '';
81
+ return `VARCHAR(${this.length})${binaryStr}`;
82
+ }
83
+ }
84
+ exports.VARCHAR = VARCHAR;
85
+ class CHAR extends AbstractDataType {
86
+ constructor(length = 1) {
87
+ super();
88
+ this.key = 'CHAR';
89
+ this.length = length;
90
+ }
91
+ toSqlString() {
92
+ return `CHAR(${this.length})`;
93
+ }
94
+ }
95
+ exports.CHAR = CHAR;
96
+ // TEXT types
97
+ class TEXT extends AbstractDataType {
98
+ constructor(length) {
99
+ super();
100
+ this.key = 'TEXT';
101
+ this.length = length;
102
+ }
103
+ /**
104
+ * Get the TEXT type string based on length variant for MySQL/MariaDB
105
+ */
106
+ getTextType() {
107
+ if (!this.length) {
108
+ return 'TEXT';
109
+ }
110
+ // MySQL/MariaDB format: TINYTEXT, MEDIUMTEXT, LONGTEXT
111
+ if (this.length === 'tiny')
112
+ return 'TINYTEXT';
113
+ if (this.length === 'medium')
114
+ return 'MEDIUMTEXT';
115
+ if (this.length === 'long')
116
+ return 'LONGTEXT';
117
+ return 'TEXT';
118
+ }
119
+ toSqlString(dialect) {
120
+ switch (dialect) {
121
+ case 'postgres':
122
+ // PostgreSQL: Use TEXT for all variants
123
+ return 'TEXT';
124
+ case 'mysql':
125
+ case 'mariadb':
126
+ // MySQL/MariaDB: TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT
127
+ return this.getTextType();
128
+ case 'sqlite':
129
+ // SQLite: Use TEXT for all variants
130
+ return 'TEXT';
131
+ case 'mssql':
132
+ case 'sqlserver':
133
+ // SQL Server: Use TEXT (deprecated) or NVARCHAR(MAX) for large text
134
+ return 'NVARCHAR(MAX)';
135
+ default:
136
+ // Default to standard TEXT
137
+ return this.getTextType();
138
+ }
139
+ }
140
+ }
141
+ exports.TEXT = TEXT;
142
+ // Convenience classes for specific TEXT length variants (MySQL/MariaDB)
143
+ class TINYTEXT extends AbstractDataType {
144
+ constructor() {
145
+ super(...arguments);
146
+ this.key = 'TINYTEXT';
147
+ }
148
+ toSqlString(dialect) {
149
+ switch (dialect) {
150
+ case 'postgres':
151
+ case 'sqlite':
152
+ return 'TEXT';
153
+ case 'mysql':
154
+ case 'mariadb':
155
+ return 'TINYTEXT';
156
+ case 'mssql':
157
+ case 'sqlserver':
158
+ return 'NVARCHAR(MAX)';
159
+ default:
160
+ return 'TINYTEXT';
161
+ }
162
+ }
163
+ }
164
+ exports.TINYTEXT = TINYTEXT;
165
+ class MEDIUMTEXT extends AbstractDataType {
166
+ constructor() {
167
+ super(...arguments);
168
+ this.key = 'MEDIUMTEXT';
169
+ }
170
+ toSqlString(dialect) {
171
+ switch (dialect) {
172
+ case 'postgres':
173
+ case 'sqlite':
174
+ return 'TEXT';
175
+ case 'mysql':
176
+ case 'mariadb':
177
+ return 'MEDIUMTEXT';
178
+ case 'mssql':
179
+ case 'sqlserver':
180
+ return 'NVARCHAR(MAX)';
181
+ default:
182
+ return 'MEDIUMTEXT';
183
+ }
184
+ }
185
+ }
186
+ exports.MEDIUMTEXT = MEDIUMTEXT;
187
+ class LONGTEXT extends AbstractDataType {
188
+ constructor() {
189
+ super(...arguments);
190
+ this.key = 'LONGTEXT';
191
+ }
192
+ toSqlString(dialect) {
193
+ switch (dialect) {
194
+ case 'postgres':
195
+ case 'sqlite':
196
+ return 'TEXT';
197
+ case 'mysql':
198
+ case 'mariadb':
199
+ return 'LONGTEXT';
200
+ case 'mssql':
201
+ case 'sqlserver':
202
+ return 'NVARCHAR(MAX)';
203
+ default:
204
+ return 'LONGTEXT';
205
+ }
206
+ }
207
+ }
208
+ exports.LONGTEXT = LONGTEXT;
209
+ // Base class for integer types with unsigned and zerofill support
210
+ class AbstractIntegerType extends AbstractDataType {
211
+ /**
212
+ * Set as unsigned
213
+ * @example
214
+ * DataTypes.INTEGER.UNSIGNED()
215
+ * DataTypes.BIGINT.UNSIGNED()
216
+ */
217
+ UNSIGNED() {
218
+ this.unsigned = true;
219
+ return this;
220
+ }
221
+ /**
222
+ * Set as zerofill
223
+ * @example
224
+ * DataTypes.INTEGER.ZEROFILL()
225
+ * DataTypes.INTEGER.UNSIGNED().ZEROFILL()
226
+ */
227
+ ZEROFILL() {
228
+ this.zerofill = true;
229
+ return this;
230
+ }
231
+ /**
232
+ * Generate SQL string with unsigned and zerofill options
233
+ */
234
+ toSqlStringHelper(baseType) {
235
+ let sql = baseType;
236
+ if (this.length) {
237
+ sql = `${baseType}(${this.length})`;
238
+ }
239
+ if (this.unsigned) {
240
+ sql += ' UNSIGNED';
241
+ }
242
+ if (this.zerofill) {
243
+ sql += ' ZEROFILL';
244
+ }
245
+ return sql;
246
+ }
247
+ }
248
+ // Number types
249
+ class INTEGER extends AbstractIntegerType {
250
+ constructor(options = {}) {
251
+ super();
252
+ this.key = 'INTEGER';
253
+ this.length = options.length;
254
+ this.unsigned = options.unsigned;
255
+ this.zerofill = options.zerofill;
256
+ }
257
+ toSqlString() {
258
+ return this.toSqlStringHelper('INTEGER');
259
+ }
260
+ }
261
+ exports.INTEGER = INTEGER;
262
+ // TINYINT - tiny integer (1 byte, -128 to 127 signed, 0 to 255 unsigned)
263
+ class TINYINT extends AbstractIntegerType {
264
+ /**
265
+ * Create a TINYINT data type
266
+ * @param options - Optional options object
267
+ * @example
268
+ * // Simple TINYINT
269
+ * DataTypes.TINYINT()
270
+ * // TINYINT with options
271
+ * DataTypes.TINYINT({ unsigned: true })
272
+ * // Using chainable methods
273
+ * DataTypes.TINYINT().UNSIGNED()
274
+ * DataTypes.TINYINT().ZEROFILL()
275
+ */
276
+ constructor(options = {}) {
277
+ super();
278
+ this.key = 'TINYINT';
279
+ this.length = options.length;
280
+ this.unsigned = options.unsigned;
281
+ this.zerofill = options.zerofill;
282
+ }
283
+ toSqlString() {
284
+ return this.toSqlStringHelper('TINYINT');
285
+ }
286
+ }
287
+ exports.TINYINT = TINYINT;
288
+ // SMALLINT - small integer (2 bytes, -32768 to 32767 signed, 0 to 65535 unsigned)
289
+ class SMALLINT extends AbstractIntegerType {
290
+ /**
291
+ * Create a SMALLINT data type
292
+ * @param options - Optional options object
293
+ * @example
294
+ * // Simple SMALLINT
295
+ * DataTypes.SMALLINT()
296
+ * // SMALLINT with options
297
+ * DataTypes.SMALLINT({ unsigned: true })
298
+ * // Using chainable methods
299
+ * DataTypes.SMALLINT().UNSIGNED()
300
+ * DataTypes.SMALLINT().ZEROFILL()
301
+ */
302
+ constructor(options = {}) {
303
+ super();
304
+ this.key = 'SMALLINT';
305
+ this.length = options.length;
306
+ this.unsigned = options.unsigned;
307
+ this.zerofill = options.zerofill;
308
+ }
309
+ toSqlString() {
310
+ return this.toSqlStringHelper('SMALLINT');
311
+ }
312
+ }
313
+ exports.SMALLINT = SMALLINT;
314
+ // MEDIUMINT - medium integer (3 bytes, -8388608 to 8388607 signed, 0 to 16777215 unsigned)
315
+ class MEDIUMINT extends AbstractIntegerType {
316
+ /**
317
+ * Create a MEDIUMINT data type
318
+ * @param options - Optional options object
319
+ * @example
320
+ * // Simple MEDIUMINT
321
+ * DataTypes.MEDIUMINT()
322
+ * // MEDIUMINT with options
323
+ * DataTypes.MEDIUMINT({ unsigned: true })
324
+ * // Using chainable methods
325
+ * DataTypes.MEDIUMINT().UNSIGNED()
326
+ * DataTypes.MEDIUMINT().ZEROFILL()
327
+ */
328
+ constructor(options = {}) {
329
+ super();
330
+ this.key = 'MEDIUMINT';
331
+ this.length = options.length;
332
+ this.unsigned = options.unsigned;
333
+ this.zerofill = options.zerofill;
334
+ }
335
+ toSqlString() {
336
+ return this.toSqlStringHelper('MEDIUMINT');
337
+ }
338
+ }
339
+ exports.MEDIUMINT = MEDIUMINT;
340
+ class BIGINT extends AbstractIntegerType {
341
+ /**
342
+ * Create a BIGINT data type
343
+ * @param options - Optional options object
344
+ * @example
345
+ * // Simple BIGINT
346
+ * DataTypes.BIGINT()
347
+ * // BIGINT with options
348
+ * DataTypes.BIGINT({ unsigned: true })
349
+ * // Using chainable methods
350
+ * DataTypes.BIGINT().UNSIGNED()
351
+ * DataTypes.BIGINT().ZEROFILL()
352
+ */
353
+ constructor(options = {}) {
354
+ super();
355
+ this.key = 'BIGINT';
356
+ this.length = options.length;
357
+ this.unsigned = options.unsigned;
358
+ this.zerofill = options.zerofill;
359
+ }
360
+ toSqlString() {
361
+ return this.toSqlStringHelper('BIGINT');
362
+ }
363
+ }
364
+ exports.BIGINT = BIGINT;
365
+ class FLOAT extends AbstractDataType {
366
+ /**
367
+ * Create a FLOAT data type
368
+ * @param precisionOrOptions - Either a precision number or an options object
369
+ * @example
370
+ * // Simple FLOAT
371
+ * DataTypes.FLOAT()
372
+ * // FLOAT with precision
373
+ * DataTypes.FLOAT(8)
374
+ * // FLOAT with options
375
+ * DataTypes.FLOAT({ precision: 8, decimals: 2, unsigned: true })
376
+ */
377
+ constructor(precisionOrOptions) {
378
+ super();
379
+ this.key = 'FLOAT';
380
+ if (typeof precisionOrOptions === 'number') {
381
+ this.precision = precisionOrOptions;
382
+ }
383
+ else if (precisionOrOptions) {
384
+ this.precision = precisionOrOptions.precision;
385
+ this.decimals = precisionOrOptions.decimals;
386
+ this.unsigned = precisionOrOptions.unsigned;
387
+ }
388
+ }
389
+ toSqlString(dialect) {
390
+ let sql = 'FLOAT';
391
+ if (this.precision) {
392
+ // MySQL/MariaDB support FLOAT(p) where p is precision
393
+ if (this.decimals) {
394
+ sql = `FLOAT(${this.precision},${this.decimals})`;
395
+ }
396
+ else if (dialect === 'mysql' || dialect === 'mariadb') {
397
+ sql = `FLOAT(${this.precision})`;
398
+ }
399
+ }
400
+ if (this.unsigned) {
401
+ sql += ' UNSIGNED';
402
+ }
403
+ return sql;
404
+ }
405
+ }
406
+ exports.FLOAT = FLOAT;
407
+ class DOUBLE extends AbstractDataType {
408
+ /**
409
+ * Create a DOUBLE data type
410
+ * @param precisionOrOptions - Either a precision number or an options object
411
+ * @example
412
+ * // Simple DOUBLE
413
+ * DataTypes.DOUBLE()
414
+ * // DOUBLE with precision (MySQL/MariaDB)
415
+ * DataTypes.DOUBLE(16)
416
+ * // DOUBLE with options (backward compatibility)
417
+ * DataTypes.DOUBLE({ precision: 16, decimals: 4, unsigned: true })
418
+ */
419
+ constructor(precisionOrOptions) {
420
+ super();
421
+ this.key = 'DOUBLE';
422
+ if (typeof precisionOrOptions === 'number') {
423
+ this.precision = precisionOrOptions;
424
+ }
425
+ else if (precisionOrOptions) {
426
+ this.precision = precisionOrOptions.precision;
427
+ this.decimals = precisionOrOptions.decimals;
428
+ this.unsigned = precisionOrOptions.unsigned;
429
+ }
430
+ }
431
+ toSqlString(dialect) {
432
+ let sql = 'DOUBLE';
433
+ if (this.precision) {
434
+ // MySQL/MariaDB support DOUBLE(p) where p is precision
435
+ if (this.decimals) {
436
+ sql = `DOUBLE(${this.precision},${this.decimals})`;
437
+ }
438
+ else if (dialect === 'mysql' || dialect === 'mariadb') {
439
+ sql = `DOUBLE(${this.precision})`;
440
+ }
441
+ }
442
+ else if (this.decimals) {
443
+ // Backward compatibility: DOUBLE with only decimals
444
+ sql = `DOUBLE(10,${this.decimals})`;
445
+ }
446
+ if (this.unsigned) {
447
+ sql += ' UNSIGNED';
448
+ }
449
+ return sql;
450
+ }
451
+ }
452
+ exports.DOUBLE = DOUBLE;
453
+ class DECIMAL extends AbstractDataType {
454
+ /**
455
+ * Create a DECIMAL data type
456
+ * @param precisionOrOptions - Either precision number or an options object
457
+ * @param scale - Number of decimal places (when precision is a number)
458
+ * @param unsigned - Whether the value is unsigned
459
+ * @example
460
+ * // DECIMAL with default precision (10, 0)
461
+ * DataTypes.DECIMAL()
462
+ * // DECIMAL with precision only (scale defaults to 0)
463
+ * DataTypes.DECIMAL(10)
464
+ * // DECIMAL with precision and scale
465
+ * DataTypes.DECIMAL(10, 2)
466
+ * // DECIMAL with options object
467
+ * DataTypes.DECIMAL({ precision: 10, scale: 2, unsigned: true })
468
+ */
469
+ constructor(precisionOrOptions, scale = 0, unsigned = false) {
470
+ super();
471
+ this.key = 'DECIMAL';
472
+ if (typeof precisionOrOptions === 'number') {
473
+ this.precision = precisionOrOptions;
474
+ this.scale = scale;
475
+ this.unsigned = unsigned;
476
+ }
477
+ else if (precisionOrOptions) {
478
+ this.precision = precisionOrOptions.precision ?? 10;
479
+ this.scale = precisionOrOptions.scale ?? 0;
480
+ this.unsigned = precisionOrOptions.unsigned;
481
+ }
482
+ else {
483
+ // Default: DECIMAL(10, 0)
484
+ this.precision = 10;
485
+ this.scale = 0;
486
+ this.unsigned = false;
487
+ }
488
+ }
489
+ toSqlString(dialect) {
490
+ let sql = `DECIMAL(${this.precision},${this.scale})`;
491
+ // UNSIGNED is not standard for DECIMAL in most dialects
492
+ // Only MySQL/MariaDB support it
493
+ if (this.unsigned && (dialect === 'mysql' || dialect === 'mariadb')) {
494
+ sql += ' UNSIGNED';
495
+ }
496
+ return sql;
497
+ }
498
+ }
499
+ exports.DECIMAL = DECIMAL;
500
+ // Boolean
501
+ class BOOLEAN extends AbstractDataType {
502
+ constructor() {
503
+ super(...arguments);
504
+ this.key = 'BOOLEAN';
505
+ }
506
+ toSqlString() {
507
+ return 'INTEGER'; // SQLite uses INTEGER for booleans
508
+ }
509
+ }
510
+ exports.BOOLEAN = BOOLEAN;
511
+ // Date types
512
+ class DATE extends AbstractDataType {
513
+ constructor(precision, timezone = false) {
514
+ super();
515
+ this.key = 'DATE';
516
+ this.precision = precision;
517
+ this.timezone = timezone;
518
+ }
519
+ toSqlString(dialect) {
520
+ const precisionStr = this.precision !== undefined ? `(${this.precision})` : '';
521
+ switch (dialect) {
522
+ case 'postgres':
523
+ // PostgreSQL: TIMESTAMP WITH/WITHOUT TIME ZONE
524
+ return this.timezone
525
+ ? `TIMESTAMP${precisionStr} WITH TIME ZONE`
526
+ : `TIMESTAMP${precisionStr}`;
527
+ case 'mysql':
528
+ case 'mariadb':
529
+ // MySQL/MariaDB: DATETIME or TIMESTAMP
530
+ return `DATETIME${precisionStr}`;
531
+ case 'sqlite':
532
+ // SQLite stores dates as TEXT in ISO8601 format
533
+ return `TEXT`;
534
+ case 'mssql':
535
+ case 'sqlserver':
536
+ // SQL Server: DATETIME2 for more precision
537
+ return `DATETIME2${precisionStr}`;
538
+ default:
539
+ return `DATETIME${precisionStr}`;
540
+ }
541
+ }
542
+ }
543
+ exports.DATE = DATE;
544
+ class DATEONLY extends AbstractDataType {
545
+ constructor() {
546
+ super(...arguments);
547
+ this.key = 'DATEONLY';
548
+ }
549
+ toSqlString(dialect) {
550
+ switch (dialect) {
551
+ case 'postgres':
552
+ // PostgreSQL: DATE
553
+ return 'DATE';
554
+ case 'mysql':
555
+ case 'mariadb':
556
+ // MySQL/MariaDB: DATE
557
+ return 'DATE';
558
+ case 'sqlite':
559
+ // SQLite stores dates as TEXT in ISO8601 format (YYYY-MM-DD)
560
+ return 'TEXT';
561
+ case 'mssql':
562
+ case 'sqlserver':
563
+ // SQL Server: DATE
564
+ return 'DATE';
565
+ default:
566
+ return 'DATE';
567
+ }
568
+ }
569
+ }
570
+ exports.DATEONLY = DATEONLY;
571
+ class TIME extends AbstractDataType {
572
+ constructor(precision, timezone = false) {
573
+ super();
574
+ this.key = 'TIME';
575
+ this.precision = precision;
576
+ this.timezone = timezone;
577
+ }
578
+ toSqlString(dialect) {
579
+ const precisionStr = this.precision !== undefined ? `(${this.precision})` : '';
580
+ switch (dialect) {
581
+ case 'postgres':
582
+ // PostgreSQL: TIME WITH/WITHOUT TIME ZONE
583
+ return this.timezone ? `TIME${precisionStr} WITH TIME ZONE` : `TIME${precisionStr}`;
584
+ case 'mysql':
585
+ case 'mariadb':
586
+ // MySQL/MariaDB: TIME
587
+ return `TIME${precisionStr}`;
588
+ case 'sqlite':
589
+ // SQLite stores time as TEXT in ISO8601 format
590
+ return `TEXT`;
591
+ case 'mssql':
592
+ case 'sqlserver':
593
+ // SQL Server: TIME
594
+ return `TIME${precisionStr}`;
595
+ default:
596
+ return `TIME${precisionStr}`;
597
+ }
598
+ }
599
+ }
600
+ exports.TIME = TIME;
601
+ // REAL - single-precision floating point (native SQLite storage class,
602
+ // PostgreSQL/MSSQL 4-byte float, alias for FLOAT/DOUBLE in MySQL/MariaDB)
603
+ class REAL extends AbstractDataType {
604
+ /**
605
+ * Create a REAL data type
606
+ * @param precisionOrOptions - Either a precision number or an options object
607
+ * @example
608
+ * // Simple REAL
609
+ * DataTypes.REAL()
610
+ * // REAL with precision (MySQL/MariaDB)
611
+ * DataTypes.REAL(10)
612
+ * // REAL with options
613
+ * DataTypes.REAL({ precision: 10, decimals: 2, unsigned: true })
614
+ */
615
+ constructor(precisionOrOptions) {
616
+ super();
617
+ this.key = 'REAL';
618
+ if (typeof precisionOrOptions === 'number') {
619
+ this.precision = precisionOrOptions;
620
+ }
621
+ else if (precisionOrOptions) {
622
+ this.precision = precisionOrOptions.precision;
623
+ this.decimals = precisionOrOptions.decimals;
624
+ this.unsigned = precisionOrOptions.unsigned;
625
+ }
626
+ }
627
+ toSqlString(dialect) {
628
+ let sql = 'REAL';
629
+ if (this.precision && this.decimals && (dialect === 'mysql' || dialect === 'mariadb')) {
630
+ // MySQL/MariaDB REAL is an alias for DOUBLE and supports (precision,decimals)
631
+ sql = `REAL(${this.precision},${this.decimals})`;
632
+ }
633
+ if (this.unsigned && (dialect === 'mysql' || dialect === 'mariadb')) {
634
+ sql += ' UNSIGNED';
635
+ }
636
+ return sql;
637
+ }
638
+ }
639
+ exports.REAL = REAL;
640
+ // TIMESTAMP - dedicated timestamp type distinct from DATE/NOW
641
+ class TIMESTAMP extends AbstractDataType {
642
+ constructor(precision) {
643
+ super();
644
+ this.key = 'TIMESTAMP';
645
+ this.precision = precision;
646
+ }
647
+ toSqlString(dialect) {
648
+ const precisionStr = this.precision !== undefined ? `(${this.precision})` : '';
649
+ switch (dialect) {
650
+ case 'postgres':
651
+ return `TIMESTAMP${precisionStr}`;
652
+ case 'mysql':
653
+ case 'mariadb':
654
+ return `TIMESTAMP${precisionStr}`;
655
+ case 'sqlite':
656
+ // SQLite stores timestamps as TEXT in ISO8601 format
657
+ return 'TEXT';
658
+ case 'mssql':
659
+ case 'sqlserver':
660
+ return `DATETIME2${precisionStr}`;
661
+ default:
662
+ return `TIMESTAMP${precisionStr}`;
663
+ }
664
+ }
665
+ /**
666
+ * Get the current timestamp SQL for use as a default value
667
+ */
668
+ toDefaultValue(dialect) {
669
+ switch (dialect) {
670
+ case 'sqlite':
671
+ return "datetime('now')";
672
+ case 'mssql':
673
+ case 'sqlserver':
674
+ return 'GETDATE()';
675
+ default:
676
+ return 'CURRENT_TIMESTAMP';
677
+ }
678
+ }
679
+ }
680
+ exports.TIMESTAMP = TIMESTAMP;
681
+ // DATETIME - explicit datetime type (distinct from DATE, which supports timezone options)
682
+ class DATETIME extends AbstractDataType {
683
+ constructor(precision) {
684
+ super();
685
+ this.key = 'DATETIME';
686
+ this.precision = precision;
687
+ }
688
+ toSqlString(dialect) {
689
+ const precisionStr = this.precision !== undefined ? `(${this.precision})` : '';
690
+ switch (dialect) {
691
+ case 'postgres':
692
+ return `TIMESTAMP${precisionStr}`;
693
+ case 'mysql':
694
+ case 'mariadb':
695
+ return `DATETIME${precisionStr}`;
696
+ case 'sqlite':
697
+ // SQLite stores dates as TEXT in ISO8601 format
698
+ return 'TEXT';
699
+ case 'mssql':
700
+ case 'sqlserver':
701
+ return `DATETIME2${precisionStr}`;
702
+ default:
703
+ return `DATETIME${precisionStr}`;
704
+ }
705
+ }
706
+ }
707
+ exports.DATETIME = DATETIME;
708
+ // UUID - stores UUID strings (works with all dialects)
709
+ class UUID extends AbstractDataType {
710
+ constructor() {
711
+ super(...arguments);
712
+ this.key = 'UUID';
713
+ }
714
+ toSqlString(dialect) {
715
+ switch (dialect) {
716
+ case 'postgres':
717
+ return 'UUID';
718
+ case 'mysql':
719
+ case 'mariadb':
720
+ return 'VARCHAR(36)';
721
+ case 'sqlite':
722
+ default:
723
+ return 'TEXT';
724
+ }
725
+ }
726
+ }
727
+ exports.UUID = UUID;
728
+ // UUIDV4 - auto-generates UUID v4 on insert (works with all dialects)
729
+ class UUIDV4 extends AbstractDataType {
730
+ constructor() {
731
+ super(...arguments);
732
+ this.key = 'UUIDV4';
733
+ }
734
+ toSqlString(dialect) {
735
+ switch (dialect) {
736
+ case 'postgres':
737
+ return 'UUID';
738
+ case 'mysql':
739
+ case 'mariadb':
740
+ return 'VARCHAR(36)';
741
+ case 'sqlite':
742
+ default:
743
+ return 'TEXT';
744
+ }
745
+ }
746
+ /**
747
+ * Get the default value for UUIDV4 - generates a new UUID v4 string
748
+ * This is called by the dialect when using UUIDV4 as a defaultValue
749
+ */
750
+ toDefaultValue(_dialect) {
751
+ return UUIDV4.generate();
752
+ }
753
+ /**
754
+ * Generate a UUID v4 string (instance method)
755
+ */
756
+ generate() {
757
+ return UUIDV4.generate();
758
+ }
759
+ /**
760
+ * Generate a UUID v4 string (static method)
761
+ */
762
+ static generate() {
763
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
764
+ const r = (Math.random() * 16) | 0;
765
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
766
+ return v.toString(16);
767
+ });
768
+ }
769
+ }
770
+ exports.UUIDV4 = UUIDV4;
771
+ // UUIDV1 - auto-generates a time-based UUID v1 on insert (works with all dialects)
772
+ class UUIDV1 extends AbstractDataType {
773
+ constructor() {
774
+ super(...arguments);
775
+ this.key = 'UUIDV1';
776
+ }
777
+ toSqlString(dialect) {
778
+ switch (dialect) {
779
+ case 'postgres':
780
+ return 'UUID';
781
+ case 'mysql':
782
+ case 'mariadb':
783
+ return 'VARCHAR(36)';
784
+ case 'sqlite':
785
+ default:
786
+ return 'TEXT';
787
+ }
788
+ }
789
+ /**
790
+ * Get the default value for UUIDV1 - generates a new UUID v1 string
791
+ * This is called by the dialect when using UUIDV1 as a defaultValue
792
+ */
793
+ toDefaultValue(_dialect) {
794
+ return UUIDV1.generate();
795
+ }
796
+ /**
797
+ * Generate a UUID v1 string (instance method)
798
+ */
799
+ generate() {
800
+ return UUIDV1.generate();
801
+ }
802
+ /**
803
+ * Generate a time-based UUID v1 string (static method)
804
+ * Note: This is a simplified, structurally-valid v1 UUID (RFC 4122 layout:
805
+ * time_low-time_mid-time_hi_and_version-clock_seq-node) derived from the
806
+ * current timestamp. It does not track a persistent MAC address or clock
807
+ * sequence across calls, which is acceptable for use as a unique row id.
808
+ */
809
+ static generate() {
810
+ // 100-nanosecond intervals between the UUID epoch (1582-10-15) and the Unix epoch
811
+ const UUID_EPOCH_OFFSET = 122192928000000000n;
812
+ const timestamp = BigInt(Date.now()) * 10000n + UUID_EPOCH_OFFSET;
813
+ const timeLow = (timestamp & 0xffffffffn).toString(16).padStart(8, '0');
814
+ const timeMid = ((timestamp >> 32n) & 0xffffn).toString(16).padStart(4, '0');
815
+ const timeHiAndVersion = (((timestamp >> 48n) & 0x0fffn) | 0x1000n)
816
+ .toString(16)
817
+ .padStart(4, '0');
818
+ const clockSeq = ((Math.floor(Math.random() * 0x3fff) & 0x3fff) | 0x8000)
819
+ .toString(16)
820
+ .padStart(4, '0');
821
+ const node = Array.from({ length: 6 }, () => Math.floor(Math.random() * 256)
822
+ .toString(16)
823
+ .padStart(2, '0')).join('');
824
+ return `${timeLow}-${timeMid}-${timeHiAndVersion}-${clockSeq}-${node}`;
825
+ }
826
+ }
827
+ exports.UUIDV1 = UUIDV1;
828
+ // NOW - current timestamp
829
+ class NOW extends AbstractDataType {
830
+ constructor(precision) {
831
+ super();
832
+ this.key = 'NOW';
833
+ this.precision = precision;
834
+ }
835
+ /**
836
+ * Get the current timestamp SQL for use as default value
837
+ * This returns the raw SQL function name that gets passed through
838
+ * without quotes in the defaultValue handling
839
+ */
840
+ toDefaultValue(dialect) {
841
+ switch (dialect) {
842
+ case 'postgres':
843
+ // PostgreSQL: CURRENT_TIMESTAMP or NOW()
844
+ return 'CURRENT_TIMESTAMP';
845
+ case 'mysql':
846
+ case 'mariadb':
847
+ // MySQL/MariaDB: CURRENT_TIMESTAMP or NOW()
848
+ return 'CURRENT_TIMESTAMP';
849
+ case 'sqlite':
850
+ // SQLite: datetime('now')
851
+ return "datetime('now')";
852
+ case 'mssql':
853
+ case 'sqlserver':
854
+ // SQL Server: GETDATE() or GETUTCDATE()
855
+ return 'GETDATE()';
856
+ default:
857
+ // Default to standard SQL
858
+ return 'CURRENT_TIMESTAMP';
859
+ }
860
+ }
861
+ toSqlString(dialect) {
862
+ // When used as a column type, generate proper DATETIME type
863
+ const precisionStr = this.precision !== undefined ? `(${this.precision})` : '';
864
+ switch (dialect) {
865
+ case 'postgres':
866
+ return `TIMESTAMP${precisionStr}`;
867
+ case 'mysql':
868
+ case 'mariadb':
869
+ return `DATETIME${precisionStr}`;
870
+ case 'sqlite':
871
+ // SQLite uses TEXT for timestamps but supports datetime() function
872
+ return 'TEXT';
873
+ case 'mssql':
874
+ case 'sqlserver':
875
+ return `DATETIME2${precisionStr}`;
876
+ default:
877
+ return 'DATETIME';
878
+ }
879
+ }
880
+ }
881
+ exports.NOW = NOW;
882
+ // JSON types with dialect-specific handling
883
+ /**
884
+ * JSON - standard JSON (text-based)
885
+ * - PostgreSQL: native JSON type
886
+ * - MySQL/MariaDB: native JSON type
887
+ * - SQLite: TEXT with JSON handling
888
+ *
889
+ * @example
890
+ * // Use native JSON where supported
891
+ * metadata: DataTypes.JSON(true)
892
+ * // Use TEXT fallback (useful for SQLite compatibility)
893
+ * settings: DataTypes.JSON(false) // or DataTypes.JSON()
894
+ */
895
+ class JSON extends AbstractDataType {
896
+ constructor(useNative = false) {
897
+ super();
898
+ this.key = 'JSON';
899
+ this.useNative = useNative;
900
+ }
901
+ toSqlString(dialect) {
902
+ // If useNative is false, always use TEXT
903
+ if (!this.useNative) {
904
+ return 'TEXT';
905
+ }
906
+ switch (dialect) {
907
+ case 'postgres':
908
+ case 'mysql':
909
+ case 'mariadb':
910
+ return 'JSON';
911
+ case 'sqlite':
912
+ default:
913
+ return 'TEXT';
914
+ }
915
+ }
916
+ }
917
+ exports.JSON = JSON;
918
+ /**
919
+ * JSONB - binary JSON (PostgreSQL native)
920
+ * - PostgreSQL: native JSONB type (binary format, indexed)
921
+ * - MySQL/MariaDB: TEXT with JSON handling (no native JSONB)
922
+ * - SQLite: TEXT with JSON handling
923
+ *
924
+ * Benefits of JSONB in PostgreSQL:
925
+ * - Binary storage format (faster parsing)
926
+ * - Supports indexing with GIN
927
+ * - Key existence operators (? &?| etc.)
928
+ *
929
+ * @example
930
+ * // Use native JSONB for PostgreSQL, TEXT for others
931
+ * settings: DataTypes.JSONB()
932
+ * // or DataTypes.JSONB(true)
933
+ *
934
+ * // Always use TEXT (useful when JSONB features not needed)
935
+ * metadata: DataTypes.JSONB(false)
936
+ */
937
+ class JSONB extends AbstractDataType {
938
+ constructor(useNative = false) {
939
+ super();
940
+ this.key = 'JSONB';
941
+ this.useNative = useNative;
942
+ }
943
+ toSqlString(dialect) {
944
+ // If useNative is false, always use TEXT
945
+ if (!this.useNative) {
946
+ return 'TEXT';
947
+ }
948
+ switch (dialect) {
949
+ case 'postgres':
950
+ // PostgreSQL has native JSONB support
951
+ return 'JSONB';
952
+ case 'mysql':
953
+ case 'mariadb':
954
+ // MySQL/MariaDB: No native JSONB, use JSON type (TEXT fallback)
955
+ return 'JSON';
956
+ case 'sqlite':
957
+ default:
958
+ // SQLite: No native JSON/JSONB support
959
+ return 'TEXT';
960
+ }
961
+ }
962
+ }
963
+ exports.JSONB = JSONB;
964
+ // HSTORE - PostgreSQL key-value type
965
+ // Requires: CREATE EXTENSION IF NOT EXISTS hstore
966
+ class HSTORE extends AbstractDataType {
967
+ constructor(useNative = true) {
968
+ super();
969
+ this.key = 'HSTORE';
970
+ this.useNative = useNative;
971
+ }
972
+ toSqlString(dialect) {
973
+ if (!this.useNative) {
974
+ // Fallback to JSONB for dialects without HStore support
975
+ return 'JSONB';
976
+ }
977
+ switch (dialect) {
978
+ case 'postgres':
979
+ return 'HSTORE';
980
+ case 'mysql':
981
+ case 'mariadb':
982
+ case 'sqlite':
983
+ default:
984
+ // No native HStore support, fallback to JSONB
985
+ return 'JSONB';
986
+ }
987
+ }
988
+ /**
989
+ * Get the SQL to create the HStore extension (PostgreSQL)
990
+ */
991
+ static getExtensionSQL() {
992
+ return 'CREATE EXTENSION IF NOT EXISTS hstore';
993
+ }
994
+ }
995
+ exports.HSTORE = HSTORE;
996
+ // RANGE - PostgreSQL range types
997
+ // Range types: int4range, int8range, numrange, tsrange, tstzrange, daterange
998
+ class RANGE extends AbstractDataType {
999
+ constructor(subtype = 'int4range') {
1000
+ super();
1001
+ this.key = 'RANGE';
1002
+ this.subtype = subtype;
1003
+ }
1004
+ toSqlString(dialect) {
1005
+ switch (dialect) {
1006
+ case 'postgres':
1007
+ return this.subtype;
1008
+ case 'mysql':
1009
+ case 'mariadb':
1010
+ case 'sqlite':
1011
+ default:
1012
+ // Range types not supported, use VARCHAR as fallback
1013
+ return 'VARCHAR(255)';
1014
+ }
1015
+ }
1016
+ }
1017
+ exports.RANGE = RANGE;
1018
+ // INET - PostgreSQL IP address type
1019
+ //
1020
+ // PostgreSQL's own `INET` column stores either an IPv4 or IPv6 address (and
1021
+ // doesn't need to know which up front), so `version` only matters for
1022
+ // dialects - like ClickHouse - that have genuinely distinct fixed-width
1023
+ // IPv4/IPv6 column types (`IPv4` vs `IPv6`) rather than one type that holds
1024
+ // either. Defaults to `4` to preserve the previous unconditional `VARCHAR(45)`
1025
+ // /`IPv4`-shaped behavior for existing callers that don't pass a version.
1026
+ class INET extends AbstractDataType {
1027
+ constructor(options) {
1028
+ super();
1029
+ this.key = 'INET';
1030
+ const version = typeof options === 'number' ? options : options?.version;
1031
+ this.version = version === 6 ? 6 : 4;
1032
+ }
1033
+ toSqlString(dialect) {
1034
+ switch (dialect) {
1035
+ case 'postgres':
1036
+ return 'INET';
1037
+ case 'mysql':
1038
+ case 'mariadb':
1039
+ // MySQL/MariaDB: No INET type, use VARCHAR
1040
+ return 'VARCHAR(45)';
1041
+ case 'sqlite':
1042
+ // SQLite: No INET type, use TEXT
1043
+ return 'TEXT';
1044
+ default:
1045
+ return 'VARCHAR(45)';
1046
+ }
1047
+ }
1048
+ }
1049
+ exports.INET = INET;
1050
+ // CIDR - PostgreSQL network address type
1051
+ class CIDR extends AbstractDataType {
1052
+ constructor() {
1053
+ super(...arguments);
1054
+ this.key = 'CIDR';
1055
+ }
1056
+ toSqlString(dialect) {
1057
+ switch (dialect) {
1058
+ case 'postgres':
1059
+ return 'CIDR';
1060
+ case 'mysql':
1061
+ case 'mariadb':
1062
+ // MySQL/MariaDB: No CIDR type, use VARCHAR
1063
+ return 'VARCHAR(45)';
1064
+ case 'sqlite':
1065
+ // SQLite: No CIDR type, use TEXT
1066
+ return 'TEXT';
1067
+ default:
1068
+ return 'VARCHAR(45)';
1069
+ }
1070
+ }
1071
+ }
1072
+ exports.CIDR = CIDR;
1073
+ // MACADDR - PostgreSQL MAC address type
1074
+ class MACADDR extends AbstractDataType {
1075
+ constructor() {
1076
+ super(...arguments);
1077
+ this.key = 'MACADDR';
1078
+ }
1079
+ toSqlString(dialect) {
1080
+ switch (dialect) {
1081
+ case 'postgres':
1082
+ return 'MACADDR';
1083
+ case 'mysql':
1084
+ case 'mariadb':
1085
+ // MySQL/MariaDB: No MACADDR type, use VARCHAR
1086
+ return 'VARCHAR(17)';
1087
+ case 'sqlite':
1088
+ // SQLite: No MACADDR type, use TEXT
1089
+ return 'TEXT';
1090
+ default:
1091
+ return 'VARCHAR(17)';
1092
+ }
1093
+ }
1094
+ }
1095
+ exports.MACADDR = MACADDR;
1096
+ // BINARY - fixed-length binary data
1097
+ class BINARY extends AbstractDataType {
1098
+ constructor(length = 1) {
1099
+ super();
1100
+ this.key = 'BINARY';
1101
+ this.length = length;
1102
+ }
1103
+ toSqlString(dialect) {
1104
+ // MySQL/MariaDB use BINARY
1105
+ if (dialect === 'mysql' || dialect === 'mariadb') {
1106
+ return `BINARY(${this.length})`;
1107
+ }
1108
+ // SQLite uses BLOB for binary data
1109
+ return `BLOB`;
1110
+ }
1111
+ }
1112
+ exports.BINARY = BINARY;
1113
+ // VARBINARY - variable-length binary data
1114
+ class VARBINARY extends AbstractDataType {
1115
+ constructor(length = 255) {
1116
+ super();
1117
+ this.key = 'VARBINARY';
1118
+ this.length = length;
1119
+ }
1120
+ toSqlString(dialect) {
1121
+ // MySQL/MariaDB use VARBINARY
1122
+ if (dialect === 'mysql' || dialect === 'mariadb') {
1123
+ return `VARBINARY(${this.length})`;
1124
+ }
1125
+ // SQLite uses BLOB for binary data
1126
+ return `BLOB`;
1127
+ }
1128
+ }
1129
+ exports.VARBINARY = VARBINARY;
1130
+ // BLOB types - binary data storage with dialect-specific handling
1131
+ class BLOB extends AbstractDataType {
1132
+ constructor(length) {
1133
+ super();
1134
+ this.key = 'BLOB';
1135
+ this.length = length;
1136
+ }
1137
+ /**
1138
+ * Get the BLOB type string based on length variant
1139
+ * MySQL/MariaDB format: TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB
1140
+ */
1141
+ getBlobType() {
1142
+ if (!this.length) {
1143
+ return 'BLOB';
1144
+ }
1145
+ // MySQL/MariaDB format: TINYBLOB, MEDIUMBLOB, LONGBLOB
1146
+ if (this.length === 'tiny')
1147
+ return 'TINYBLOB';
1148
+ if (this.length === 'medium')
1149
+ return 'MEDIUMBLOB';
1150
+ if (this.length === 'long')
1151
+ return 'LONGBLOB';
1152
+ return 'BLOB';
1153
+ }
1154
+ toSqlString(dialect) {
1155
+ switch (dialect) {
1156
+ case 'postgres':
1157
+ // PostgreSQL uses BYTEA for binary data
1158
+ return 'BYTEA';
1159
+ case 'mysql':
1160
+ case 'mariadb':
1161
+ // MySQL/MariaDB support TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB
1162
+ return this.getBlobType();
1163
+ case 'sqlite':
1164
+ // SQLite uses BLOB for all binary data
1165
+ return 'BLOB';
1166
+ case 'mssql':
1167
+ case 'sqlserver':
1168
+ // SQL Server uses VARBINARY(MAX) for binary data
1169
+ return 'VARBINARY(MAX)';
1170
+ default:
1171
+ // Default to standard BLOB
1172
+ return this.getBlobType();
1173
+ }
1174
+ }
1175
+ }
1176
+ exports.BLOB = BLOB;
1177
+ // Convenience classes for specific BLOB types
1178
+ class TINYBLOB extends AbstractDataType {
1179
+ constructor() {
1180
+ super(...arguments);
1181
+ this.key = 'TINYBLOB';
1182
+ }
1183
+ toSqlString(dialect) {
1184
+ switch (dialect) {
1185
+ case 'postgres':
1186
+ return 'BYTEA';
1187
+ case 'mysql':
1188
+ case 'mariadb':
1189
+ return 'TINYBLOB';
1190
+ case 'sqlite':
1191
+ case 'mssql':
1192
+ case 'sqlserver':
1193
+ return 'BLOB';
1194
+ default:
1195
+ return 'TINYBLOB';
1196
+ }
1197
+ }
1198
+ }
1199
+ exports.TINYBLOB = TINYBLOB;
1200
+ class MEDIUMBLOB extends AbstractDataType {
1201
+ constructor() {
1202
+ super(...arguments);
1203
+ this.key = 'MEDIUMBLOB';
1204
+ }
1205
+ toSqlString(dialect) {
1206
+ switch (dialect) {
1207
+ case 'postgres':
1208
+ return 'BYTEA';
1209
+ case 'mysql':
1210
+ case 'mariadb':
1211
+ return 'MEDIUMBLOB';
1212
+ case 'sqlite':
1213
+ case 'mssql':
1214
+ case 'sqlserver':
1215
+ return 'VARBINARY(MAX)';
1216
+ default:
1217
+ return 'MEDIUMBLOB';
1218
+ }
1219
+ }
1220
+ }
1221
+ exports.MEDIUMBLOB = MEDIUMBLOB;
1222
+ class LONGBLOB extends AbstractDataType {
1223
+ constructor() {
1224
+ super(...arguments);
1225
+ this.key = 'LONGBLOB';
1226
+ }
1227
+ toSqlString(dialect) {
1228
+ switch (dialect) {
1229
+ case 'postgres':
1230
+ return 'BYTEA';
1231
+ case 'mysql':
1232
+ case 'mariadb':
1233
+ return 'LONGBLOB';
1234
+ case 'sqlite':
1235
+ case 'mssql':
1236
+ case 'sqlserver':
1237
+ return 'VARBINARY(MAX)';
1238
+ default:
1239
+ return 'LONGBLOB';
1240
+ }
1241
+ }
1242
+ }
1243
+ exports.LONGBLOB = LONGBLOB;
1244
+ // ENUM
1245
+ class ENUM extends AbstractDataType {
1246
+ /**
1247
+ * Create an ENUM data type
1248
+ * @param values - Either an array of values or individual string values
1249
+ * @example
1250
+ * // Array of values
1251
+ * DataTypes.ENUM(['active', 'inactive', 'pending'])
1252
+ * // Individual values
1253
+ * DataTypes.ENUM('active', 'inactive', 'pending')
1254
+ */
1255
+ constructor(...values) {
1256
+ super();
1257
+ this.key = 'ENUM';
1258
+ // Handle both array and spread arguments
1259
+ if (values.length === 1 && Array.isArray(values[0])) {
1260
+ this.values = values[0];
1261
+ }
1262
+ else {
1263
+ this.values = values;
1264
+ }
1265
+ }
1266
+ /**
1267
+ * Set a name for the enum type (useful for PostgreSQL/MySQL)
1268
+ */
1269
+ setName(name) {
1270
+ this.name = name;
1271
+ return this;
1272
+ }
1273
+ toSqlString(dialect) {
1274
+ const valuesStr = this.values.map((v) => `'${v}'`).join(', ');
1275
+ switch (dialect) {
1276
+ case 'postgres':
1277
+ // PostgreSQL supports native ENUM type
1278
+ if (this.name) {
1279
+ return `VARCHAR(255)`; // Will be created as ENUM type separately
1280
+ }
1281
+ return `VARCHAR(255)`;
1282
+ case 'mysql':
1283
+ case 'mariadb':
1284
+ // MySQL/MariaDB support native ENUM type
1285
+ return `ENUM(${valuesStr})`;
1286
+ case 'sqlite':
1287
+ default:
1288
+ // SQLite uses TEXT with validation
1289
+ return 'TEXT';
1290
+ }
1291
+ }
1292
+ /**
1293
+ * Get the values for validation
1294
+ */
1295
+ getValues() {
1296
+ return [...this.values];
1297
+ }
1298
+ /**
1299
+ * Validate if a value is valid for this ENUM
1300
+ */
1301
+ validate(value) {
1302
+ return this.values.includes(value);
1303
+ }
1304
+ /**
1305
+ * Generate an ALTER TABLE statement to add/modify ENUM column
1306
+ * Note: MySQL uses MODIFY COLUMN, PostgreSQL needs type recreation
1307
+ */
1308
+ toAlterTableSql(dialect, tableName, columnName, _columnDefinition) {
1309
+ const valuesStr = this.values.map((v) => `'${v}'`).join(', ');
1310
+ switch (dialect) {
1311
+ case 'mysql':
1312
+ case 'mariadb':
1313
+ return `ALTER TABLE \`${tableName}\` MODIFY COLUMN \`${columnName}\` ENUM(${valuesStr})`;
1314
+ case 'postgres': {
1315
+ // PostgreSQL requires creating the type first, then altering the column
1316
+ const typeName = this.name || `${tableName}_${columnName}_type`;
1317
+ return `-- PostgreSQL requires manual type creation:
1318
+ DROP TYPE IF EXISTS ${typeName};
1319
+ CREATE TYPE ${typeName} AS ENUM (${valuesStr});
1320
+ ALTER TABLE ${tableName} ALTER COLUMN ${columnName} TYPE ${typeName};
1321
+ ALTER TABLE ${tableName} ALTER COLUMN ${columnName} SET DEFAULT '${this.values[0]}';`;
1322
+ }
1323
+ default:
1324
+ return `-- ENUM not supported for ${dialect}, using TEXT`;
1325
+ }
1326
+ }
1327
+ }
1328
+ exports.ENUM = ENUM;
1329
+ // ARRAY - PostgreSQL native arrays with fallback to JSON/TEXT for other dialects
1330
+ class ARRAY extends AbstractDataType {
1331
+ /**
1332
+ * Create an ARRAY data type
1333
+ * @param type - The data type of array elements
1334
+ * @example
1335
+ * // Array of strings
1336
+ * tags: DataTypes.ARRAY(DataTypes.STRING)
1337
+ * // Array of integers
1338
+ * numbers: DataTypes.ARRAY(DataTypes.INTEGER)
1339
+ * // Array of floats
1340
+ * prices: DataTypes.ARRAY(DataTypes.FLOAT)
1341
+ */
1342
+ constructor(type) {
1343
+ super();
1344
+ this.key = 'ARRAY';
1345
+ this.type = type;
1346
+ }
1347
+ /**
1348
+ * Get the SQL string representation based on the dialect
1349
+ * PostgreSQL: Uses native array syntax (e.g., TEXT[], INTEGER[])
1350
+ * Other dialects: Falls back to JSON or TEXT
1351
+ */
1352
+ toSqlString(dialect) {
1353
+ // Get the base type for the element, passing the dialect through so nested
1354
+ // types (e.g. STRING(50), DECIMAL(10,2)) resolve correctly per-dialect
1355
+ const elementType = this.type.toSqlString(dialect);
1356
+ switch (dialect) {
1357
+ case 'postgres':
1358
+ // PostgreSQL supports native arrays with element type + []
1359
+ return `${elementType}[]`;
1360
+ case 'mysql':
1361
+ case 'mariadb':
1362
+ // MySQL/MariaDB: Use JSON type for arrays
1363
+ return 'JSON';
1364
+ case 'sqlite':
1365
+ case 'mssql':
1366
+ case 'sqlserver':
1367
+ default:
1368
+ // SQLite and SQL Server: Store as TEXT (JSON serialized)
1369
+ return 'TEXT';
1370
+ }
1371
+ }
1372
+ /**
1373
+ * Get the element type
1374
+ */
1375
+ getElementType() {
1376
+ return this.type;
1377
+ }
1378
+ }
1379
+ exports.ARRAY = ARRAY;
1380
+ // LIST - DuckDB native variable-length list type, with fallback to JSON/TEXT
1381
+ // for dialects without a composite list type. Distinct from ARRAY: ARRAY is
1382
+ // modeled on PostgreSQL's fixed-element-type array (and mainly documents
1383
+ // PostgreSQL-native `[]` syntax with generic fallbacks), whereas LIST maps
1384
+ // onto DuckDB's `<type>[]` LIST columns specifically and is the type callers
1385
+ // should reach for when targeting DuckDB's composite type system.
1386
+ class LIST extends AbstractDataType {
1387
+ /**
1388
+ * Create a LIST data type
1389
+ * @param type - The data type of list elements
1390
+ * @example
1391
+ * // List of integers (DuckDB: INTEGER[])
1392
+ * tags: DataTypes.LIST(DataTypes.INTEGER)
1393
+ * // Nested list (DuckDB: VARCHAR[][])
1394
+ * matrix: DataTypes.LIST(DataTypes.LIST(DataTypes.VARCHAR))
1395
+ */
1396
+ constructor(type) {
1397
+ super();
1398
+ this.key = 'LIST';
1399
+ this.type = type;
1400
+ }
1401
+ /**
1402
+ * Get the SQL string representation based on the dialect
1403
+ * DuckDB/PostgreSQL: native `elementType[]` syntax
1404
+ * Other dialects: falls back to JSON or TEXT
1405
+ */
1406
+ toSqlString(dialect) {
1407
+ const elementType = this.type.toSqlString(dialect);
1408
+ switch (dialect) {
1409
+ case 'duckdb':
1410
+ case 'postgres':
1411
+ return `${elementType}[]`;
1412
+ case 'mysql':
1413
+ case 'mariadb':
1414
+ return 'JSON';
1415
+ case 'sqlite':
1416
+ case 'mssql':
1417
+ case 'sqlserver':
1418
+ default:
1419
+ return 'TEXT';
1420
+ }
1421
+ }
1422
+ /**
1423
+ * Get the element type
1424
+ */
1425
+ getElementType() {
1426
+ return this.type;
1427
+ }
1428
+ }
1429
+ exports.LIST = LIST;
1430
+ // STRUCT - DuckDB native nested record type (named fields with heterogeneous
1431
+ // types), with fallback to JSON/TEXT for dialects without a composite struct type.
1432
+ class STRUCT extends AbstractDataType {
1433
+ /**
1434
+ * Create a STRUCT data type
1435
+ * @param fields - A map of field name -> field data type
1436
+ * @example
1437
+ * // DuckDB: STRUCT(x INTEGER, y INTEGER)
1438
+ * point: DataTypes.STRUCT({ x: DataTypes.INTEGER, y: DataTypes.INTEGER })
1439
+ */
1440
+ constructor(fields) {
1441
+ super();
1442
+ this.key = 'STRUCT';
1443
+ this.fields = fields;
1444
+ }
1445
+ /**
1446
+ * Get the SQL string representation based on the dialect
1447
+ * DuckDB: native `STRUCT(field TYPE, ...)` syntax
1448
+ * Other dialects: falls back to JSON or TEXT
1449
+ */
1450
+ toSqlString(dialect) {
1451
+ switch (dialect) {
1452
+ case 'duckdb': {
1453
+ const parts = Object.entries(this.fields).map(([name, type]) => `${name} ${type.toSqlString(dialect)}`);
1454
+ return `STRUCT(${parts.join(', ')})`;
1455
+ }
1456
+ case 'mysql':
1457
+ case 'mariadb':
1458
+ return 'JSON';
1459
+ case 'postgres':
1460
+ case 'sqlite':
1461
+ case 'mssql':
1462
+ case 'sqlserver':
1463
+ default:
1464
+ return 'TEXT';
1465
+ }
1466
+ }
1467
+ /**
1468
+ * Get the struct's fields
1469
+ */
1470
+ getFields() {
1471
+ return this.fields;
1472
+ }
1473
+ }
1474
+ exports.STRUCT = STRUCT;
1475
+ // MAP - DuckDB native key/value map type (homogeneous key type, homogeneous
1476
+ // value type, unlike STRUCT), with fallback to JSON/TEXT for other dialects.
1477
+ class MAP extends AbstractDataType {
1478
+ /**
1479
+ * Create a MAP data type
1480
+ * @param keyType - The data type of map keys
1481
+ * @param valueType - The data type of map values
1482
+ * @example
1483
+ * // DuckDB: MAP(VARCHAR, INTEGER)
1484
+ * scores: DataTypes.MAP(DataTypes.STRING, DataTypes.INTEGER)
1485
+ */
1486
+ constructor(keyType, valueType) {
1487
+ super();
1488
+ this.key = 'MAP';
1489
+ this.keyType = keyType;
1490
+ this.valueType = valueType;
1491
+ }
1492
+ /**
1493
+ * Get the SQL string representation based on the dialect
1494
+ * DuckDB: native `MAP(keyType, valueType)` syntax
1495
+ * Other dialects: falls back to JSON or TEXT
1496
+ */
1497
+ toSqlString(dialect) {
1498
+ switch (dialect) {
1499
+ case 'duckdb':
1500
+ return `MAP(${this.keyType.toSqlString(dialect)}, ${this.valueType.toSqlString(dialect)})`;
1501
+ case 'mysql':
1502
+ case 'mariadb':
1503
+ return 'JSON';
1504
+ case 'postgres':
1505
+ case 'sqlite':
1506
+ case 'mssql':
1507
+ case 'sqlserver':
1508
+ default:
1509
+ return 'TEXT';
1510
+ }
1511
+ }
1512
+ /**
1513
+ * Get the map's key type
1514
+ */
1515
+ getKeyType() {
1516
+ return this.keyType;
1517
+ }
1518
+ /**
1519
+ * Get the map's value type
1520
+ */
1521
+ getValueType() {
1522
+ return this.valueType;
1523
+ }
1524
+ }
1525
+ exports.MAP = MAP;
1526
+ // UNION - DuckDB native tagged-union type (exactly one of several named
1527
+ // alternative types is active at a time), with fallback to JSON/TEXT for
1528
+ // other dialects. Not to be confused with the SQL `UNION` query operator.
1529
+ class DUCKDB_UNION extends AbstractDataType {
1530
+ /**
1531
+ * Create a UNION data type
1532
+ * @param fields - A map of tag name -> alternative data type
1533
+ * @example
1534
+ * // DuckDB: UNION(num INTEGER, str VARCHAR)
1535
+ * value: DataTypes.UNION({ num: DataTypes.INTEGER, str: DataTypes.STRING })
1536
+ */
1537
+ constructor(fields) {
1538
+ super();
1539
+ this.key = 'UNION';
1540
+ this.fields = fields;
1541
+ }
1542
+ /**
1543
+ * Get the SQL string representation based on the dialect
1544
+ * DuckDB: native `UNION(tag TYPE, ...)` syntax
1545
+ * Other dialects: falls back to JSON or TEXT
1546
+ */
1547
+ toSqlString(dialect) {
1548
+ switch (dialect) {
1549
+ case 'duckdb': {
1550
+ const parts = Object.entries(this.fields).map(([tag, type]) => `${tag} ${type.toSqlString(dialect)}`);
1551
+ return `UNION(${parts.join(', ')})`;
1552
+ }
1553
+ case 'mysql':
1554
+ case 'mariadb':
1555
+ return 'JSON';
1556
+ case 'postgres':
1557
+ case 'sqlite':
1558
+ case 'mssql':
1559
+ case 'sqlserver':
1560
+ default:
1561
+ return 'TEXT';
1562
+ }
1563
+ }
1564
+ /**
1565
+ * Get the union's member fields
1566
+ */
1567
+ getFields() {
1568
+ return this.fields;
1569
+ }
1570
+ }
1571
+ exports.DUCKDB_UNION = DUCKDB_UNION;
1572
+ /**
1573
+ * Geometry - for spatial/geometric data
1574
+ * Supports optional geometry type and SRID (Spatial Reference System Identifier)
1575
+ *
1576
+ * @example
1577
+ * // Basic geometry (stored as JSON/text)
1578
+ * location: DataTypes.GEOMETRY
1579
+ *
1580
+ * // Geometry with specific type
1581
+ * point: DataTypes.GEOMETRY('POINT')
1582
+ * line: DataTypes.GEOMETRY('LINESTRING')
1583
+ * area: DataTypes.GEOMETRY('POLYGON')
1584
+ *
1585
+ * // Geometry with type and SRID (coordinate system)
1586
+ * geoPoint: DataTypes.GEOMETRY('POINT', 4326)
1587
+ */
1588
+ class GEOMETRY extends AbstractDataType {
1589
+ constructor(typeOrOptions, srid) {
1590
+ super();
1591
+ this.key = 'GEOMETRY';
1592
+ if (typeof typeOrOptions === 'object' && typeOrOptions !== null) {
1593
+ // Called with options object: GEOMETRY({ type: 'POINT', srid: 4326 })
1594
+ this.type = typeOrOptions.type;
1595
+ this.srid = typeOrOptions.srid;
1596
+ }
1597
+ else {
1598
+ // Called with positional args: GEOMETRY('POINT', 4326)
1599
+ this.type = typeOrOptions;
1600
+ this.srid = srid;
1601
+ }
1602
+ }
1603
+ /**
1604
+ * Get the geometry type in uppercase
1605
+ */
1606
+ getGeometryType() {
1607
+ return this.type?.toUpperCase();
1608
+ }
1609
+ toSqlString(dialect) {
1610
+ const typeStr = this.type ? this.type.toUpperCase() : '';
1611
+ const sridStr = this.srid ? `, ${this.srid}` : '';
1612
+ switch (dialect) {
1613
+ case 'postgres':
1614
+ // PostgreSQL with PostGIS extension
1615
+ if (typeStr && sridStr) {
1616
+ return `GEOMETRY(${typeStr}${sridStr})`;
1617
+ }
1618
+ else if (typeStr) {
1619
+ return `GEOMETRY(${typeStr})`;
1620
+ }
1621
+ return 'GEOMETRY';
1622
+ case 'mysql':
1623
+ case 'mariadb':
1624
+ // MySQL/MariaDB spatial types
1625
+ if (typeStr && sridStr) {
1626
+ return `${typeStr}${sridStr}`;
1627
+ }
1628
+ else if (typeStr) {
1629
+ return typeStr;
1630
+ }
1631
+ return 'GEOMETRY';
1632
+ case 'mssql':
1633
+ case 'sqlserver':
1634
+ // SQL Server uses geography/geometry types
1635
+ if (typeStr) {
1636
+ return `geometry`;
1637
+ }
1638
+ return 'geometry';
1639
+ case 'sqlite':
1640
+ default:
1641
+ // SQLite stores spatial data as BLOB (GeoJSON or WKB)
1642
+ return 'BLOB';
1643
+ }
1644
+ }
1645
+ }
1646
+ exports.GEOMETRY = GEOMETRY;
1647
+ /**
1648
+ * Geography - for geographic/spatial data (uses WGS84 coordinate system)
1649
+ * Unlike GEOMETRY, GEOGRAPHY performs calculations using spherical geography
1650
+ *
1651
+ * @example
1652
+ * // Basic geography (defaults to WGS84 - SRID 4326)
1653
+ * location: DataTypes.GEOGRAPHY
1654
+ *
1655
+ * // Geography with specific type
1656
+ * point: DataTypes.GEOGRAPHY('POINT')
1657
+ * area: DataTypes.GEOGRAPHY('POLYGON', 4326)
1658
+ *
1659
+ * // Geography with type and custom SRID
1660
+ * // 4326 = WGS 84 (most common)
1661
+ * // 3857 = Web Mercator
1662
+ * region: DataTypes.GEOGRAPHY('MULTIPOLYGON', 4326)
1663
+ */
1664
+ class GEOGRAPHY extends AbstractDataType {
1665
+ constructor(typeOrOptions, srid) {
1666
+ super();
1667
+ this.key = 'GEOGRAPHY';
1668
+ if (typeof typeOrOptions === 'object' && typeOrOptions !== null) {
1669
+ // Called with options object: GEOGRAPHY({ type: 'POLYGON', srid: 4326 })
1670
+ this.type = typeOrOptions.type;
1671
+ this.srid = typeOrOptions.srid;
1672
+ }
1673
+ else {
1674
+ // Called with positional args: GEOGRAPHY('POLYGON', 4326)
1675
+ this.type = typeOrOptions;
1676
+ this.srid = srid;
1677
+ }
1678
+ // Default to WGS84 (SRID 4326) if not specified
1679
+ if (this.srid === undefined) {
1680
+ this.srid = 4326;
1681
+ }
1682
+ }
1683
+ /**
1684
+ * Get the geography type in uppercase
1685
+ */
1686
+ getGeographyType() {
1687
+ return this.type?.toUpperCase();
1688
+ }
1689
+ /**
1690
+ * Get the SRID (defaults to 4326 for WGS84)
1691
+ */
1692
+ getSRID() {
1693
+ return this.srid || 4326;
1694
+ }
1695
+ toSqlString(dialect) {
1696
+ const typeStr = this.type ? this.type.toUpperCase() : '';
1697
+ const sridStr = this.srid ? `, ${this.srid}` : '';
1698
+ switch (dialect) {
1699
+ case 'postgres':
1700
+ // PostgreSQL with PostGIS - GEOGRAPHY is preferred for geographic data
1701
+ if (typeStr && sridStr) {
1702
+ return `GEOGRAPHY(${typeStr}${sridStr})`;
1703
+ }
1704
+ else if (typeStr) {
1705
+ return `GEOGRAPHY(${typeStr})`;
1706
+ }
1707
+ // Default geography defaults to GEOGRAPHY(GEOMETRY, 4326)
1708
+ return 'GEOGRAPHY';
1709
+ case 'mysql':
1710
+ case 'mariadb':
1711
+ // MySQL 8.0+ supports GEOGRAPHY type
1712
+ if (typeStr) {
1713
+ return typeStr;
1714
+ }
1715
+ return 'GEOMETRY'; // MySQL treats geography as geometry
1716
+ case 'mssql':
1717
+ case 'sqlserver':
1718
+ // SQL Server geography type (uses WGS84 by default)
1719
+ if (typeStr) {
1720
+ return `geography`;
1721
+ }
1722
+ return 'geography';
1723
+ case 'sqlite':
1724
+ default:
1725
+ // SQLite stores spatial data as BLOB
1726
+ return 'BLOB';
1727
+ }
1728
+ }
1729
+ }
1730
+ exports.GEOGRAPHY = GEOGRAPHY;
1731
+ /**
1732
+ * POINT - specific geometry type for points
1733
+ * Shorthand for GEOMETRY('POINT', srid)
1734
+ *
1735
+ * @example
1736
+ * // Point with default SRID (4326)
1737
+ * location: DataTypes.POINT()
1738
+ *
1739
+ * // Point with custom SRID
1740
+ * location: DataTypes.POINT(4326)
1741
+ */
1742
+ class POINT extends AbstractDataType {
1743
+ constructor(srid) {
1744
+ super();
1745
+ this.key = 'POINT';
1746
+ this.srid = srid;
1747
+ }
1748
+ toSqlString(dialect) {
1749
+ switch (dialect) {
1750
+ case 'postgres':
1751
+ if (this.srid) {
1752
+ return `GEOMETRY(POINT, ${this.srid})`;
1753
+ }
1754
+ return 'GEOMETRY(POINT)';
1755
+ case 'mysql':
1756
+ case 'mariadb':
1757
+ return 'POINT';
1758
+ case 'mssql':
1759
+ case 'sqlserver':
1760
+ return 'geometry';
1761
+ case 'sqlite':
1762
+ default:
1763
+ return 'BLOB';
1764
+ }
1765
+ }
1766
+ }
1767
+ exports.POINT = POINT;
1768
+ /**
1769
+ * LINESTRING - specific geometry type for lines
1770
+ * Shorthand for GEOMETRY('LINESTRING', srid)
1771
+ *
1772
+ * @example
1773
+ * // LineString with default SRID (4326)
1774
+ * route: DataTypes.LINESTRING()
1775
+ *
1776
+ * // LineString with custom SRID
1777
+ * route: DataTypes.LINESTRING(4326)
1778
+ */
1779
+ class LINESTRING extends AbstractDataType {
1780
+ constructor(srid) {
1781
+ super();
1782
+ this.key = 'LINESTRING';
1783
+ this.srid = srid;
1784
+ }
1785
+ toSqlString(dialect) {
1786
+ switch (dialect) {
1787
+ case 'postgres':
1788
+ if (this.srid) {
1789
+ return `GEOMETRY(LINESTRING, ${this.srid})`;
1790
+ }
1791
+ return 'GEOMETRY(LINESTRING)';
1792
+ case 'mysql':
1793
+ case 'mariadb':
1794
+ return 'LINESTRING';
1795
+ case 'mssql':
1796
+ case 'sqlserver':
1797
+ return 'geometry';
1798
+ case 'sqlite':
1799
+ default:
1800
+ return 'BLOB';
1801
+ }
1802
+ }
1803
+ }
1804
+ exports.LINESTRING = LINESTRING;
1805
+ /**
1806
+ * POLYGON - specific geometry type for polygons
1807
+ * Shorthand for GEOMETRY('POLYGON', srid)
1808
+ *
1809
+ * @example
1810
+ * // Polygon with default SRID (4326)
1811
+ * boundary: DataTypes.POLYGON()
1812
+ *
1813
+ * // Polygon with custom SRID
1814
+ * boundary: DataTypes.POLYGON(4326)
1815
+ */
1816
+ class POLYGON extends AbstractDataType {
1817
+ constructor(srid) {
1818
+ super();
1819
+ this.key = 'POLYGON';
1820
+ this.srid = srid;
1821
+ }
1822
+ toSqlString(dialect) {
1823
+ switch (dialect) {
1824
+ case 'postgres':
1825
+ if (this.srid) {
1826
+ return `GEOMETRY(POLYGON, ${this.srid})`;
1827
+ }
1828
+ return 'GEOMETRY(POLYGON)';
1829
+ case 'mysql':
1830
+ case 'mariadb':
1831
+ return 'POLYGON';
1832
+ case 'mssql':
1833
+ case 'sqlserver':
1834
+ return 'geometry';
1835
+ case 'sqlite':
1836
+ default:
1837
+ return 'BLOB';
1838
+ }
1839
+ }
1840
+ }
1841
+ exports.POLYGON = POLYGON;
1842
+ // MULTIPOINT - MySQL spatial type for collections of points
1843
+ class MULTIPOINT extends AbstractDataType {
1844
+ constructor(srid) {
1845
+ super();
1846
+ this.key = 'MULTIPOINT';
1847
+ this.srid = srid;
1848
+ }
1849
+ toSqlString(dialect) {
1850
+ switch (dialect) {
1851
+ case 'postgres':
1852
+ if (this.srid) {
1853
+ return `GEOMETRY(MULTIPOINT, ${this.srid})`;
1854
+ }
1855
+ return 'GEOMETRY(MULTIPOINT)';
1856
+ case 'mysql':
1857
+ case 'mariadb':
1858
+ return 'MULTIPOINT';
1859
+ case 'mssql':
1860
+ case 'sqlserver':
1861
+ return 'geometry';
1862
+ case 'sqlite':
1863
+ default:
1864
+ return 'BLOB';
1865
+ }
1866
+ }
1867
+ }
1868
+ exports.MULTIPOINT = MULTIPOINT;
1869
+ // MULTILINESTRING - MySQL spatial type for collections of lines
1870
+ class MULTILINESTRING extends AbstractDataType {
1871
+ constructor(srid) {
1872
+ super();
1873
+ this.key = 'MULTILINESTRING';
1874
+ this.srid = srid;
1875
+ }
1876
+ toSqlString(dialect) {
1877
+ switch (dialect) {
1878
+ case 'postgres':
1879
+ if (this.srid) {
1880
+ return `GEOMETRY(MULTILINESTRING, ${this.srid})`;
1881
+ }
1882
+ return 'GEOMETRY(MULTILINESTRING)';
1883
+ case 'mysql':
1884
+ case 'mariadb':
1885
+ return 'MULTILINESTRING';
1886
+ case 'mssql':
1887
+ case 'sqlserver':
1888
+ return 'geometry';
1889
+ case 'sqlite':
1890
+ default:
1891
+ return 'BLOB';
1892
+ }
1893
+ }
1894
+ }
1895
+ exports.MULTILINESTRING = MULTILINESTRING;
1896
+ // MULTIPOLYGON - MySQL spatial type for collections of polygons
1897
+ class MULTIPOLYGON extends AbstractDataType {
1898
+ constructor(srid) {
1899
+ super();
1900
+ this.key = 'MULTIPOLYGON';
1901
+ this.srid = srid;
1902
+ }
1903
+ toSqlString(dialect) {
1904
+ switch (dialect) {
1905
+ case 'postgres':
1906
+ if (this.srid) {
1907
+ return `GEOMETRY(MULTIPOLYGON, ${this.srid})`;
1908
+ }
1909
+ return 'GEOMETRY(MULTIPOLYGON)';
1910
+ case 'mysql':
1911
+ case 'mariadb':
1912
+ return 'MULTIPOLYGON';
1913
+ case 'mssql':
1914
+ case 'sqlserver':
1915
+ return 'geometry';
1916
+ case 'sqlite':
1917
+ default:
1918
+ return 'BLOB';
1919
+ }
1920
+ }
1921
+ }
1922
+ exports.MULTIPOLYGON = MULTIPOLYGON;
1923
+ // GEOMETRYCOLLECTION - MySQL spatial type for heterogeneous geometry collections
1924
+ class GEOMETRYCOLLECTION extends AbstractDataType {
1925
+ constructor(srid) {
1926
+ super();
1927
+ this.key = 'GEOMETRYCOLLECTION';
1928
+ this.srid = srid;
1929
+ }
1930
+ toSqlString(dialect) {
1931
+ switch (dialect) {
1932
+ case 'postgres':
1933
+ if (this.srid) {
1934
+ return `GEOMETRY(GEOMETRYCOLLECTION, ${this.srid})`;
1935
+ }
1936
+ return 'GEOMETRY(GEOMETRYCOLLECTION)';
1937
+ case 'mysql':
1938
+ case 'mariadb':
1939
+ return 'GEOMETRYCOLLECTION';
1940
+ case 'mssql':
1941
+ case 'sqlserver':
1942
+ return 'geometry';
1943
+ case 'sqlite':
1944
+ default:
1945
+ return 'BLOB';
1946
+ }
1947
+ }
1948
+ }
1949
+ exports.GEOMETRYCOLLECTION = GEOMETRYCOLLECTION;
1950
+ // SET - MySQL SET column type for storing multiple values from a set
1951
+ class SET extends AbstractDataType {
1952
+ /**
1953
+ * Create a SET data type
1954
+ * @param values - Either an array of values or individual string values
1955
+ * @example
1956
+ * // Array of values
1957
+ * DataTypes.SET(['red', 'green', 'blue'])
1958
+ * // Individual values
1959
+ * DataTypes.SET('red', 'green', 'blue')
1960
+ */
1961
+ constructor(...values) {
1962
+ super();
1963
+ this.key = 'SET';
1964
+ // Handle both array and spread arguments
1965
+ if (values.length === 1 && Array.isArray(values[0])) {
1966
+ this.values = values[0];
1967
+ }
1968
+ else {
1969
+ this.values = values;
1970
+ }
1971
+ }
1972
+ toSqlString(dialect) {
1973
+ const valuesStr = this.values.map((v) => `'${v}'`).join(', ');
1974
+ switch (dialect) {
1975
+ case 'mysql':
1976
+ case 'mariadb':
1977
+ // MySQL/MariaDB support native SET type
1978
+ return `SET(${valuesStr})`;
1979
+ case 'postgres':
1980
+ case 'sqlite':
1981
+ default:
1982
+ // Other dialects use TEXT with validation
1983
+ return 'TEXT';
1984
+ }
1985
+ }
1986
+ /**
1987
+ * Get the values for validation
1988
+ */
1989
+ getValues() {
1990
+ return [...this.values];
1991
+ }
1992
+ /**
1993
+ * Validate if a value is valid for this SET
1994
+ */
1995
+ validate(value) {
1996
+ return this.values.includes(value);
1997
+ }
1998
+ }
1999
+ exports.SET = SET;
2000
+ // JSONColumn - MySQL native JSON column type
2001
+ class JSONColumn extends AbstractDataType {
2002
+ /**
2003
+ * Create a JSON column type
2004
+ * @param options - Options for JSON column
2005
+ * @example
2006
+ * // Basic JSON column
2007
+ * DataTypes.JSONCOLUMN()
2008
+ * // JSON column with validation
2009
+ * DataTypes.JSONCOLUMN({ validate: true })
2010
+ */
2011
+ constructor(options) {
2012
+ super();
2013
+ this.key = 'JSONCOLUMN';
2014
+ if (options) {
2015
+ this.validate = options.validate;
2016
+ this.unescapedUnicode = options.unescapedUnicode;
2017
+ this.compact = options.compact;
2018
+ }
2019
+ }
2020
+ toSqlString(dialect) {
2021
+ switch (dialect) {
2022
+ case 'mysql':
2023
+ case 'mariadb':
2024
+ // MySQL/MariaDB native JSON type
2025
+ return 'JSON';
2026
+ case 'postgres':
2027
+ // PostgreSQL uses JSONB for better performance
2028
+ return 'JSONB';
2029
+ case 'sqlite':
2030
+ return 'TEXT';
2031
+ case 'mssql':
2032
+ case 'sqlserver':
2033
+ // SQL Server uses NVARCHAR(MAX) for JSON
2034
+ return 'NVARCHAR(MAX)';
2035
+ default:
2036
+ return 'TEXT';
2037
+ }
2038
+ }
2039
+ }
2040
+ exports.JSONColumn = JSONColumn;
2041
+ class VIRTUAL extends AbstractDataType {
2042
+ constructor(options) {
2043
+ super();
2044
+ this.key = 'VIRTUAL';
2045
+ if (options) {
2046
+ this.returnType = options.returnType;
2047
+ this.get = options.get;
2048
+ this.set = options.set;
2049
+ this.dependencies = options.dependencies;
2050
+ }
2051
+ }
2052
+ toSqlString() {
2053
+ // Virtual fields don't create a database column
2054
+ return '';
2055
+ }
2056
+ /**
2057
+ * Check if this virtual field has a getter
2058
+ */
2059
+ hasGetter() {
2060
+ return typeof this.get === 'function';
2061
+ }
2062
+ /**
2063
+ * Check if this virtual field has a setter
2064
+ */
2065
+ hasSetter() {
2066
+ return typeof this.set === 'function';
2067
+ }
2068
+ /**
2069
+ * Get the dependencies for this virtual field
2070
+ */
2071
+ getDependencies() {
2072
+ return this.dependencies || [];
2073
+ }
2074
+ }
2075
+ exports.VIRTUAL = VIRTUAL;
2076
+ /**
2077
+ * VIRTUALSTRING - virtual string field with getter/setter support
2078
+ * Does not create a database column but provides computed string values
2079
+ *
2080
+ * @example
2081
+ * // Virtual string with getter (computed from other fields)
2082
+ * fullName: DataTypes.VIRTUALSTRING({
2083
+ * get() {
2084
+ * return `${this.firstName} ${this.lastName}`;
2085
+ * },
2086
+ * dependencies: ['firstName', 'lastName']
2087
+ * })
2088
+ *
2089
+ * // Virtual string with getter and setter
2090
+ * email: DataTypes.VIRTUALSTRING({
2091
+ * get() {
2092
+ * return this._email?.toLowerCase();
2093
+ * },
2094
+ * set(value: string) {
2095
+ * this._email = value.trim().toLowerCase();
2096
+ * },
2097
+ * length: 255
2098
+ * })
2099
+ */
2100
+ class VIRTUALSTRING extends AbstractDataType {
2101
+ constructor(options) {
2102
+ super();
2103
+ this.key = 'VIRTUALSTRING';
2104
+ if (options) {
2105
+ this.get = options.get;
2106
+ this.set = options.set;
2107
+ this.length = options.length;
2108
+ this.dependencies = options.dependencies;
2109
+ }
2110
+ }
2111
+ toSqlString() {
2112
+ // Virtual fields don't create a database column
2113
+ return '';
2114
+ }
2115
+ /**
2116
+ * Check if this virtual string field has a getter
2117
+ */
2118
+ hasGetter() {
2119
+ return typeof this.get === 'function';
2120
+ }
2121
+ /**
2122
+ * Check if this virtual string field has a setter
2123
+ */
2124
+ hasSetter() {
2125
+ return typeof this.set === 'function';
2126
+ }
2127
+ /**
2128
+ * Get the dependencies for this virtual field
2129
+ */
2130
+ getDependencies() {
2131
+ return this.dependencies || [];
2132
+ }
2133
+ /**
2134
+ * Get the maximum length for validation
2135
+ */
2136
+ getLength() {
2137
+ return this.length;
2138
+ }
2139
+ }
2140
+ exports.VIRTUALSTRING = VIRTUALSTRING;
2141
+ /**
2142
+ * ALGORITHM - data type for hash algorithms
2143
+ * Used for storing hashed values (passwords, checksums, etc.)
2144
+ * Can be used with VIRTUAL type for computed/hashed fields
2145
+ *
2146
+ * Common output lengths:
2147
+ * - MD5: 32 hex chars (16 bytes)
2148
+ * - SHA1: 40 hex chars (20 bytes)
2149
+ * - SHA256: 64 hex chars (32 bytes)
2150
+ * - SHA384: 96 hex chars (48 bytes)
2151
+ * - SHA512: 128 hex chars (64 bytes)
2152
+ * - BCRYPT: 60 chars (with $2a$ or $2b$ prefix)
2153
+ * - ARGON2: Variable, typically ~100 chars (with $argon2$ prefix)
2154
+ * - PBKDF2: Variable based on hash length
2155
+ *
2156
+ * @example
2157
+ * // Store password hash using BCRYPT (recommended for passwords)
2158
+ * password: DataTypes.ALGORITHM({ algorithm: 'BCRYPT', cost: 12 })
2159
+ *
2160
+ * // Store checksum using SHA256
2161
+ * fileChecksum: DataTypes.ALGORITHM({ algorithm: 'SHA256' })
2162
+ *
2163
+ * // Store password hash using ARGON2
2164
+ * password: DataTypes.ALGORITHM({ algorithm: 'ARGON2', cost: 65536, parallelism: 2 })
2165
+ *
2166
+ * // Use with VIRTUAL for auto-hashing on set
2167
+ * passwordHash: DataTypes.VIRTUAL({
2168
+ * returnType: DataTypes.ALGORITHM({ algorithm: 'BCRYPT' }),
2169
+ * set(value: string) {
2170
+ * this.password = hashPassword(value);
2171
+ * }
2172
+ * })
2173
+ */
2174
+ class ALGORITHM extends AbstractDataType {
2175
+ /**
2176
+ * Get the default cost/rounds for each algorithm
2177
+ */
2178
+ getDefaultCost() {
2179
+ switch (this.algorithm) {
2180
+ case 'BCRYPT':
2181
+ return 10;
2182
+ case 'ARGON2':
2183
+ return 65536; // memory cost in KB
2184
+ case 'PBKDF2':
2185
+ return 100000;
2186
+ case 'SCRYPT':
2187
+ return 16384;
2188
+ default:
2189
+ return 0;
2190
+ }
2191
+ }
2192
+ /**
2193
+ * Get the output length for each algorithm (in characters for VARCHAR)
2194
+ * This accounts for the full hash including prefixes, salts, etc.
2195
+ */
2196
+ getOutputLength() {
2197
+ switch (this.algorithm) {
2198
+ case 'MD5':
2199
+ return 32; // 32 hex characters
2200
+ case 'SHA1':
2201
+ return 40; // 40 hex characters
2202
+ case 'SHA256':
2203
+ return 64; // 64 hex characters
2204
+ case 'SHA384':
2205
+ return 96; // 96 hex characters
2206
+ case 'SHA512':
2207
+ return 128; // 128 hex characters
2208
+ case 'SHA512_256':
2209
+ return 64; // 64 hex characters
2210
+ case 'BCRYPT':
2211
+ return 60; // $2a$10$ + 53 characters
2212
+ case 'ARGON2':
2213
+ return 128; // $argon2id$v=19$m=65536,t=3,p=2$ + salt + hash
2214
+ case 'PBKDF2':
2215
+ return this.hashLength ? this.hashLength * 2 : 128; // Hex encoded
2216
+ case 'SCRYPT':
2217
+ return 128; // Variable length
2218
+ case 'NTLM':
2219
+ return 32; // 32 hex characters
2220
+ case 'MYSQL':
2221
+ return 40; // 40 hex characters
2222
+ case 'POSTGRESQL_MD5':
2223
+ return 35; // md5( + 32 hex + )
2224
+ default:
2225
+ return 64;
2226
+ }
2227
+ }
2228
+ constructor(options) {
2229
+ super();
2230
+ this.key = 'ALGORITHM';
2231
+ this.algorithm = options.algorithm;
2232
+ this.cost = options.cost ?? (options.algorithm ? this.getDefaultCost() : undefined);
2233
+ this.saltLength = options.saltLength;
2234
+ this.hashLength = options.hashLength;
2235
+ this.includeSalt = options.includeSalt ?? true;
2236
+ this.parallelism = options.parallelism ?? 1;
2237
+ this.blockSize = options.blockSize ?? 8;
2238
+ }
2239
+ /**
2240
+ * Get the algorithm name
2241
+ */
2242
+ getAlgorithm() {
2243
+ return this.algorithm;
2244
+ }
2245
+ /**
2246
+ * Check if this is a password hashing algorithm (slow hash)
2247
+ * Password hashing algorithms are designed to be slow to prevent brute force
2248
+ */
2249
+ isPasswordHash() {
2250
+ return ['BCRYPT', 'ARGON2', 'PBKDF2', 'SCRYPT'].includes(this.algorithm);
2251
+ }
2252
+ /**
2253
+ * Check if this is a fast hash algorithm (checksums)
2254
+ */
2255
+ isFastHash() {
2256
+ return ['MD5', 'SHA1', 'SHA256', 'SHA384', 'SHA512', 'SHA512_256', 'NTLM'].includes(this.algorithm);
2257
+ }
2258
+ /**
2259
+ * Get the configuration object for hashing libraries
2260
+ */
2261
+ getHashConfig() {
2262
+ const config = {
2263
+ algorithm: this.algorithm,
2264
+ };
2265
+ if (this.cost) {
2266
+ if (this.algorithm === 'BCRYPT') {
2267
+ config.rounds = this.cost;
2268
+ }
2269
+ else if (this.algorithm === 'ARGON2') {
2270
+ config.memoryCost = this.cost;
2271
+ }
2272
+ else if (this.algorithm === 'PBKDF2') {
2273
+ config.iterations = this.cost;
2274
+ }
2275
+ else if (this.algorithm === 'SCRYPT') {
2276
+ config.cost = this.cost;
2277
+ }
2278
+ }
2279
+ if (this.saltLength) {
2280
+ config.saltLength = this.saltLength;
2281
+ }
2282
+ if (this.hashLength) {
2283
+ config.hashLength = this.hashLength;
2284
+ }
2285
+ if (this.parallelism && this.algorithm === 'ARGON2') {
2286
+ config.parallelism = this.parallelism;
2287
+ }
2288
+ if (this.blockSize && this.algorithm === 'ARGON2') {
2289
+ config.blockSize = this.blockSize;
2290
+ }
2291
+ return config;
2292
+ }
2293
+ toSqlString(dialect) {
2294
+ const length = this.getOutputLength();
2295
+ // For most databases, use VARCHAR with appropriate length
2296
+ // Some databases support native password hash types
2297
+ switch (dialect) {
2298
+ case 'postgres':
2299
+ // PostgreSQL doesn't have specific hash types, use VARCHAR
2300
+ return `VARCHAR(${length})`;
2301
+ case 'mysql':
2302
+ case 'mariadb':
2303
+ // MySQL/MariaDB - use VARCHAR for password hashes
2304
+ return `VARCHAR(${length})`;
2305
+ case 'sqlite':
2306
+ // SQLite uses TEXT for variable-length strings
2307
+ return `TEXT`;
2308
+ case 'mssql':
2309
+ case 'sqlserver':
2310
+ // SQL Server uses NVARCHAR
2311
+ return `NVARCHAR(${length})`;
2312
+ default:
2313
+ return `VARCHAR(${length})`;
2314
+ }
2315
+ }
2316
+ }
2317
+ exports.ALGORITHM = ALGORITHM;
2318
+ /**
2319
+ * VIRTUAL with ALGORITHM - computed hash field
2320
+ * Useful for automatic password hashing when setting values
2321
+ *
2322
+ * @example
2323
+ * // Auto-hash password on set using BCRYPT
2324
+ * passwordHash: DataTypes.VIRTUAL({
2325
+ * returnType: DataTypes.ALGORITHM({ algorithm: 'BCRYPT', cost: 12 }),
2326
+ * set(value: string) {
2327
+ * this._passwordHash = bcrypt.hashSync(value, 12);
2328
+ * },
2329
+ * get() {
2330
+ * return this._passwordHash;
2331
+ * }
2332
+ * })
2333
+ *
2334
+ * // Verify password (comparison virtual field)
2335
+ * password: DataTypes.STRING(255),
2336
+ * passwordConfirm: DataTypes.VIRTUAL({
2337
+ * returnType: DataTypes.BOOLEAN(),
2338
+ * set(value: string) {
2339
+ * // This will be handled by the model validation
2340
+ * }
2341
+ * })
2342
+ */
2343
+ // Helper to add static toSql, equals, and serialize methods to factory functions while preserving call signature
2344
+ function createDataTypeFactory(factory, key) {
2345
+ const factoryFn = factory;
2346
+ // Attach the key to the factory function for comparison
2347
+ factoryFn.key = key;
2348
+ factoryFn.toSql = function () { return factory().toSql(); };
2349
+ // Static equals method for comparing DataType factories
2350
+ factoryFn.equals = function (other) {
2351
+ if (!other) {
2352
+ return false;
2353
+ }
2354
+ // If it's a factory function with a key property, compare by key
2355
+ if (typeof other === 'function' && other.key) {
2356
+ return other.key === key;
2357
+ }
2358
+ // If it's an object with key property (like a DataType instance)
2359
+ if (typeof other === 'object' && other.key) {
2360
+ return other.key === key;
2361
+ }
2362
+ // If it's a string, compare directly
2363
+ if (typeof other === 'string') {
2364
+ return other === key;
2365
+ }
2366
+ return false;
2367
+ };
2368
+ // Static serialize method for serializing values
2369
+ factoryFn.serialize = function (value) {
2370
+ return value;
2371
+ };
2372
+ return factoryFn;
2373
+ }
2374
+ // Export DataTypes object with all data types
2375
+ exports.DataTypes = {
2376
+ STRING: createDataTypeFactory((length, binary = false) => new STRING(length, binary), 'STRING'),
2377
+ VARCHAR: createDataTypeFactory((length = 255) => new VARCHAR(length), 'VARCHAR'),
2378
+ CHAR: createDataTypeFactory((length = 1) => new CHAR(length), 'CHAR'),
2379
+ TEXT: createDataTypeFactory((length) => new TEXT(length), 'TEXT'),
2380
+ TINYTEXT: createDataTypeFactory(() => new TINYTEXT(), 'TINYTEXT'),
2381
+ MEDIUMTEXT: createDataTypeFactory(() => new MEDIUMTEXT(), 'MEDIUMTEXT'),
2382
+ LONGTEXT: createDataTypeFactory(() => new LONGTEXT(), 'LONGTEXT'),
2383
+ INTEGER: createDataTypeFactory((options) => new INTEGER(options || {}), 'INTEGER'),
2384
+ TINYINT: createDataTypeFactory((options) => new TINYINT(options || {}), 'TINYINT'),
2385
+ SMALLINT: createDataTypeFactory((options) => new SMALLINT(options || {}), 'SMALLINT'),
2386
+ MEDIUMINT: createDataTypeFactory((options) => new MEDIUMINT(options || {}), 'MEDIUMINT'),
2387
+ BIGINT: createDataTypeFactory((options) => new BIGINT(options || {}), 'BIGINT'),
2388
+ FLOAT: createDataTypeFactory((precisionOrOptions) => new FLOAT(precisionOrOptions), 'FLOAT'),
2389
+ DOUBLE: createDataTypeFactory((precisionOrOptions) => new DOUBLE(precisionOrOptions), 'DOUBLE'),
2390
+ DECIMAL: createDataTypeFactory((precision = 10, scale = 0, unsigned = false) => new DECIMAL(precision, scale, unsigned), 'DECIMAL'),
2391
+ REAL: createDataTypeFactory((precisionOrOptions) => new REAL(precisionOrOptions), 'REAL'),
2392
+ BOOLEAN: createDataTypeFactory(() => new BOOLEAN(), 'BOOLEAN'),
2393
+ DATE: createDataTypeFactory((precision, timezone = false) => new DATE(precision, timezone), 'DATE'),
2394
+ DATEONLY: createDataTypeFactory(() => new DATEONLY(), 'DATEONLY'),
2395
+ DATETIME: createDataTypeFactory((precision) => new DATETIME(precision), 'DATETIME'),
2396
+ TIMESTAMP: createDataTypeFactory((precision) => new TIMESTAMP(precision), 'TIMESTAMP'),
2397
+ NOW: createDataTypeFactory(() => new NOW(), 'NOW'),
2398
+ TIME: createDataTypeFactory((precision, timezone = false) => new TIME(precision, timezone), 'TIME'),
2399
+ UUID: createDataTypeFactory(() => new UUID(), 'UUID'),
2400
+ UUIDV1: createDataTypeFactory(() => new UUIDV1(), 'UUIDV1'),
2401
+ UUIDV4: createDataTypeFactory(() => new UUIDV4(), 'UUIDV4'),
2402
+ JSON: createDataTypeFactory((useNative = false) => new JSON(useNative), 'JSON'),
2403
+ JSONB: createDataTypeFactory((useNative = false) => new JSONB(useNative), 'JSONB'),
2404
+ // PostgreSQL-specific types
2405
+ HSTORE: createDataTypeFactory((useNative = true) => new HSTORE(useNative), 'HSTORE'),
2406
+ RANGE: createDataTypeFactory((subtype) => new RANGE(subtype), 'RANGE'),
2407
+ INET: createDataTypeFactory((options) => new INET(options), 'INET'),
2408
+ // Convenience factory for an IPv6-specific INET column, e.g.
2409
+ // `DataTypes.INET6` instead of `DataTypes.INET({ version: 6 })`. Dialects
2410
+ // with a distinct IPv6 column type (e.g. ClickHouse's `IPv6`) key off
2411
+ // `INET.version`, which this sets to `6`; dialects that only have one
2412
+ // "INET" type (Postgres) render identically either way.
2413
+ INET6: createDataTypeFactory(() => new INET({ version: 6 }), 'INET'),
2414
+ CIDR: createDataTypeFactory(() => new CIDR(), 'CIDR'),
2415
+ MACADDR: createDataTypeFactory(() => new MACADDR(), 'MACADDR'),
2416
+ BLOB: createDataTypeFactory((length) => new BLOB(length), 'BLOB'),
2417
+ TINYBLOB: createDataTypeFactory(() => new TINYBLOB(), 'TINYBLOB'),
2418
+ MEDIUMBLOB: createDataTypeFactory(() => new MEDIUMBLOB(), 'MEDIUMBLOB'),
2419
+ LONGBLOB: createDataTypeFactory(() => new LONGBLOB(), 'LONGBLOB'),
2420
+ BINARY: createDataTypeFactory((length = 1) => new BINARY(length), 'BINARY'),
2421
+ VARBINARY: createDataTypeFactory((length = 255) => new VARBINARY(length), 'VARBINARY'),
2422
+ /**
2423
+ * ENUM data type
2424
+ * @param values - Either an array of values or individual string values
2425
+ * @example
2426
+ * // Array of values
2427
+ * status: { type: DataTypes.ENUM(['active', 'inactive', 'pending']) }
2428
+ * // Individual values
2429
+ * role: DataTypes.ENUM('admin', 'user', 'guest')
2430
+ */
2431
+ ENUM: createDataTypeFactory((...values) => new ENUM(...values), 'ENUM'),
2432
+ ARRAY: createDataTypeFactory((type) => new ARRAY(type), 'ARRAY'),
2433
+ /**
2434
+ * LIST data type - DuckDB native variable-length list (`elementType[]`)
2435
+ * @param type - The data type of list elements
2436
+ * @example
2437
+ * tags: DataTypes.LIST(DataTypes.INTEGER)
2438
+ */
2439
+ LIST: createDataTypeFactory((type) => new LIST(type), 'LIST'),
2440
+ /**
2441
+ * STRUCT data type - DuckDB native nested record (`STRUCT(field TYPE, ...)`)
2442
+ * @param fields - A map of field name -> field data type
2443
+ * @example
2444
+ * point: DataTypes.STRUCT({ x: DataTypes.INTEGER, y: DataTypes.INTEGER })
2445
+ */
2446
+ STRUCT: createDataTypeFactory((fields) => new STRUCT(fields), 'STRUCT'),
2447
+ /**
2448
+ * MAP data type - DuckDB native key/value map (`MAP(keyType, valueType)`)
2449
+ * @param keyType - The data type of map keys
2450
+ * @param valueType - The data type of map values
2451
+ * @example
2452
+ * scores: DataTypes.MAP(DataTypes.STRING, DataTypes.INTEGER)
2453
+ */
2454
+ MAP: createDataTypeFactory((keyType, valueType) => new MAP(keyType, valueType), 'MAP'),
2455
+ /**
2456
+ * UNION data type - DuckDB native tagged union (`UNION(tag TYPE, ...)`)
2457
+ * @param fields - A map of tag name -> alternative data type
2458
+ * @example
2459
+ * value: DataTypes.UNION({ num: DataTypes.INTEGER, str: DataTypes.STRING })
2460
+ */
2461
+ UNION: createDataTypeFactory((fields) => new DUCKDB_UNION(fields), 'UNION'),
2462
+ GEOMETRY: createDataTypeFactory((type, srid) => new GEOMETRY(type, srid), 'GEOMETRY'),
2463
+ GEOGRAPHY: createDataTypeFactory((type, srid) => new GEOGRAPHY(type, srid), 'GEOGRAPHY'),
2464
+ POINT: createDataTypeFactory((srid) => new POINT(srid), 'POINT'),
2465
+ LINESTRING: createDataTypeFactory((srid) => new LINESTRING(srid), 'LINESTRING'),
2466
+ POLYGON: createDataTypeFactory((srid) => new POLYGON(srid), 'POLYGON'),
2467
+ MULTIPOINT: createDataTypeFactory((srid) => new MULTIPOINT(srid), 'MULTIPOINT'),
2468
+ MULTILINESTRING: createDataTypeFactory((srid) => new MULTILINESTRING(srid), 'MULTILINESTRING'),
2469
+ MULTIPOLYGON: createDataTypeFactory((srid) => new MULTIPOLYGON(srid), 'MULTIPOLYGON'),
2470
+ GEOMETRYCOLLECTION: createDataTypeFactory((srid) => new GEOMETRYCOLLECTION(srid), 'GEOMETRYCOLLECTION'),
2471
+ SET: createDataTypeFactory((...values) => new SET(...values), 'SET'),
2472
+ JSONCOLUMN: createDataTypeFactory((options) => new JSONColumn(options), 'JSONCOLUMN'),
2473
+ VIRTUAL: createDataTypeFactory((options) => new VIRTUAL(options), 'VIRTUAL'),
2474
+ VIRTUALSTRING: createDataTypeFactory((options) => new VIRTUALSTRING(options), 'VIRTUALSTRING'),
2475
+ /**
2476
+ * ALGORITHM data type for hash algorithms
2477
+ * Used for storing hashed values (passwords, checksums, etc.)
2478
+ * Supports BCRYPT, MD5, SHA1, SHA256, SHA384, SHA512, ARGON2, PBKDF2, SCRYPT, etc.
2479
+ *
2480
+ * @example
2481
+ * // Store password hash using BCRYPT (recommended for passwords)
2482
+ * password: DataTypes.ALGORITHM({ algorithm: 'BCRYPT', cost: 12 })
2483
+ *
2484
+ * // Store checksum using SHA256
2485
+ * fileChecksum: DataTypes.ALGORITHM({ algorithm: 'SHA256' })
2486
+ *
2487
+ * // Use with VIRTUAL for computed hash fields
2488
+ * passwordHash: DataTypes.VIRTUAL({
2489
+ * returnType: DataTypes.ALGORITHM({ algorithm: 'BCRYPT' }),
2490
+ * set(value: string) {
2491
+ * this.password = hashPassword(value);
2492
+ * }
2493
+ * })
2494
+ */
2495
+ ALGORITHM: createDataTypeFactory((options) => new ALGORITHM(options), 'ALGORITHM'),
2496
+ };
2497
+ /**
2498
+ * Static convenience modifiers, mirroring the chainable instance modifiers
2499
+ * (e.g. `DataTypes.INTEGER().UNSIGNED()`) as pre-built instances so they can
2500
+ * also be accessed directly off the type factory (e.g. `DataTypes.INTEGER.UNSIGNED`).
2501
+ */
2502
+ exports.DataTypes.INTEGER.UNSIGNED = new INTEGER({
2503
+ unsigned: true,
2504
+ });
2505
+ exports.DataTypes.INTEGER.ZEROFILL = new INTEGER({
2506
+ zerofill: true,
2507
+ });
2508
+ // STRING has no UNSIGNED/ZEROFILL semantics in SQL (those only apply to numeric types),
2509
+ // but the property is exposed as a harmless pass-through for API parity.
2510
+ exports.DataTypes.STRING.UNSIGNED = new STRING();
2511
+ exports.DataTypes.STRING.ZEROFILL = new STRING();
2512
+ // BOOLEAN is commonly stored as TINYINT(1) (this is what MySQL/MariaDB already do
2513
+ // under the hood for BOOLEAN columns), exposed here for explicit opt-in.
2514
+ exports.DataTypes.BOOLEAN.TINYINT = new TINYINT({ length: 1 });
2515
+ // DATE-family convenience aliases
2516
+ exports.DataTypes.DATE.TIMESTAMP = new TIMESTAMP();
2517
+ exports.DataTypes.DATE.DATEONLY = new DATEONLY();
2518
+ exports.DataTypes.DATE.TIME = new TIME();