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.
- package/CHANGELOG.md +1111 -0
- package/LICENSE +21 -0
- package/README.md +573 -0
- package/dist/audit/history-query.js +180 -0
- package/dist/audit/index.js +23 -0
- package/dist/audit/logger.js +236 -0
- package/dist/cache/cache-manager.js +84 -0
- package/dist/cache/index.js +16 -0
- package/dist/cache/redis-cluster-cache.js +557 -0
- package/dist/cli.js +2200 -0
- package/dist/compliance/audit-trail.js +68 -0
- package/dist/compliance/backup-verification.js +685 -0
- package/dist/compliance/breach-detector.js +505 -0
- package/dist/compliance/consent-record.js +227 -0
- package/dist/compliance/consent-versioning.js +331 -0
- package/dist/compliance/cross-border-log.js +530 -0
- package/dist/compliance/data-classifier.js +258 -0
- package/dist/compliance/data-lineage.js +565 -0
- package/dist/compliance/data-masker.js +303 -0
- package/dist/compliance/data-portability.js +265 -0
- package/dist/compliance/data-retention.js +195 -0
- package/dist/compliance/dsar-workflow.js +342 -0
- package/dist/compliance/field-encryption.js +223 -0
- package/dist/compliance/immutable-record.js +148 -0
- package/dist/compliance/index.js +260 -0
- package/dist/compliance/privacy-impact-assessment.js +364 -0
- package/dist/compliance/pseudonymization.js +269 -0
- package/dist/compliance/query-firewall.js +1182 -0
- package/dist/compliance/rate-limiter.js +580 -0
- package/dist/compliance/right-to-erasure.js +117 -0
- package/dist/compliance/row-level-security.js +246 -0
- package/dist/compliance/security-decorator.js +574 -0
- package/dist/compliance/security-monitor.js +525 -0
- package/dist/compliance/sensitive-data-discovery.js +476 -0
- package/dist/compliance/session-isolation.js +472 -0
- package/dist/compliance/tls-enforcer.js +108 -0
- package/dist/compliance/worm-storage.js +712 -0
- package/dist/connection-manager.js +198 -0
- package/dist/connection-pool.js +519 -0
- package/dist/decorators/audit.js +136 -0
- package/dist/decorators/belongs-to-many.js +115 -0
- package/dist/decorators/belongs-to.js +115 -0
- package/dist/decorators/check.js +435 -0
- package/dist/decorators/collate.js +329 -0
- package/dist/decorators/comment.js +205 -0
- package/dist/decorators/database-settings.js +236 -0
- package/dist/decorators/default.js +244 -0
- package/dist/decorators/encryption.js +235 -0
- package/dist/decorators/engine.js +97 -0
- package/dist/decorators/fk-constraints.js +594 -0
- package/dist/decorators/foreign-table.js +136 -0
- package/dist/decorators/generated.js +274 -0
- package/dist/decorators/has-many.js +127 -0
- package/dist/decorators/has-one.js +116 -0
- package/dist/decorators/hstore.js +129 -0
- package/dist/decorators/index.js +355 -0
- package/dist/decorators/json-column.js +83 -0
- package/dist/decorators/jsonb.js +101 -0
- package/dist/decorators/orm-decorators.js +425 -0
- package/dist/decorators/permissions.js +294 -0
- package/dist/decorators/procedure.js +210 -0
- package/dist/decorators/query-options.js +556 -0
- package/dist/decorators/range.js +167 -0
- package/dist/decorators/set-column.js +83 -0
- package/dist/decorators/spatial.js +114 -0
- package/dist/decorators/storage.js +580 -0
- package/dist/decorators/timezone.js +512 -0
- package/dist/decorators/trigger.js +90 -0
- package/dist/decorators/uuid.js +135 -0
- package/dist/decorators/view.js +258 -0
- package/dist/diagrams/chen-diagram.js +354 -0
- package/dist/diagrams/class-diagram.js +384 -0
- package/dist/diagrams/dependency-diagram.js +432 -0
- package/dist/diagrams/er-diagram.js +605 -0
- package/dist/diagrams/flow-diagram.js +394 -0
- package/dist/diagrams/gantt-diagram.js +411 -0
- package/dist/diagrams/index-diagram.js +353 -0
- package/dist/diagrams/index.js +184 -0
- package/dist/diagrams/migration-diagram.js +316 -0
- package/dist/diagrams/model-diagram.js +616 -0
- package/dist/diagrams/package-diagram.js +376 -0
- package/dist/diagrams/palette.js +85 -0
- package/dist/diagrams/relational-diagram.js +455 -0
- package/dist/diagrams/schemadoc-diagram.js +309 -0
- package/dist/diagrams/sequence-diagram.js +307 -0
- package/dist/diagrams/state-diagram.js +344 -0
- package/dist/diagrams/svg-dom.js +111 -0
- package/dist/diagrams/tree-diagram.js +250 -0
- package/dist/dialects/clickhouse/index.js +1742 -0
- package/dist/dialects/cockroachdb/index.js +4677 -0
- package/dist/dialects/cratedb/index.js +441 -0
- package/dist/dialects/databricks/index.js +517 -0
- package/dist/dialects/db2/index.js +2225 -0
- package/dist/dialects/dialect.js +720 -0
- package/dist/dialects/duckdb/index.js +2014 -0
- package/dist/dialects/exasol/index.js +357 -0
- package/dist/dialects/firebird/index.js +495 -0
- package/dist/dialects/greenplum/index.js +457 -0
- package/dist/dialects/hana/index.js +1741 -0
- package/dist/dialects/mariadb/index.js +3590 -0
- package/dist/dialects/mssql/index.js +2296 -0
- package/dist/dialects/mysql/index.js +4058 -0
- package/dist/dialects/oracle/index.js +2999 -0
- package/dist/dialects/postgres/index.js +5319 -0
- package/dist/dialects/query-stream-helper.js +152 -0
- package/dist/dialects/questdb/index.js +433 -0
- package/dist/dialects/redshift/index.js +2277 -0
- package/dist/dialects/singlestore/index.js +354 -0
- package/dist/dialects/snowflake/index.js +2082 -0
- package/dist/dialects/spanner/index.js +1768 -0
- package/dist/dialects/sqlite/index.js +3382 -0
- package/dist/dialects/tidb/index.js +377 -0
- package/dist/dialects/timescaledb/index.js +164 -0
- package/dist/dialects/trino/index.js +420 -0
- package/dist/dialects/turso/index.js +227 -0
- package/dist/dialects/vertica/index.js +317 -0
- package/dist/dialects/yugabytedb/index.js +424 -0
- package/dist/errors/index.js +472 -0
- package/dist/errors/utils.js +340 -0
- package/dist/errors.js +21 -0
- package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
- package/dist/extensions/catalog/mssql-features.js +147 -0
- package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
- package/dist/extensions/catalog/oracle-db2-features.js +196 -0
- package/dist/extensions/catalog/postgres-extensions.js +516 -0
- package/dist/extensions/index.js +71 -0
- package/dist/extensions/types.js +13 -0
- package/dist/foreign-data.js +173 -0
- package/dist/hooks/hooks-manager.js +350 -0
- package/dist/hooks/index.js +37 -0
- package/dist/index.js +463 -0
- package/dist/logging.js +335 -0
- package/dist/migrations/index.js +40 -0
- package/dist/migrations/migration.js +196 -0
- package/dist/migrations/migrator.js +411 -0
- package/dist/migrations/prormmigration.js +275 -0
- package/dist/migrations/query-interface.js +435 -0
- package/dist/migrations/seeder.js +353 -0
- package/dist/models/associations.js +852 -0
- package/dist/models/constraints.js +288 -0
- package/dist/models/data-types.js +2518 -0
- package/dist/models/decorators.js +445 -0
- package/dist/models/index.js +33 -0
- package/dist/models/indexes.js +531 -0
- package/dist/models/methods.js +382 -0
- package/dist/models/model-manager.js +103 -0
- package/dist/models/model.js +5349 -0
- package/dist/models/operators.js +67 -0
- package/dist/models/scopes.js +189 -0
- package/dist/models/typescript-types.js +26 -0
- package/dist/nosql/aerospike/index.js +205 -0
- package/dist/nosql/allegrograph/index.js +169 -0
- package/dist/nosql/arangodb/index.js +364 -0
- package/dist/nosql/azure-blob/index.js +206 -0
- package/dist/nosql/beanstalkd/index.js +231 -0
- package/dist/nosql/beequeue/index.js +210 -0
- package/dist/nosql/bigchaindb/index.js +195 -0
- package/dist/nosql/bigtable/index.js +224 -0
- package/dist/nosql/blazegraph/index.js +173 -0
- package/dist/nosql/bullmq/index.js +191 -0
- package/dist/nosql/cassandra/index.js +174 -0
- package/dist/nosql/chroma/index.js +190 -0
- package/dist/nosql/cloudflare-kv/index.js +220 -0
- package/dist/nosql/coherence/index.js +200 -0
- package/dist/nosql/cosmosdb/index.js +157 -0
- package/dist/nosql/couchbase/index.js +213 -0
- package/dist/nosql/dax/index.js +212 -0
- package/dist/nosql/deno-kv/index.js +206 -0
- package/dist/nosql/dgraph/index.js +171 -0
- package/dist/nosql/doris/index.js +169 -0
- package/dist/nosql/druid/index.js +162 -0
- package/dist/nosql/dynamodb/index.js +937 -0
- package/dist/nosql/elasticsearch/index.js +377 -0
- package/dist/nosql/etcd/index.js +502 -0
- package/dist/nosql/eventhubs/index.js +213 -0
- package/dist/nosql/eventstore/index.js +254 -0
- package/dist/nosql/faunadb/index.js +188 -0
- package/dist/nosql/firestore/index.js +177 -0
- package/dist/nosql/fluree/index.js +148 -0
- package/dist/nosql/fuseki/index.js +170 -0
- package/dist/nosql/gcs/index.js +172 -0
- package/dist/nosql/gearman/index.js +160 -0
- package/dist/nosql/geode/index.js +196 -0
- package/dist/nosql/graphdb/index.js +169 -0
- package/dist/nosql/graylog/index.js +188 -0
- package/dist/nosql/gridgain/index.js +171 -0
- package/dist/nosql/hazelcast/index.js +162 -0
- package/dist/nosql/hbase/index.js +230 -0
- package/dist/nosql/ignite/index.js +173 -0
- package/dist/nosql/immudb/index.js +184 -0
- package/dist/nosql/index.js +232 -0
- package/dist/nosql/infinispan/index.js +200 -0
- package/dist/nosql/influxdb/index.js +0 -0
- package/dist/nosql/kafka/index.js +234 -0
- package/dist/nosql/keyspaces/index.js +189 -0
- package/dist/nosql/kinesis/index.js +253 -0
- package/dist/nosql/leveldb/index.js +153 -0
- package/dist/nosql/lmdb/index.js +160 -0
- package/dist/nosql/loki/index.js +201 -0
- package/dist/nosql/marklogic/index.js +204 -0
- package/dist/nosql/materialize/index.js +145 -0
- package/dist/nosql/meilisearch/index.js +154 -0
- package/dist/nosql/memcached/index.js +223 -0
- package/dist/nosql/milvus/index.js +410 -0
- package/dist/nosql/minio/index.js +265 -0
- package/dist/nosql/momento/index.js +179 -0
- package/dist/nosql/mongodb/index.js +461 -0
- package/dist/nosql/nats/index.js +247 -0
- package/dist/nosql/nedb/index.js +164 -0
- package/dist/nosql/neo4j/index.js +450 -0
- package/dist/nosql/neptune/index.js +470 -0
- package/dist/nosql/nsq/index.js +200 -0
- package/dist/nosql/opensearch/index.js +186 -0
- package/dist/nosql/orientdb/index.js +175 -0
- package/dist/nosql/papertrail/index.js +200 -0
- package/dist/nosql/pinecone/index.js +0 -0
- package/dist/nosql/pinot/index.js +133 -0
- package/dist/nosql/pouchdb/index.js +172 -0
- package/dist/nosql/prometheus/index.js +174 -0
- package/dist/nosql/provendb/index.js +147 -0
- package/dist/nosql/pubsub/index.js +187 -0
- package/dist/nosql/pulsar/index.js +232 -0
- package/dist/nosql/qdrant/index.js +295 -0
- package/dist/nosql/qldb/index.js +192 -0
- package/dist/nosql/r2/index.js +281 -0
- package/dist/nosql/rabbitmq/index.js +237 -0
- package/dist/nosql/ravendb/index.js +175 -0
- package/dist/nosql/redis/index.js +607 -0
- package/dist/nosql/redpanda/index.js +237 -0
- package/dist/nosql/resque/index.js +203 -0
- package/dist/nosql/rethinkdb/index.js +232 -0
- package/dist/nosql/rocksdb/index.js +152 -0
- package/dist/nosql/rockset/index.js +126 -0
- package/dist/nosql/s3/index.js +298 -0
- package/dist/nosql/scylladb/index.js +178 -0
- package/dist/nosql/signoz/index.js +227 -0
- package/dist/nosql/sns/index.js +201 -0
- package/dist/nosql/solr/index.js +231 -0
- package/dist/nosql/splunk/index.js +227 -0
- package/dist/nosql/sqs/index.js +246 -0
- package/dist/nosql/stardog/index.js +169 -0
- package/dist/nosql/starrocks/index.js +170 -0
- package/dist/nosql/store.js +2 -0
- package/dist/nosql/sumologic/index.js +213 -0
- package/dist/nosql/surrealdb/index.js +179 -0
- package/dist/nosql/terminusdb/index.js +151 -0
- package/dist/nosql/tigergraph/index.js +469 -0
- package/dist/nosql/typesense/index.js +148 -0
- package/dist/nosql/unqlite/index.js +157 -0
- package/dist/nosql/upstash/index.js +167 -0
- package/dist/nosql/vercel-kv/index.js +166 -0
- package/dist/nosql/victoriametrics/index.js +213 -0
- package/dist/nosql/virtuoso/index.js +169 -0
- package/dist/nosql/weaviate/index.js +276 -0
- package/dist/operators/index.js +108 -0
- package/dist/operators.js +2690 -0
- package/dist/prisma-migrate/index.js +38 -0
- package/dist/prisma-migrate/migration-generator.js +125 -0
- package/dist/prisma-migrate/model-generator.js +172 -0
- package/dist/prisma-migrate/relations.js +100 -0
- package/dist/prisma-migrate/schema-parser.js +167 -0
- package/dist/prisma-migrate/type-mapper.js +40 -0
- package/dist/prorm.js +6832 -0
- package/dist/query-builders/cte-builder.js +80 -0
- package/dist/query-builders/functions/aggregate.js +390 -0
- package/dist/query-builders/functions/conditional.js +503 -0
- package/dist/query-builders/functions/datetime.js +695 -0
- package/dist/query-builders/functions/fulltext.js +439 -0
- package/dist/query-builders/functions/index.js +93 -0
- package/dist/query-builders/functions/json.js +427 -0
- package/dist/query-builders/functions/math.js +399 -0
- package/dist/query-builders/functions/string.js +518 -0
- package/dist/query-builders/functions/window.js +328 -0
- package/dist/query-builders/include-builder.js +323 -0
- package/dist/query-builders/index-expression-builder.js +242 -0
- package/dist/query-builders/index.js +161 -0
- package/dist/query-builders/insert-builder.js +164 -0
- package/dist/query-builders/model-helpers.js +38 -0
- package/dist/query-builders/order-limit-builder.js +239 -0
- package/dist/query-builders/sql-compiler.js +2040 -0
- package/dist/query-builders/subquery-builder.js +152 -0
- package/dist/query-builders/update-builder.js +182 -0
- package/dist/query-builders/view-builder.js +218 -0
- package/dist/query-builders/where-builder.js +1532 -0
- package/dist/query-interface.js +622 -0
- package/dist/query-optimizers/batch-optimizer.js +426 -0
- package/dist/query-optimizers/explain-plans.js +415 -0
- package/dist/query-optimizers/index.js +51 -0
- package/dist/query-optimizers/prepared-statement-cache.js +423 -0
- package/dist/query-optimizers/query-hints.js +438 -0
- package/dist/query-optimizers/query-optimizer.js +278 -0
- package/dist/query-optimizers/slow-query-logger.js +271 -0
- package/dist/replica-manager.js +507 -0
- package/dist/schema/index.js +15 -0
- package/dist/schema/migration-generator.js +374 -0
- package/dist/schema/schema-differ.js +549 -0
- package/dist/schema/types.js +6 -0
- package/dist/sql-constants.js +300 -0
- package/dist/sqlite-advanced.js +1047 -0
- package/dist/streams/index.js +12 -0
- package/dist/streams/transforms.js +178 -0
- package/dist/transaction.js +456 -0
- package/dist/types/index.js +180 -0
- package/dist/user-management.js +127 -0
- package/dist/utils/date.js +300 -0
- package/dist/utils/index.js +1079 -0
- package/dist/utils/string.js +161 -0
- package/dist/validators/index.js +19 -0
- package/dist/validators/validator.js +911 -0
- 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;
|