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,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LevelDBStore = void 0;
4
+ /**
5
+ * LevelDB store.
6
+ *
7
+ * LevelDB is an embedded, in-process ordered key-value store (no server),
8
+ * accessed here through the `level` package (an `abstract-level`
9
+ * implementation). A store is opened against a filesystem path and exposes
10
+ * ordered KV primitives — `put`/`get`/`del`, atomic `batch` writes, and
11
+ * ordered iteration via `db.iterator()`. It has no query language and no
12
+ * SQL-shaped surface, so it does not fit the `Dialect` interface used by the
13
+ * SQL dialects in this repo. Instead it implements the minimal `NoSqlStore`
14
+ * marker interface (`src/nosql/store.ts`) and exposes LevelDB's real KV
15
+ * surface directly.
16
+ *
17
+ * Built on the `level` npm driver, loaded lazily inside `connect()` (via
18
+ * `require`) so importing this module never forces the driver to be installed;
19
+ * tests inject a pre-built mock `client` instead and never reach the `require`.
20
+ */
21
+ const errors_1 = require("../../errors");
22
+ /**
23
+ * `LevelDBStore` wraps a `level` client and exposes its embedded KV surface:
24
+ * `put`/`get`/`del` for single keys, `batch` for atomic multi-key writes, and
25
+ * `list` for ordered key iteration (optionally by prefix).
26
+ */
27
+ class LevelDBStore {
28
+ constructor(options = {}) {
29
+ this.name = 'leveldb';
30
+ this.library = 'level';
31
+ this.client = null;
32
+ this.connected = false;
33
+ this.options = options;
34
+ this.path = options.path ?? './data/leveldb';
35
+ }
36
+ async connect() {
37
+ if (this.connected && this.client) {
38
+ return;
39
+ }
40
+ try {
41
+ if (this.options.client) {
42
+ this.client = this.options.client;
43
+ }
44
+ else {
45
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
46
+ const mod = require('level');
47
+ const Level = mod.Level ?? mod;
48
+ this.client = new Level(this.path);
49
+ }
50
+ this.connected = true;
51
+ }
52
+ catch (err) {
53
+ this.client = null;
54
+ this.connected = false;
55
+ const parent = err instanceof Error ? err : new Error(String(err));
56
+ throw new errors_1.ConnectionError(`Unable to open LevelDB: ${parent.message}`, {
57
+ parent,
58
+ database: 'leveldb',
59
+ });
60
+ }
61
+ }
62
+ async disconnect() {
63
+ if (this.client) {
64
+ try {
65
+ await this.client.close();
66
+ }
67
+ catch {
68
+ // best-effort close
69
+ }
70
+ this.client = null;
71
+ }
72
+ this.connected = false;
73
+ }
74
+ isConnected() {
75
+ return this.connected && this.client !== null;
76
+ }
77
+ /** Returns the underlying `level` client for anything not wrapped here. */
78
+ getClient() {
79
+ return this.requireClient();
80
+ }
81
+ requireClient() {
82
+ if (!this.client || !this.connected) {
83
+ throw new errors_1.ConnectionError('LevelDB client is not connected. Call connect() first.', {
84
+ database: 'leveldb',
85
+ });
86
+ }
87
+ return this.client;
88
+ }
89
+ wrapError(action, err) {
90
+ const parent = err instanceof Error ? err : new Error(String(err));
91
+ return errors_1.DatabaseError.from(parent, { message: `LevelDB ${action} failed: ${parent.message}` });
92
+ }
93
+ /** Writes (or overwrites) the value at `key`. */
94
+ async put(key, value) {
95
+ const client = this.requireClient();
96
+ try {
97
+ await client.put(key, value);
98
+ }
99
+ catch (err) {
100
+ throw this.wrapError('put', err);
101
+ }
102
+ }
103
+ /** Reads the value at `key`. */
104
+ async get(key) {
105
+ const client = this.requireClient();
106
+ try {
107
+ return await client.get(key);
108
+ }
109
+ catch (err) {
110
+ throw this.wrapError('get', err);
111
+ }
112
+ }
113
+ /** Deletes the value at `key`. */
114
+ async del(key) {
115
+ const client = this.requireClient();
116
+ try {
117
+ await client.del(key);
118
+ }
119
+ catch (err) {
120
+ throw this.wrapError('del', err);
121
+ }
122
+ }
123
+ /** Applies a list of `put`/`del` operations as a single atomic batch. */
124
+ async batch(ops) {
125
+ const client = this.requireClient();
126
+ try {
127
+ await client.batch(ops);
128
+ }
129
+ catch (err) {
130
+ throw this.wrapError('batch', err);
131
+ }
132
+ }
133
+ /**
134
+ * Lists keys in order. With `prefix`, restricts to keys `>= prefix` and
135
+ * `< prefix + '\xff'` (a standard prefix-scan range for byte-ordered keys).
136
+ */
137
+ async list(prefix) {
138
+ const client = this.requireClient();
139
+ try {
140
+ const range = prefix !== undefined ? { gte: prefix, lt: `${prefix}\xff` } : {};
141
+ const keys = [];
142
+ for await (const [key] of client.iterator(range)) {
143
+ keys.push(String(key));
144
+ }
145
+ return keys;
146
+ }
147
+ catch (err) {
148
+ throw this.wrapError('list', err);
149
+ }
150
+ }
151
+ }
152
+ exports.LevelDBStore = LevelDBStore;
153
+ exports.default = LevelDBStore;
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LmdbStore = void 0;
4
+ /**
5
+ * LMDB store.
6
+ *
7
+ * LMDB (Lightning Memory-Mapped Database) is an embedded, in-process,
8
+ * memory-mapped ordered key-value store (no server). A database is opened
9
+ * against a filesystem path and exposes ordered KV primitives — `put`/`get`,
10
+ * `remove` for deletes, and ordered range scans via `getRange`. It has no
11
+ * query language and no SQL-shaped surface, so it does not fit the `Dialect`
12
+ * interface used by the SQL dialects in this repo. Instead it implements the
13
+ * minimal `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes
14
+ * LMDB's real KV surface directly.
15
+ *
16
+ * Built on the `lmdb` npm driver, loaded lazily inside `connect()` (via
17
+ * `require`) so importing this module never forces the driver to be installed;
18
+ * tests inject a pre-built mock `client` instead and never reach the `require`.
19
+ */
20
+ const errors_1 = require("../../errors");
21
+ /**
22
+ * `LmdbStore` wraps an `lmdb` database and exposes its embedded KV surface:
23
+ * `put`/`get`/`del` for single keys, `batch` for multi-key writes, and `list`
24
+ * for ordered key range scans (optionally by prefix).
25
+ */
26
+ class LmdbStore {
27
+ constructor(options = {}) {
28
+ this.name = 'lmdb';
29
+ this.library = 'lmdb';
30
+ this.client = null;
31
+ this.connected = false;
32
+ this.options = options;
33
+ this.path = options.path ?? './data/lmdb';
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 lmdb = require('lmdb');
46
+ this.client = lmdb.open({ path: this.path, ...this.options.config });
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 LMDB: ${parent.message}`, {
55
+ parent,
56
+ database: 'lmdb',
57
+ });
58
+ }
59
+ }
60
+ async disconnect() {
61
+ if (this.client) {
62
+ try {
63
+ await this.client.close();
64
+ }
65
+ catch {
66
+ // best-effort close
67
+ }
68
+ this.client = null;
69
+ }
70
+ this.connected = false;
71
+ }
72
+ isConnected() {
73
+ return this.connected && this.client !== null;
74
+ }
75
+ /** Returns the underlying `lmdb` database for anything not wrapped here. */
76
+ getClient() {
77
+ return this.requireClient();
78
+ }
79
+ requireClient() {
80
+ if (!this.client || !this.connected) {
81
+ throw new errors_1.ConnectionError('LMDB database is not connected. Call connect() first.', {
82
+ database: 'lmdb',
83
+ });
84
+ }
85
+ return this.client;
86
+ }
87
+ wrapError(action, err) {
88
+ const parent = err instanceof Error ? err : new Error(String(err));
89
+ return errors_1.DatabaseError.from(parent, { message: `LMDB ${action} failed: ${parent.message}` });
90
+ }
91
+ /** Writes (or overwrites) the value at `key`. */
92
+ async put(key, value) {
93
+ const client = this.requireClient();
94
+ try {
95
+ await client.put(key, value);
96
+ }
97
+ catch (err) {
98
+ throw this.wrapError('put', err);
99
+ }
100
+ }
101
+ /** Reads the value at `key` (LMDB reads are synchronous; the result is returned directly). */
102
+ async get(key) {
103
+ const client = this.requireClient();
104
+ try {
105
+ return client.get(key);
106
+ }
107
+ catch (err) {
108
+ throw this.wrapError('get', err);
109
+ }
110
+ }
111
+ /** Deletes the value at `key` (LMDB `remove`). */
112
+ async del(key) {
113
+ const client = this.requireClient();
114
+ try {
115
+ await client.remove(key);
116
+ }
117
+ catch (err) {
118
+ throw this.wrapError('del', err);
119
+ }
120
+ }
121
+ /** Applies a list of `put`/`del` operations. LMDB coalesces concurrent writes into one transaction. */
122
+ async batch(ops) {
123
+ const client = this.requireClient();
124
+ try {
125
+ const pending = [];
126
+ for (const op of ops) {
127
+ if (op.type === 'put') {
128
+ pending.push(client.put(op.key, op.value));
129
+ }
130
+ else {
131
+ pending.push(client.remove(op.key));
132
+ }
133
+ }
134
+ await Promise.all(pending);
135
+ }
136
+ catch (err) {
137
+ throw this.wrapError('batch', err);
138
+ }
139
+ }
140
+ /**
141
+ * Lists keys in order via `getRange`. With `prefix`, restricts to keys
142
+ * `>= prefix` and `< prefix + '\xff'` (a standard prefix-scan range).
143
+ */
144
+ async list(prefix) {
145
+ const client = this.requireClient();
146
+ try {
147
+ const range = prefix !== undefined ? { start: prefix, end: `${prefix}\xff` } : {};
148
+ const keys = [];
149
+ for (const { key } of client.getRange(range)) {
150
+ keys.push(String(key));
151
+ }
152
+ return keys;
153
+ }
154
+ catch (err) {
155
+ throw this.wrapError('list', err);
156
+ }
157
+ }
158
+ }
159
+ exports.LmdbStore = LmdbStore;
160
+ exports.default = LmdbStore;
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ /**
3
+ * Grafana Loki store implementation.
4
+ *
5
+ * Loki is a horizontally-scalable, multi-tenant log aggregation system. It
6
+ * indexes only a small set of labels per log stream (not the log contents)
7
+ * and is queried with LogQL, a label-matcher + filter language modelled on
8
+ * PromQL. There is no SQL-shaped query surface, no row-level UPDATE/DELETE,
9
+ * and no identifier escaping, so Loki does not fit the SQL `Dialect`
10
+ * interface (`src/dialects/dialect.ts`). This class implements the minimal
11
+ * `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes Loki's
12
+ * HTTP push/query API directly.
13
+ *
14
+ * ## No canonical driver - HTTP over `fetch`
15
+ *
16
+ * Loki has no single canonical npm client; it is just an HTTP/JSON API.
17
+ * Rather than depend on any package, this store talks to the server with
18
+ * the global `fetch` (so `library` is `'fetch'`). For tests (and for callers
19
+ * who want their own transport), an alternative HTTP client can be injected
20
+ * via `LokiStoreOptions.client`; when omitted, a tiny internal client over
21
+ * `fetch` + `baseURL` is built at connect time.
22
+ *
23
+ * ## Endpoints wrapped
24
+ *
25
+ * - `push(labels, entries)` -> `POST /loki/api/v1/push` (ingest log lines)
26
+ * - `query(logql, opts?)` -> `GET /loki/api/v1/query_range` (search)
27
+ * - `labels()` -> `GET /loki/api/v1/labels` (label names)
28
+ * - `streams(match?)` -> `GET /loki/api/v1/series` (label sets)
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.LokiStore = exports.DEFAULT_LOKI_BASE_URL = void 0;
32
+ exports.createFetchClient = createFetchClient;
33
+ const errors_1 = require("../../errors");
34
+ /** Default Grafana Loki HTTP API base URL. */
35
+ exports.DEFAULT_LOKI_BASE_URL = 'http://localhost:3100';
36
+ /** Build a `fetch`-backed client for the given base URL. */
37
+ function createFetchClient(baseURL, headers) {
38
+ const buildUrl = (path, params) => {
39
+ const url = new URL(path, baseURL.endsWith('/') ? baseURL : `${baseURL}/`);
40
+ for (const [key, value] of Object.entries(params ?? {})) {
41
+ if (value === undefined)
42
+ continue;
43
+ if (Array.isArray(value)) {
44
+ for (const item of value)
45
+ url.searchParams.append(key, item);
46
+ }
47
+ else {
48
+ url.searchParams.set(key, value);
49
+ }
50
+ }
51
+ return url.toString();
52
+ };
53
+ return {
54
+ async get(path, params) {
55
+ const res = await fetch(buildUrl(path, params), { method: 'GET', headers });
56
+ if (!res.ok)
57
+ throw new Error(`HTTP ${res.status} ${res.statusText}`);
58
+ return res.json();
59
+ },
60
+ async post(path, body, contentType) {
61
+ const res = await fetch(buildUrl(path), {
62
+ method: 'POST',
63
+ body,
64
+ headers: { ...(headers ?? {}), ...(contentType ? { 'Content-Type': contentType } : {}) },
65
+ });
66
+ if (!res.ok)
67
+ throw new Error(`HTTP ${res.status} ${res.statusText}`);
68
+ const text = await res.text();
69
+ if (!text)
70
+ return undefined;
71
+ try {
72
+ return JSON.parse(text);
73
+ }
74
+ catch {
75
+ return text;
76
+ }
77
+ },
78
+ };
79
+ }
80
+ /**
81
+ * `LokiStore` wraps Grafana Loki's HTTP push/query API (log ingestion via
82
+ * the push endpoint, LogQL range search, and label/series metadata lookups)
83
+ * behind the `NoSqlStore` lifecycle.
84
+ */
85
+ class LokiStore {
86
+ constructor(options = {}) {
87
+ this.name = 'loki';
88
+ this.library = 'fetch';
89
+ this.client = null;
90
+ this.connected = false;
91
+ this.baseURL = options.baseURL ?? exports.DEFAULT_LOKI_BASE_URL;
92
+ this.injectedClient = options.client;
93
+ this.headers = {
94
+ ...(options.headers ?? {}),
95
+ ...(options.tenantID ? { 'X-Scope-OrgID': options.tenantID } : {}),
96
+ };
97
+ }
98
+ // ---------------------------------------------------------------------
99
+ // Connection lifecycle
100
+ // ---------------------------------------------------------------------
101
+ async connect() {
102
+ if (this.connected && this.client)
103
+ return;
104
+ this.client = this.injectedClient ?? createFetchClient(this.baseURL, this.headers);
105
+ this.connected = true;
106
+ }
107
+ async disconnect() {
108
+ this.client = null;
109
+ this.connected = false;
110
+ }
111
+ isConnected() {
112
+ return this.connected && this.client !== null;
113
+ }
114
+ /** Returns the underlying (internal or injected) HTTP client. */
115
+ getClient() {
116
+ return this.requireClient();
117
+ }
118
+ requireClient() {
119
+ if (!this.client) {
120
+ throw new errors_1.ConnectionError('Not connected to Loki', {
121
+ database: 'loki',
122
+ host: this.baseURL,
123
+ });
124
+ }
125
+ return this.client;
126
+ }
127
+ async doGet(path, params, action) {
128
+ const client = this.requireClient();
129
+ try {
130
+ const body = await client.get(path, params);
131
+ return body?.data;
132
+ }
133
+ catch (err) {
134
+ const parent = err instanceof Error ? err : new Error(String(err));
135
+ throw errors_1.DatabaseError.from(parent, {
136
+ message: `Loki ${action ?? 'request'} failed: ${parent.message}`,
137
+ });
138
+ }
139
+ }
140
+ // ---------------------------------------------------------------------
141
+ // Ingest
142
+ // ---------------------------------------------------------------------
143
+ /**
144
+ * Pushes a batch of log entries for one stream (identified by its label
145
+ * set) via `POST /loki/api/v1/push`. Each entry is serialized as
146
+ * `[<ts-ns>, <line>]` (plus optional structured metadata) in Loki's
147
+ * push payload shape.
148
+ */
149
+ async push(labels, entries) {
150
+ const client = this.requireClient();
151
+ const values = entries.map((e) => e.metadata
152
+ ? [String(e.ts), e.line, e.metadata]
153
+ : [String(e.ts), e.line]);
154
+ const payload = { streams: [{ stream: labels, values }] };
155
+ try {
156
+ return await client.post('/loki/api/v1/push', JSON.stringify(payload), 'application/json');
157
+ }
158
+ catch (err) {
159
+ const parent = err instanceof Error ? err : new Error(String(err));
160
+ throw errors_1.DatabaseError.from(parent, { message: `Loki push failed: ${parent.message}` });
161
+ }
162
+ }
163
+ // ---------------------------------------------------------------------
164
+ // Query
165
+ // ---------------------------------------------------------------------
166
+ /**
167
+ * Runs a LogQL query over a time window via `GET /loki/api/v1/query_range`.
168
+ * Returns the `data` payload (`{ resultType, result }`).
169
+ */
170
+ async query(logql, options = {}) {
171
+ return this.doGet('/loki/api/v1/query_range', {
172
+ query: logql,
173
+ start: options.start === undefined ? undefined : String(options.start),
174
+ end: options.end === undefined ? undefined : String(options.end),
175
+ limit: options.limit === undefined ? undefined : String(options.limit),
176
+ direction: options.direction,
177
+ step: options.step === undefined ? undefined : String(options.step),
178
+ }, 'query');
179
+ }
180
+ // ---------------------------------------------------------------------
181
+ // Metadata
182
+ // ---------------------------------------------------------------------
183
+ /** Lists the known label names via `GET /loki/api/v1/labels`. */
184
+ async labels() {
185
+ return this.doGet('/loki/api/v1/labels', undefined, 'labels');
186
+ }
187
+ /**
188
+ * Lists the label sets (streams) matching an optional selector via
189
+ * `GET /loki/api/v1/series`.
190
+ */
191
+ async streams(match) {
192
+ const matches = match === undefined ? undefined : Array.isArray(match) ? match : [match];
193
+ return this.doGet('/loki/api/v1/series', matches ? { 'match[]': matches } : undefined, 'series');
194
+ }
195
+ /** Lists the distinct values of a label via `GET /loki/api/v1/label/<name>/values`. */
196
+ async labelValues(label) {
197
+ return this.doGet(`/loki/api/v1/label/${encodeURIComponent(label)}/values`, undefined, 'labelValues');
198
+ }
199
+ }
200
+ exports.LokiStore = LokiStore;
201
+ exports.default = LokiStore;