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,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UnqliteStore = void 0;
4
+ /**
5
+ * UnQLite store.
6
+ *
7
+ * UnQLite is an embedded, in-process, serverless database engine with a simple
8
+ * key-value store layer (plus a document store, not modelled here). A database
9
+ * is opened against a filesystem path and exposes KV primitives — `store`,
10
+ * `fetch`, `delete`, and record iteration. It has no SQL-shaped surface, so it
11
+ * does not fit the `Dialect` interface used by the SQL dialects in this repo.
12
+ * Instead it implements the minimal `NoSqlStore` marker interface
13
+ * (`src/nosql/store.ts`) and maps a common KV surface onto UnQLite's calls.
14
+ *
15
+ * Built on the `unqlite` npm driver (callback-based), loaded lazily inside
16
+ * `connect()` (via `require`) so importing this module never forces the driver
17
+ * to be installed; tests inject a pre-built mock `client` instead and never
18
+ * reach the `require`.
19
+ */
20
+ const errors_1 = require("../../errors");
21
+ /**
22
+ * `UnqliteStore` wraps an `unqlite` client and exposes its embedded KV
23
+ * surface: `put`/`get`/`del` (mapped to `store`/`fetch`/`delete`), `batch` for
24
+ * multi-key writes, and `list` for key iteration.
25
+ */
26
+ class UnqliteStore {
27
+ constructor(options = {}) {
28
+ this.name = 'unqlite';
29
+ this.library = 'unqlite';
30
+ this.client = null;
31
+ this.connected = false;
32
+ this.options = options;
33
+ this.path = options.path ?? './data/unqlite.db';
34
+ }
35
+ async connect() {
36
+ if (this.connected && this.client) {
37
+ return;
38
+ }
39
+ try {
40
+ if (this.options.client) {
41
+ this.client = this.options.client;
42
+ }
43
+ else {
44
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
45
+ const UnQLite = require('unqlite');
46
+ this.client = new UnQLite(this.path);
47
+ }
48
+ this.connected = true;
49
+ }
50
+ catch (err) {
51
+ this.client = null;
52
+ this.connected = false;
53
+ const parent = err instanceof Error ? err : new Error(String(err));
54
+ throw new errors_1.ConnectionError(`Unable to open UnQLite: ${parent.message}`, {
55
+ parent,
56
+ database: 'unqlite',
57
+ });
58
+ }
59
+ }
60
+ async disconnect() {
61
+ if (this.client) {
62
+ const client = this.client;
63
+ if (typeof client.close === 'function') {
64
+ try {
65
+ await this.promisify((cb) => client.close(cb));
66
+ }
67
+ catch {
68
+ // best-effort close
69
+ }
70
+ }
71
+ this.client = null;
72
+ }
73
+ this.connected = false;
74
+ }
75
+ isConnected() {
76
+ return this.connected && this.client !== null;
77
+ }
78
+ /** Returns the underlying `unqlite` client for anything not wrapped here. */
79
+ getClient() {
80
+ return this.requireClient();
81
+ }
82
+ requireClient() {
83
+ if (!this.client || !this.connected) {
84
+ throw new errors_1.ConnectionError('UnQLite client is not connected. Call connect() first.', {
85
+ database: 'unqlite',
86
+ });
87
+ }
88
+ return this.client;
89
+ }
90
+ wrapError(action, err) {
91
+ const parent = err instanceof Error ? err : new Error(String(err));
92
+ return errors_1.DatabaseError.from(parent, { message: `UnQLite ${action} failed: ${parent.message}` });
93
+ }
94
+ /** Wrap a callback-style UnQLite call into a Promise. */
95
+ promisify(fn) {
96
+ return new Promise((resolve, reject) => {
97
+ fn((err, result) => (err ? reject(err) : resolve(result)));
98
+ });
99
+ }
100
+ /** Writes (or overwrites) the value at `key` (UnQLite `store`). */
101
+ async put(key, value) {
102
+ const client = this.requireClient();
103
+ try {
104
+ await this.promisify((cb) => client.store(key, value, cb));
105
+ }
106
+ catch (err) {
107
+ throw this.wrapError('put', err);
108
+ }
109
+ }
110
+ /** Reads the value at `key` (UnQLite `fetch`). */
111
+ async get(key) {
112
+ const client = this.requireClient();
113
+ try {
114
+ return await this.promisify((cb) => client.fetch(key, cb));
115
+ }
116
+ catch (err) {
117
+ throw this.wrapError('get', err);
118
+ }
119
+ }
120
+ /** Deletes the value at `key` (UnQLite `delete`). */
121
+ async del(key) {
122
+ const client = this.requireClient();
123
+ try {
124
+ await this.promisify((cb) => client.delete(key, cb));
125
+ }
126
+ catch (err) {
127
+ throw this.wrapError('del', err);
128
+ }
129
+ }
130
+ /** Applies a list of `put`/`del` operations sequentially. */
131
+ async batch(ops) {
132
+ for (const op of ops) {
133
+ if (op.type === 'put') {
134
+ await this.put(op.key, op.value);
135
+ }
136
+ else {
137
+ await this.del(op.key);
138
+ }
139
+ }
140
+ }
141
+ /** Lists all keys by iterating records with UnQLite's `each` cursor. */
142
+ async list() {
143
+ const client = this.requireClient();
144
+ try {
145
+ const keys = [];
146
+ await this.promisify((cb) => client.each((key) => {
147
+ keys.push(String(key));
148
+ }, cb));
149
+ return keys;
150
+ }
151
+ catch (err) {
152
+ throw this.wrapError('list', err);
153
+ }
154
+ }
155
+ }
156
+ exports.UnqliteStore = UnqliteStore;
157
+ exports.default = UnqliteStore;
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ /**
3
+ * Upstash Redis store implementation.
4
+ *
5
+ * Upstash Redis is a serverless, globally-replicated Redis served over an
6
+ * HTTP/REST connection via the `@upstash/redis` client. It has no SQL query
7
+ * surface, so this class implements the minimal `NoSqlStore` marker
8
+ * interface and exposes an edge-KV `get`/`set`/`del`/`list`/`incr` surface
9
+ * mapped onto the `@upstash/redis` client.
10
+ *
11
+ * ## Driver
12
+ *
13
+ * Uses `@upstash/redis` (`new Redis({ url, token })`). The driver is loaded
14
+ * lazily inside `connect()` (or supplied pre-built via the `client` option)
15
+ * so importing this module never requires `@upstash/redis` to be installed
16
+ * unless a store is actually connected. Tests inject a mock `client`.
17
+ *
18
+ * ## Serialization
19
+ *
20
+ * String values are passed through verbatim; every other value is
21
+ * `JSON.stringify`'d before being written.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.UpstashStore = void 0;
25
+ const errors_1 = require("../../errors");
26
+ function serialize(value) {
27
+ return typeof value === 'string' ? value : JSON.stringify(value);
28
+ }
29
+ /**
30
+ * `UpstashStore` wraps an `@upstash/redis` client behind the `NoSqlStore`
31
+ * lifecycle and an edge-KV `get`/`set`/`del`/`list`/`incr` surface.
32
+ */
33
+ class UpstashStore {
34
+ constructor(options = {}) {
35
+ this.name = 'upstash';
36
+ this.library = '@upstash/redis';
37
+ this.client = null;
38
+ this.connected = false;
39
+ this.options = options;
40
+ }
41
+ // ---------------------------------------------------------------------
42
+ // Connection lifecycle
43
+ // ---------------------------------------------------------------------
44
+ async connect() {
45
+ if (this.connected && this.client) {
46
+ return;
47
+ }
48
+ try {
49
+ if (this.options.client) {
50
+ this.client = this.options.client;
51
+ }
52
+ else {
53
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
54
+ const mod = require('@upstash/redis');
55
+ const Redis = mod.Redis ?? mod.default ?? mod;
56
+ this.client = new Redis({
57
+ url: this.options.url,
58
+ token: this.options.token,
59
+ });
60
+ }
61
+ this.connected = true;
62
+ }
63
+ catch (err) {
64
+ this.client = null;
65
+ this.connected = false;
66
+ throw wrapConnectionError(err, this.options.url);
67
+ }
68
+ }
69
+ async disconnect() {
70
+ this.client = null;
71
+ this.connected = false;
72
+ }
73
+ isConnected() {
74
+ return this.connected && this.client !== null;
75
+ }
76
+ /** Returns the underlying `@upstash/redis` client for anything not wrapped here. */
77
+ getClient() {
78
+ return this.requireClient();
79
+ }
80
+ requireClient() {
81
+ if (!this.client) {
82
+ throw new errors_1.ConnectionError('Not connected to Upstash Redis', {
83
+ database: 'upstash',
84
+ host: this.options.url,
85
+ });
86
+ }
87
+ return this.client;
88
+ }
89
+ // ---------------------------------------------------------------------
90
+ // Key-value operations
91
+ // ---------------------------------------------------------------------
92
+ /** Read a key. Returns whatever the client returns (`null` if missing). */
93
+ async get(key) {
94
+ const client = this.requireClient();
95
+ try {
96
+ return await client.get(key);
97
+ }
98
+ catch (err) {
99
+ throw wrapDatabaseError(err, 'GET');
100
+ }
101
+ }
102
+ /**
103
+ * Write `value` under `key`. Strings are stored verbatim; other values are
104
+ * JSON-serialized. `options.ttl` maps to Redis `EX` (seconds),
105
+ * `options.expiration` to `EXAT` (absolute Unix seconds).
106
+ */
107
+ async set(key, value, options = {}) {
108
+ const client = this.requireClient();
109
+ const setOptions = {};
110
+ if (options.ttl !== undefined)
111
+ setOptions.ex = options.ttl;
112
+ if (options.expiration !== undefined)
113
+ setOptions.exat = options.expiration;
114
+ try {
115
+ return await client.set(key, serialize(value), Object.keys(setOptions).length > 0 ? setOptions : undefined);
116
+ }
117
+ catch (err) {
118
+ throw wrapDatabaseError(err, 'SET');
119
+ }
120
+ }
121
+ /** Delete a key. Returns the number of keys removed. */
122
+ async del(key) {
123
+ const client = this.requireClient();
124
+ try {
125
+ return await client.del(key);
126
+ }
127
+ catch (err) {
128
+ throw wrapDatabaseError(err, 'DEL');
129
+ }
130
+ }
131
+ /** List key names, optionally filtered by `prefix` (matched as `<prefix>*`). */
132
+ async list(prefix) {
133
+ const client = this.requireClient();
134
+ try {
135
+ return await client.keys(prefix ? `${prefix}*` : '*');
136
+ }
137
+ catch (err) {
138
+ throw wrapDatabaseError(err, 'LIST');
139
+ }
140
+ }
141
+ /** Atomically increment the numeric value at `key` by `by` (default `1`). */
142
+ async incr(key, by = 1) {
143
+ const client = this.requireClient();
144
+ try {
145
+ return by === 1 ? await client.incr(key) : await client.incrby(key, by);
146
+ }
147
+ catch (err) {
148
+ throw wrapDatabaseError(err, 'INCR');
149
+ }
150
+ }
151
+ }
152
+ exports.UpstashStore = UpstashStore;
153
+ function wrapConnectionError(err, host) {
154
+ const parent = err instanceof Error ? err : new Error(String(err));
155
+ return new errors_1.ConnectionError(`Unable to connect to Upstash Redis: ${parent.message}`, {
156
+ parent,
157
+ database: 'upstash',
158
+ host,
159
+ });
160
+ }
161
+ function wrapDatabaseError(err, action) {
162
+ const parent = err instanceof Error ? err : new Error(String(err));
163
+ return errors_1.DatabaseError.from(parent, {
164
+ message: `Upstash Redis ${action} failed: ${parent.message}`,
165
+ });
166
+ }
167
+ exports.default = UpstashStore;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ /**
3
+ * Vercel KV store implementation.
4
+ *
5
+ * Vercel KV is a serverless, globally-replicated Redis-compatible key-value
6
+ * store fronted by the `@vercel/kv` client (a durable-HTTP Redis client). It
7
+ * has no SQL query surface, so this class implements the minimal
8
+ * `NoSqlStore` marker interface and exposes an edge-KV
9
+ * `get`/`set`/`del`/`list`/`incr` surface mapped onto the `@vercel/kv`
10
+ * client.
11
+ *
12
+ * ## Driver
13
+ *
14
+ * Uses `@vercel/kv` (`createClient({ url, token })`). The driver is loaded
15
+ * lazily inside `connect()` (or supplied pre-built via the `client` option)
16
+ * so importing this module never requires `@vercel/kv` to be installed
17
+ * unless a store is actually connected. Tests inject a mock `client`.
18
+ *
19
+ * ## Serialization
20
+ *
21
+ * String values are passed through verbatim; every other value is
22
+ * `JSON.stringify`'d before being written, so reads via `get()` return the
23
+ * serialized string.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.VercelKvStore = void 0;
27
+ const errors_1 = require("../../errors");
28
+ function serialize(value) {
29
+ return typeof value === 'string' ? value : JSON.stringify(value);
30
+ }
31
+ /**
32
+ * `VercelKvStore` wraps a `@vercel/kv` client behind the `NoSqlStore`
33
+ * lifecycle and an edge-KV `get`/`set`/`del`/`list`/`incr` surface.
34
+ */
35
+ class VercelKvStore {
36
+ constructor(options = {}) {
37
+ this.name = 'vercel-kv';
38
+ this.library = '@vercel/kv';
39
+ this.client = null;
40
+ this.connected = false;
41
+ this.options = options;
42
+ }
43
+ // ---------------------------------------------------------------------
44
+ // Connection lifecycle
45
+ // ---------------------------------------------------------------------
46
+ async connect() {
47
+ if (this.connected && this.client) {
48
+ return;
49
+ }
50
+ try {
51
+ if (this.options.client) {
52
+ this.client = this.options.client;
53
+ }
54
+ else {
55
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
56
+ const kv = require('@vercel/kv');
57
+ this.client = kv.createClient({
58
+ url: this.options.url,
59
+ token: this.options.token,
60
+ });
61
+ }
62
+ this.connected = true;
63
+ }
64
+ catch (err) {
65
+ this.client = null;
66
+ this.connected = false;
67
+ throw wrapConnectionError(err, this.options.url);
68
+ }
69
+ }
70
+ async disconnect() {
71
+ this.client = null;
72
+ this.connected = false;
73
+ }
74
+ isConnected() {
75
+ return this.connected && this.client !== null;
76
+ }
77
+ /** Returns the underlying `@vercel/kv` client for anything not wrapped here. */
78
+ getClient() {
79
+ return this.requireClient();
80
+ }
81
+ requireClient() {
82
+ if (!this.client) {
83
+ throw new errors_1.ConnectionError('Not connected to Vercel KV', {
84
+ database: 'vercel-kv',
85
+ host: this.options.url,
86
+ });
87
+ }
88
+ return this.client;
89
+ }
90
+ // ---------------------------------------------------------------------
91
+ // Key-value operations
92
+ // ---------------------------------------------------------------------
93
+ /** Read a key. Returns whatever the client returns (`null` if missing). */
94
+ async get(key) {
95
+ const client = this.requireClient();
96
+ try {
97
+ return await client.get(key);
98
+ }
99
+ catch (err) {
100
+ throw wrapDatabaseError(err, 'GET');
101
+ }
102
+ }
103
+ /**
104
+ * Write `value` under `key`. Strings are stored verbatim; other values are
105
+ * JSON-serialized. `options.ttl` maps to Redis `EX` (seconds),
106
+ * `options.expiration` to `EXAT` (absolute Unix seconds).
107
+ */
108
+ async set(key, value, options = {}) {
109
+ const client = this.requireClient();
110
+ const setOptions = {};
111
+ if (options.ttl !== undefined)
112
+ setOptions.ex = options.ttl;
113
+ if (options.expiration !== undefined)
114
+ setOptions.exat = options.expiration;
115
+ try {
116
+ return await client.set(key, serialize(value), Object.keys(setOptions).length > 0 ? setOptions : undefined);
117
+ }
118
+ catch (err) {
119
+ throw wrapDatabaseError(err, 'SET');
120
+ }
121
+ }
122
+ /** Delete a key. Returns the number of keys removed. */
123
+ async del(key) {
124
+ const client = this.requireClient();
125
+ try {
126
+ return await client.del(key);
127
+ }
128
+ catch (err) {
129
+ throw wrapDatabaseError(err, 'DEL');
130
+ }
131
+ }
132
+ /** List key names, optionally filtered by `prefix` (matched as `<prefix>*`). */
133
+ async list(prefix) {
134
+ const client = this.requireClient();
135
+ try {
136
+ return await client.keys(prefix ? `${prefix}*` : '*');
137
+ }
138
+ catch (err) {
139
+ throw wrapDatabaseError(err, 'LIST');
140
+ }
141
+ }
142
+ /** Atomically increment the numeric value at `key` by `by` (default `1`). */
143
+ async incr(key, by = 1) {
144
+ const client = this.requireClient();
145
+ try {
146
+ return by === 1 ? await client.incr(key) : await client.incrby(key, by);
147
+ }
148
+ catch (err) {
149
+ throw wrapDatabaseError(err, 'INCR');
150
+ }
151
+ }
152
+ }
153
+ exports.VercelKvStore = VercelKvStore;
154
+ function wrapConnectionError(err, host) {
155
+ const parent = err instanceof Error ? err : new Error(String(err));
156
+ return new errors_1.ConnectionError(`Unable to connect to Vercel KV: ${parent.message}`, {
157
+ parent,
158
+ database: 'vercel-kv',
159
+ host,
160
+ });
161
+ }
162
+ function wrapDatabaseError(err, action) {
163
+ const parent = err instanceof Error ? err : new Error(String(err));
164
+ return errors_1.DatabaseError.from(parent, { message: `Vercel KV ${action} failed: ${parent.message}` });
165
+ }
166
+ exports.default = VercelKvStore;
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ /**
3
+ * VictoriaMetrics store implementation.
4
+ *
5
+ * VictoriaMetrics is a fast, cost-effective time-series database. Crucially
6
+ * it is **API-compatible with Prometheus**: it exposes the same
7
+ * `/api/v1/query` and `/api/v1/query_range` PromQL endpoints (plus MetricsQL
8
+ * extensions), so PromQL queries written against Prometheus work unchanged
9
+ * here. Unlike Prometheus, VictoriaMetrics also accepts client-side writes -
10
+ * it can ingest data pushed to it in several line formats, including the
11
+ * Prometheus text exposition format via `/api/v1/import/prometheus`.
12
+ *
13
+ * Because there is no SQL-shaped query surface, no row-level UPDATE/DELETE,
14
+ * and no identifier escaping, this engine does not fit the SQL `Dialect`
15
+ * interface (`src/dialects/dialect.ts`). This class implements the minimal
16
+ * `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes the
17
+ * Prometheus-compatible read API plus VictoriaMetrics's write API.
18
+ *
19
+ * ## No canonical driver - HTTP over `fetch`
20
+ *
21
+ * VictoriaMetrics has no single canonical npm client; it is an HTTP/JSON
22
+ * (and text-ingest) API. This store talks to it with the global `fetch`.
23
+ * For tests (and custom transports) an alternative HTTP client can be
24
+ * injected via `VictoriaMetricsStoreOptions.client`; when omitted, a tiny
25
+ * internal client over `fetch` + `baseURL` is built at connect time.
26
+ *
27
+ * ## Endpoints wrapped
28
+ *
29
+ * Read (Prometheus-compatible, under `/api/v1`):
30
+ * - `instantQuery(promql, time?)` -> `GET /api/v1/query`
31
+ * - `rangeQuery(promql, {start,end,step})` -> `GET /api/v1/query_range`
32
+ *
33
+ * Write (VictoriaMetrics-specific):
34
+ * - `importPrometheus(lines)` -> `POST /api/v1/import/prometheus`
35
+ * - `write(metric, value, timestamp?, labels?)` builds one Prometheus
36
+ * exposition line and POSTs it via `importPrometheus`.
37
+ *
38
+ * Read methods return the parsed `data` field of the response envelope.
39
+ */
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.VictoriaMetricsStore = exports.DEFAULT_VICTORIAMETRICS_BASE_URL = void 0;
42
+ exports.createFetchClient = createFetchClient;
43
+ exports.buildPrometheusLine = buildPrometheusLine;
44
+ const errors_1 = require("../../errors");
45
+ /** Default VictoriaMetrics HTTP API base URL (single-node). */
46
+ exports.DEFAULT_VICTORIAMETRICS_BASE_URL = 'http://localhost:8428';
47
+ /** Build a `fetch`-backed client for the given base URL. */
48
+ function createFetchClient(baseURL, headers) {
49
+ const buildUrl = (path, params) => {
50
+ const url = new URL(path, baseURL.endsWith('/') ? baseURL : `${baseURL}/`);
51
+ for (const [key, value] of Object.entries(params ?? {})) {
52
+ if (value === undefined)
53
+ continue;
54
+ if (Array.isArray(value)) {
55
+ for (const item of value)
56
+ url.searchParams.append(key, item);
57
+ }
58
+ else {
59
+ url.searchParams.set(key, value);
60
+ }
61
+ }
62
+ return url.toString();
63
+ };
64
+ return {
65
+ async get(path, params) {
66
+ const res = await fetch(buildUrl(path, params), { method: 'GET', headers });
67
+ if (!res.ok) {
68
+ throw new Error(`HTTP ${res.status} ${res.statusText}`);
69
+ }
70
+ return res.json();
71
+ },
72
+ async post(path, body, contentType) {
73
+ const res = await fetch(buildUrl(path), {
74
+ method: 'POST',
75
+ body,
76
+ headers: { ...(headers ?? {}), ...(contentType ? { 'Content-Type': contentType } : {}) },
77
+ });
78
+ if (!res.ok) {
79
+ throw new Error(`HTTP ${res.status} ${res.statusText}`);
80
+ }
81
+ const text = await res.text();
82
+ return text || undefined;
83
+ },
84
+ };
85
+ }
86
+ /**
87
+ * Build a single Prometheus text-exposition line:
88
+ *
89
+ * metric{label="value",...} value [timestamp_ms]
90
+ *
91
+ * Label values are escaped per the exposition format (`\`, `"`, newline).
92
+ */
93
+ function buildPrometheusLine(metric, value, timestamp, labels) {
94
+ const entries = Object.entries(labels ?? {});
95
+ const labelPart = entries.length
96
+ ? `{${entries
97
+ .map(([k, v]) => `${k}="${String(v).replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n')}"`)
98
+ .join(',')}}`
99
+ : '';
100
+ const tsPart = timestamp === undefined ? '' : ` ${timestamp}`;
101
+ return `${metric}${labelPart} ${value}${tsPart}`;
102
+ }
103
+ /**
104
+ * `VictoriaMetricsStore` wraps VictoriaMetrics's Prometheus-compatible
105
+ * PromQL read API (instant/range queries) and its Prometheus-exposition
106
+ * write/import API behind the `NoSqlStore` lifecycle.
107
+ */
108
+ class VictoriaMetricsStore {
109
+ constructor(options = {}) {
110
+ this.name = 'victoriametrics';
111
+ this.library = 'fetch';
112
+ this.client = null;
113
+ this.connected = false;
114
+ this.baseURL = options.baseURL ?? exports.DEFAULT_VICTORIAMETRICS_BASE_URL;
115
+ this.injectedClient = options.client;
116
+ this.headers = options.headers;
117
+ }
118
+ // ---------------------------------------------------------------------
119
+ // Connection lifecycle
120
+ // ---------------------------------------------------------------------
121
+ async connect() {
122
+ if (this.connected && this.client) {
123
+ return;
124
+ }
125
+ this.client = this.injectedClient ?? createFetchClient(this.baseURL, this.headers);
126
+ this.connected = true;
127
+ }
128
+ async disconnect() {
129
+ this.client = null;
130
+ this.connected = false;
131
+ }
132
+ isConnected() {
133
+ return this.connected && this.client !== null;
134
+ }
135
+ /** Returns the underlying (internal or injected) HTTP client. */
136
+ getClient() {
137
+ return this.requireClient();
138
+ }
139
+ requireClient() {
140
+ if (!this.client) {
141
+ throw new errors_1.ConnectionError('Not connected to VictoriaMetrics', {
142
+ database: 'victoriametrics',
143
+ host: this.baseURL,
144
+ });
145
+ }
146
+ return this.client;
147
+ }
148
+ async doGet(path, params, action) {
149
+ const client = this.requireClient();
150
+ try {
151
+ const body = await client.get(path, params);
152
+ return body?.data;
153
+ }
154
+ catch (err) {
155
+ const parent = err instanceof Error ? err : new Error(String(err));
156
+ throw errors_1.DatabaseError.from(parent, {
157
+ message: `VictoriaMetrics ${action ?? 'request'} failed: ${parent.message}`,
158
+ });
159
+ }
160
+ }
161
+ // ---------------------------------------------------------------------
162
+ // PromQL query API (Prometheus-compatible, read-only)
163
+ // ---------------------------------------------------------------------
164
+ /**
165
+ * Runs a PromQL/MetricsQL instant query via `GET /api/v1/query`
166
+ * (identical to the Prometheus endpoint). Returns the `data` payload.
167
+ */
168
+ async instantQuery(promql, time) {
169
+ return this.doGet('/api/v1/query', { query: promql, time: time === undefined ? undefined : String(time) }, 'instantQuery');
170
+ }
171
+ /**
172
+ * Runs a PromQL/MetricsQL range query via `GET /api/v1/query_range`
173
+ * (identical to the Prometheus endpoint). Returns the `data` payload.
174
+ */
175
+ async rangeQuery(promql, options) {
176
+ return this.doGet('/api/v1/query_range', {
177
+ query: promql,
178
+ start: String(options.start),
179
+ end: String(options.end),
180
+ step: String(options.step),
181
+ }, 'rangeQuery');
182
+ }
183
+ // ---------------------------------------------------------------------
184
+ // Write API (VictoriaMetrics-specific)
185
+ // ---------------------------------------------------------------------
186
+ /**
187
+ * Imports raw data in Prometheus text-exposition format via
188
+ * `POST /api/v1/import/prometheus`. Accepts a single newline-delimited
189
+ * string or an array of lines (joined with newlines).
190
+ */
191
+ async importPrometheus(lines) {
192
+ const client = this.requireClient();
193
+ const body = Array.isArray(lines) ? lines.join('\n') : lines;
194
+ try {
195
+ return await client.post('/api/v1/import/prometheus', body, 'text/plain');
196
+ }
197
+ catch (err) {
198
+ const parent = err instanceof Error ? err : new Error(String(err));
199
+ throw errors_1.DatabaseError.from(parent, {
200
+ message: `VictoriaMetrics importPrometheus failed: ${parent.message}`,
201
+ });
202
+ }
203
+ }
204
+ /**
205
+ * Writes a single sample by building one Prometheus-exposition line
206
+ * (`metric{labels} value [timestamp_ms]`) and importing it via
207
+ * `importPrometheus`.
208
+ */
209
+ async write(metric, value, timestamp, labels) {
210
+ return this.importPrometheus(buildPrometheusLine(metric, value, timestamp, labels));
211
+ }
212
+ }
213
+ exports.VictoriaMetricsStore = VictoriaMetricsStore;