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,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HBaseStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Apache HBase store.
|
|
6
|
+
*
|
|
7
|
+
* HBase is a wide-column, sorted-map distributed store built on top of HDFS,
|
|
8
|
+
* modelled on Google's Bigtable paper. Data is addressed by a `(row key,
|
|
9
|
+
* column family, column qualifier, timestamp)` tuple: rows are identified by
|
|
10
|
+
* an arbitrary byte-string row key (kept in sorted order), and each row holds
|
|
11
|
+
* cells grouped into a small, fixed set of column families, with an unbounded
|
|
12
|
+
* number of qualifiers per family created on the fly at write time. There is
|
|
13
|
+
* no fixed schema beyond the family list, no joins, no secondary indexes, and
|
|
14
|
+
* no arbitrary WHERE filtering — reads are either single-row gets by row key
|
|
15
|
+
* or range scans over the sorted key space. None of that fits the SQL-shaped
|
|
16
|
+
* `Dialect` interface (`src/dialects/dialect.ts`), so this store implements
|
|
17
|
+
* the minimal `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes
|
|
18
|
+
* HBase's own row/cell operations directly.
|
|
19
|
+
*
|
|
20
|
+
* Built on the `hbase` npm package (an HBase Stargate / REST-gateway client).
|
|
21
|
+
* That driver exposes a fluent surface — `client.table(name).row(key).put(...)`
|
|
22
|
+
* and `client.table(name).scan(...)` — with Node-style `(err, result)`
|
|
23
|
+
* callbacks. This store assumes that shape and promisifies each call. The
|
|
24
|
+
* driver is an optional peer dependency loaded lazily inside `connect()` (via
|
|
25
|
+
* `require`) so importing this module never forces the driver to be installed;
|
|
26
|
+
* tests inject a pre-built mock `client` instead.
|
|
27
|
+
*
|
|
28
|
+
* Assumed driver call surface (from the `hbase` REST client):
|
|
29
|
+
* client.table(name).create({ ColumnSchema: [{ name }, ...] }, cb)
|
|
30
|
+
* client.table(name).row(key).put(column, value, cb) // single cell
|
|
31
|
+
* client.table(name).row(key).put(columns, values, cb) // multi cell
|
|
32
|
+
* client.table(name).row(key).get(cb) // -> cells
|
|
33
|
+
* client.table(name).row(key).delete(cb)
|
|
34
|
+
* client.table(name).scan(options, cb) // -> rows
|
|
35
|
+
* A cell/column is addressed as `'family:qualifier'`, matching HBase's own
|
|
36
|
+
* column naming.
|
|
37
|
+
*/
|
|
38
|
+
const errors_1 = require("../../errors");
|
|
39
|
+
/**
|
|
40
|
+
* `HBaseStore` wraps an `hbase` REST-gateway client and exposes HBase's
|
|
41
|
+
* row/cell surface: `put`/`get`/`deleteRow` for single-row operations, `scan`
|
|
42
|
+
* for range reads over the sorted key space, and `createTable` for defining a
|
|
43
|
+
* table's column families. Column cells are addressed as `'family:qualifier'`.
|
|
44
|
+
*/
|
|
45
|
+
class HBaseStore {
|
|
46
|
+
constructor(options = {}) {
|
|
47
|
+
this.name = 'hbase';
|
|
48
|
+
this.library = 'hbase';
|
|
49
|
+
this.client = null;
|
|
50
|
+
this.connected = false;
|
|
51
|
+
this.options = options;
|
|
52
|
+
}
|
|
53
|
+
// ---------------------------------------------------------------------
|
|
54
|
+
// NoSqlStore lifecycle
|
|
55
|
+
// ---------------------------------------------------------------------
|
|
56
|
+
async connect() {
|
|
57
|
+
if (this.connected && this.client) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
let client = this.options.client;
|
|
62
|
+
if (!client) {
|
|
63
|
+
// Lazy-load the optional driver so importing this module never
|
|
64
|
+
// requires `hbase` to be installed. Tests inject a mock `client`
|
|
65
|
+
// above and never reach this branch.
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
67
|
+
const hbase = require('hbase');
|
|
68
|
+
client = hbase({
|
|
69
|
+
host: this.options.host,
|
|
70
|
+
port: this.options.port,
|
|
71
|
+
...this.options.clientOptions,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
this.client = client;
|
|
75
|
+
this.connected = true;
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
this.client = null;
|
|
79
|
+
this.connected = false;
|
|
80
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
81
|
+
throw new errors_1.ConnectionError(`Unable to connect to HBase: ${parent.message}`, {
|
|
82
|
+
parent,
|
|
83
|
+
database: 'hbase',
|
|
84
|
+
host: this.options.host,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The `hbase` REST client is stateless (each call is an HTTP request), so
|
|
90
|
+
* there is no socket to tear down; `disconnect()` simply drops the reference
|
|
91
|
+
* and flips `connected` to false.
|
|
92
|
+
*/
|
|
93
|
+
async disconnect() {
|
|
94
|
+
this.client = null;
|
|
95
|
+
this.connected = false;
|
|
96
|
+
}
|
|
97
|
+
isConnected() {
|
|
98
|
+
return this.connected && this.client !== null;
|
|
99
|
+
}
|
|
100
|
+
/** Returns the underlying `hbase` client for anything not wrapped here. */
|
|
101
|
+
getClient() {
|
|
102
|
+
return this.requireClient();
|
|
103
|
+
}
|
|
104
|
+
requireClient() {
|
|
105
|
+
if (!this.client || !this.connected) {
|
|
106
|
+
throw new errors_1.ConnectionError('HBase client is not connected. Call connect() first.', {
|
|
107
|
+
database: 'hbase',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return this.client;
|
|
111
|
+
}
|
|
112
|
+
wrapError(action, err) {
|
|
113
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
114
|
+
return errors_1.DatabaseError.from(parent, { message: `HBase ${action} failed: ${parent.message}` });
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------
|
|
117
|
+
// Row / cell operations
|
|
118
|
+
// ---------------------------------------------------------------------
|
|
119
|
+
/**
|
|
120
|
+
* Writes (puts) one or more cells into a single row. `data` maps
|
|
121
|
+
* `'family:qualifier'` column keys to values, e.g.
|
|
122
|
+
* `{ 'cf:name': 'alice', 'cf:age': 30 }`. Passed to the driver as parallel
|
|
123
|
+
* `columns`/`values` arrays via `table(table).row(row).put(...)`.
|
|
124
|
+
*/
|
|
125
|
+
async put(table, row, data) {
|
|
126
|
+
const client = this.requireClient();
|
|
127
|
+
const columns = Object.keys(data);
|
|
128
|
+
if (columns.length === 0) {
|
|
129
|
+
throw new errors_1.DatabaseError('put() requires at least one column', {
|
|
130
|
+
original: 'empty put data',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const values = columns.map((c) => data[c]);
|
|
134
|
+
try {
|
|
135
|
+
return await new Promise((resolve, reject) => {
|
|
136
|
+
client
|
|
137
|
+
.table(table)
|
|
138
|
+
.row(row)
|
|
139
|
+
.put(columns, values, (err, result) => err ? reject(err) : resolve(result));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
throw this.wrapError(`put on '${table}' row '${row}'`, err);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Reads a single row by key via `table(table).row(row).get(...)`, returning
|
|
148
|
+
* the row's cells as the driver surfaces them (an array of
|
|
149
|
+
* `{ column, timestamp, $ }` cell descriptors for the `hbase` REST client).
|
|
150
|
+
*/
|
|
151
|
+
async get(table, row) {
|
|
152
|
+
const client = this.requireClient();
|
|
153
|
+
try {
|
|
154
|
+
return await new Promise((resolve, reject) => {
|
|
155
|
+
client
|
|
156
|
+
.table(table)
|
|
157
|
+
.row(row)
|
|
158
|
+
.get((err, cells) => (err ? reject(err) : resolve(cells)));
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
throw this.wrapError(`get on '${table}' row '${row}'`, err);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/** Deletes an entire row (all its cells) via `table(table).row(row).delete(...)`. */
|
|
166
|
+
async deleteRow(table, row) {
|
|
167
|
+
const client = this.requireClient();
|
|
168
|
+
try {
|
|
169
|
+
return await new Promise((resolve, reject) => {
|
|
170
|
+
client
|
|
171
|
+
.table(table)
|
|
172
|
+
.row(row)
|
|
173
|
+
.delete((err, result) => (err ? reject(err) : resolve(result)));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
throw this.wrapError(`deleteRow on '${table}' row '${row}'`, err);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Range-scans a table via `table(table).scan(options, ...)`, returning the
|
|
182
|
+
* matching rows. Since HBase keeps row keys sorted, `startRow`/`endRow`
|
|
183
|
+
* define an efficient contiguous range; `columns` restricts which families/
|
|
184
|
+
* qualifiers are read. Returns the rows as the driver surfaces them.
|
|
185
|
+
*/
|
|
186
|
+
async scan(table, opts = {}) {
|
|
187
|
+
const client = this.requireClient();
|
|
188
|
+
try {
|
|
189
|
+
return await new Promise((resolve, reject) => {
|
|
190
|
+
client
|
|
191
|
+
.table(table)
|
|
192
|
+
.scan(opts, (err, rows) => (err ? reject(err) : resolve(rows)));
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
throw this.wrapError(`scan on '${table}'`, err);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// ---------------------------------------------------------------------
|
|
200
|
+
// Table lifecycle
|
|
201
|
+
// ---------------------------------------------------------------------
|
|
202
|
+
/**
|
|
203
|
+
* Creates a table with the given column families via
|
|
204
|
+
* `table(table).create(...)`. `families` is the list of column family names
|
|
205
|
+
* (e.g. `['cf', 'meta']`); each is sent to the driver as an HBase
|
|
206
|
+
* `ColumnSchema` entry. A table must declare its families up front — unlike
|
|
207
|
+
* qualifiers, families cannot be added implicitly at write time.
|
|
208
|
+
*/
|
|
209
|
+
async createTable(table, families) {
|
|
210
|
+
const client = this.requireClient();
|
|
211
|
+
if (!families || families.length === 0) {
|
|
212
|
+
throw new errors_1.DatabaseError('createTable() requires at least one column family', {
|
|
213
|
+
original: 'empty families list',
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const schema = { ColumnSchema: families.map((name) => ({ name })) };
|
|
217
|
+
try {
|
|
218
|
+
return await new Promise((resolve, reject) => {
|
|
219
|
+
client
|
|
220
|
+
.table(table)
|
|
221
|
+
.create(schema, (err, result) => err ? reject(err) : resolve(result));
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
throw this.wrapError(`createTable '${table}'`, err);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
exports.HBaseStore = HBaseStore;
|
|
230
|
+
exports.default = HBaseStore;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Apache Ignite store implementation.
|
|
4
|
+
*
|
|
5
|
+
* Apache Ignite is a distributed in-memory data grid / database. Data lives
|
|
6
|
+
* in distributed key/value caches partitioned across cluster nodes, accessed
|
|
7
|
+
* here via Ignite's thin-client protocol. Although Ignite also speaks SQL,
|
|
8
|
+
* this store targets its distributed-cache (key/value grid) surface, which
|
|
9
|
+
* does not fit the SQL-shaped `Dialect` interface, so it implements the
|
|
10
|
+
* minimal `NoSqlStore` marker interface and exposes cache operations
|
|
11
|
+
* (getCache/put/get/removeKey/getKeys/getSize) as a typed, promise-based API.
|
|
12
|
+
*
|
|
13
|
+
* Uses the `apache-ignite-client` driver (the official Node.js thin client).
|
|
14
|
+
* The driver is loaded lazily inside `connect()` (or supplied pre-built via
|
|
15
|
+
* the `client` option) so importing this module never requires
|
|
16
|
+
* `apache-ignite-client` to be installed unless an Ignite store is actually
|
|
17
|
+
* connected. Tests inject a mock client this way.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.IgniteStore = exports.IGNITE_DB = void 0;
|
|
21
|
+
const errors_1 = require("../../errors");
|
|
22
|
+
/** Slug + human label for error/message context. Shared with `GridGainStore`. */
|
|
23
|
+
exports.IGNITE_DB = 'ignite';
|
|
24
|
+
function wrapConnectionError(err, database = exports.IGNITE_DB, label = 'Ignite') {
|
|
25
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
26
|
+
const message = /econnrefused/i.test(parent.message)
|
|
27
|
+
? 'Connection refused'
|
|
28
|
+
: `Unable to connect to ${label}: ${parent.message}`;
|
|
29
|
+
return new errors_1.ConnectionError(message, { parent, database });
|
|
30
|
+
}
|
|
31
|
+
function wrapDatabaseError(err, action, label = 'Ignite') {
|
|
32
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
33
|
+
return errors_1.DatabaseError.from(parent, { message: `${label} ${action} failed: ${parent.message}` });
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* `IgniteStore` wraps an `apache-ignite-client` `IgniteClient` and exposes
|
|
37
|
+
* its distributed-cache operations as a typed, promise-based API.
|
|
38
|
+
*/
|
|
39
|
+
class IgniteStore {
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.name = 'ignite';
|
|
42
|
+
this.library = 'apache-ignite-client';
|
|
43
|
+
this.database = exports.IGNITE_DB;
|
|
44
|
+
this.label = 'Ignite';
|
|
45
|
+
this.client = null;
|
|
46
|
+
this.connected = false;
|
|
47
|
+
/** Resolved `CacheClient` handles, cached by name so `getMap` is idempotent. */
|
|
48
|
+
this.caches = new Map();
|
|
49
|
+
this.options = options;
|
|
50
|
+
}
|
|
51
|
+
// ---------------------------------------------------------------------
|
|
52
|
+
// Connection lifecycle
|
|
53
|
+
// ---------------------------------------------------------------------
|
|
54
|
+
async connect() {
|
|
55
|
+
if (this.connected && this.client) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
if (this.options.client) {
|
|
60
|
+
this.client = this.options.client;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
64
|
+
const mod = require('apache-ignite-client');
|
|
65
|
+
const IgniteClient = mod.IgniteClient ?? mod;
|
|
66
|
+
const IgniteClientConfiguration = mod.IgniteClientConfiguration;
|
|
67
|
+
const client = new IgniteClient();
|
|
68
|
+
const endpoints = this.options.endpoints ?? ['127.0.0.1:10800'];
|
|
69
|
+
const cfg = new IgniteClientConfiguration(...endpoints);
|
|
70
|
+
await client.connect(cfg);
|
|
71
|
+
this.client = client;
|
|
72
|
+
}
|
|
73
|
+
this.connected = true;
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
this.client = null;
|
|
77
|
+
this.connected = false;
|
|
78
|
+
throw wrapConnectionError(err, this.database, this.label);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async disconnect() {
|
|
82
|
+
if (this.client) {
|
|
83
|
+
try {
|
|
84
|
+
await this.client.disconnect();
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// best-effort disconnect
|
|
88
|
+
}
|
|
89
|
+
this.client = null;
|
|
90
|
+
}
|
|
91
|
+
this.caches.clear();
|
|
92
|
+
this.connected = false;
|
|
93
|
+
}
|
|
94
|
+
isConnected() {
|
|
95
|
+
return this.connected && this.client !== null;
|
|
96
|
+
}
|
|
97
|
+
/** Returns the underlying `apache-ignite-client` client for anything not wrapped here. */
|
|
98
|
+
getClient() {
|
|
99
|
+
return this.requireClient();
|
|
100
|
+
}
|
|
101
|
+
requireClient() {
|
|
102
|
+
if (!this.client) {
|
|
103
|
+
throw new errors_1.ConnectionError(`Not connected to ${this.label}`, { database: this.database });
|
|
104
|
+
}
|
|
105
|
+
return this.client;
|
|
106
|
+
}
|
|
107
|
+
// ---------------------------------------------------------------------
|
|
108
|
+
// Distributed cache operations
|
|
109
|
+
// ---------------------------------------------------------------------
|
|
110
|
+
/** Resolve (and cache) a distributed cache handle by name. */
|
|
111
|
+
async getMap(name) {
|
|
112
|
+
const cached = this.caches.get(name);
|
|
113
|
+
if (cached) {
|
|
114
|
+
return cached;
|
|
115
|
+
}
|
|
116
|
+
const client = this.requireClient();
|
|
117
|
+
try {
|
|
118
|
+
const cache = await client.getCache(name);
|
|
119
|
+
this.caches.set(name, cache);
|
|
120
|
+
return cache;
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
throw wrapDatabaseError(err, 'getCache', this.label);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Put `value` under `key` in `map` (an Ignite cache handle). */
|
|
127
|
+
async mapPut(map, key, value) {
|
|
128
|
+
try {
|
|
129
|
+
return await map.put(key, value);
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
throw wrapDatabaseError(err, 'cache put', this.label);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Get the value stored under `key` in `map` (or null if absent). */
|
|
136
|
+
async mapGet(map, key) {
|
|
137
|
+
try {
|
|
138
|
+
return await map.get(key);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
throw wrapDatabaseError(err, 'cache get', this.label);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/** Remove `key` from `map`. Returns Ignite's boolean success flag. */
|
|
145
|
+
async mapRemove(map, key) {
|
|
146
|
+
try {
|
|
147
|
+
return await map.removeKey(key);
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
throw wrapDatabaseError(err, 'cache removeKey', this.label);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Return all keys currently in `map` as an array. */
|
|
154
|
+
async mapKeys(map) {
|
|
155
|
+
try {
|
|
156
|
+
return await map.getKeys();
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
throw wrapDatabaseError(err, 'cache getKeys', this.label);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** Return the number of entries in `map`. */
|
|
163
|
+
async mapSize(map) {
|
|
164
|
+
try {
|
|
165
|
+
return await map.getSize();
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
throw wrapDatabaseError(err, 'cache getSize', this.label);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
exports.IgniteStore = IgniteStore;
|
|
173
|
+
exports.default = IgniteStore;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* immudb store implementation.
|
|
4
|
+
*
|
|
5
|
+
* immudb is an immutable, append-only key-value (and SQL) database with
|
|
6
|
+
* built-in cryptographic verification: every write is added to a tamper-
|
|
7
|
+
* evident Merkle-tree-backed log, and `verifiedSet`/`verifiedGet` return an
|
|
8
|
+
* inclusion/consistency proof the client checks locally, so a compromised
|
|
9
|
+
* server cannot lie about stored data without detection.
|
|
10
|
+
*
|
|
11
|
+
* immudb is a key-value ledger, not a SQL `Dialect`, so this class implements
|
|
12
|
+
* the minimal `NoSqlStore` marker interface plus the shared ledger surface
|
|
13
|
+
* (`append`/`get`/`history`/`verify`/`query`). Because immudb addresses
|
|
14
|
+
* records by key rather than by (table, row), `append`/`get`/`history`/
|
|
15
|
+
* `verify` treat their first argument as a key namespace and compose the
|
|
16
|
+
* immudb key as `<table>:<id>` (or just `<table>` when no id is given).
|
|
17
|
+
* `query` maps to immudb's embedded SQL engine (`sqlQuery`/`sqlExec`).
|
|
18
|
+
*
|
|
19
|
+
* ## Lazy driver loading
|
|
20
|
+
*
|
|
21
|
+
* The `immudb-node` package is loaded lazily inside `connect()`; importing
|
|
22
|
+
* this module never requires it. Tests inject a pre-built, already-logged-in
|
|
23
|
+
* client via `ImmudbStoreOptions.client`, bypassing the `require`.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.ImmudbStore = void 0;
|
|
27
|
+
const errors_1 = require("../../errors");
|
|
28
|
+
/**
|
|
29
|
+
* `ImmudbStore` wraps an `immudb-node` client behind the shared ledger
|
|
30
|
+
* surface. `append` performs a `verifiedSet` (returning the write's
|
|
31
|
+
* transaction id), `get` a `verifiedGet`, `history` returns prior revisions
|
|
32
|
+
* of a key, `verify` returns the full verified-read response (value + proof),
|
|
33
|
+
* and `query` runs embedded SQL via `sqlQuery`.
|
|
34
|
+
*/
|
|
35
|
+
class ImmudbStore {
|
|
36
|
+
constructor(options = {}) {
|
|
37
|
+
this.name = 'immudb';
|
|
38
|
+
this.library = 'immudb-node';
|
|
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 mod = require('immudb-node');
|
|
57
|
+
const ImmudbClient = mod.default ?? mod.ImmudbClient ?? mod;
|
|
58
|
+
this.client = new ImmudbClient({
|
|
59
|
+
host: this.options.host ?? '127.0.0.1',
|
|
60
|
+
port: this.options.port ?? 3322,
|
|
61
|
+
});
|
|
62
|
+
if (typeof this.client.login === 'function') {
|
|
63
|
+
await this.client.login({
|
|
64
|
+
user: this.options.user ?? 'immudb',
|
|
65
|
+
password: this.options.password ?? 'immudb',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (this.options.database && typeof this.client.useDatabase === 'function') {
|
|
69
|
+
await this.client.useDatabase({ databasename: this.options.database });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
this.connected = true;
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
this.client = null;
|
|
76
|
+
this.connected = false;
|
|
77
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
78
|
+
throw new errors_1.ConnectionError(`Unable to connect to immudb: ${parent.message}`, {
|
|
79
|
+
parent,
|
|
80
|
+
database: 'immudb',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async disconnect() {
|
|
85
|
+
if (this.client) {
|
|
86
|
+
try {
|
|
87
|
+
if (typeof this.client.close === 'function')
|
|
88
|
+
await this.client.close();
|
|
89
|
+
else if (typeof this.client.shutdown === 'function')
|
|
90
|
+
await this.client.shutdown();
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// best-effort close
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
this.client = null;
|
|
97
|
+
this.connected = false;
|
|
98
|
+
}
|
|
99
|
+
isConnected() {
|
|
100
|
+
return this.connected && this.client !== null;
|
|
101
|
+
}
|
|
102
|
+
/** Returns the underlying `immudb-node` client for anything not wrapped here. */
|
|
103
|
+
getClient() {
|
|
104
|
+
return this.requireClient();
|
|
105
|
+
}
|
|
106
|
+
requireClient() {
|
|
107
|
+
if (!this.client || !this.connected) {
|
|
108
|
+
throw new errors_1.ConnectionError('Not connected to immudb. Call connect() first.', {
|
|
109
|
+
database: 'immudb',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return this.client;
|
|
113
|
+
}
|
|
114
|
+
/** Compose the immudb key from a (table, id) address. */
|
|
115
|
+
keyFor(table, id) {
|
|
116
|
+
return id === undefined || id === null || id === '' ? table : `${table}:${id}`;
|
|
117
|
+
}
|
|
118
|
+
encode(data) {
|
|
119
|
+
return typeof data === 'string' ? data : JSON.stringify(data);
|
|
120
|
+
}
|
|
121
|
+
async run(action, fn) {
|
|
122
|
+
this.requireClient();
|
|
123
|
+
try {
|
|
124
|
+
return await fn();
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
128
|
+
throw errors_1.DatabaseError.from(parent, { message: `immudb ${action} failed: ${parent.message}` });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------
|
|
132
|
+
// Ledger surface
|
|
133
|
+
// ---------------------------------------------------------------------
|
|
134
|
+
/**
|
|
135
|
+
* Append `data` under the key `<table>:<data.id>` (or `<table>` if `data`
|
|
136
|
+
* has no `id`) via a verified, tamper-evident write. Returns the write's
|
|
137
|
+
* transaction id/hash from immudb's response.
|
|
138
|
+
*/
|
|
139
|
+
async append(table, data) {
|
|
140
|
+
const id = data?.id;
|
|
141
|
+
const key = this.keyFor(table, id === undefined ? undefined : String(id));
|
|
142
|
+
const client = this.requireClient();
|
|
143
|
+
const res = await this.run('append', () => client.verifiedSet({ key, value: this.encode(data) }));
|
|
144
|
+
return String(res?.transactionId ?? res?.id ?? res?.txId ?? res?.tx ?? key);
|
|
145
|
+
}
|
|
146
|
+
/** Verified read of the current value at `<table>:<id>` (or `<table>`). */
|
|
147
|
+
async get(table, id) {
|
|
148
|
+
const client = this.requireClient();
|
|
149
|
+
return this.run('get', () => client.verifiedGet({ key: this.keyFor(table, id) }));
|
|
150
|
+
}
|
|
151
|
+
/** Return every prior revision of the key `<table>:<id>` (or `<table>`). */
|
|
152
|
+
async history(table, id) {
|
|
153
|
+
const client = this.requireClient();
|
|
154
|
+
return this.run('history', () => client.history({ key: this.keyFor(table, id) }));
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Verified read returning the full response - value plus the cryptographic
|
|
158
|
+
* inclusion proof immudb generates for `verifiedGet`. The presence of a
|
|
159
|
+
* resolved response (rather than a thrown verification error) is the proof
|
|
160
|
+
* that the value is consistent with the tamper-evident log.
|
|
161
|
+
*/
|
|
162
|
+
async verify(table, id) {
|
|
163
|
+
const client = this.requireClient();
|
|
164
|
+
return this.run('verify', () => client.verifiedGet({ key: this.keyFor(table, id) }));
|
|
165
|
+
}
|
|
166
|
+
/** Run a SQL `statement` against immudb's embedded SQL engine (`sqlQuery`). */
|
|
167
|
+
async query(statement, params) {
|
|
168
|
+
const client = this.requireClient();
|
|
169
|
+
if (typeof client.sqlQuery !== 'function') {
|
|
170
|
+
throw new errors_1.DatabaseError('immudb client does not support sqlQuery()', { code: 'QUERY_ERROR' });
|
|
171
|
+
}
|
|
172
|
+
return this.run('query', () => client.sqlQuery({ sql: statement, params }));
|
|
173
|
+
}
|
|
174
|
+
/** Execute a SQL DDL/DML `statement` via `sqlExec` (no rows returned). */
|
|
175
|
+
async exec(statement, params) {
|
|
176
|
+
const client = this.requireClient();
|
|
177
|
+
if (typeof client.sqlExec !== 'function') {
|
|
178
|
+
throw new errors_1.DatabaseError('immudb client does not support sqlExec()', { code: 'QUERY_ERROR' });
|
|
179
|
+
}
|
|
180
|
+
return this.run('exec', () => client.sqlExec({ sql: statement, params }));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.ImmudbStore = ImmudbStore;
|
|
184
|
+
exports.default = ImmudbStore;
|