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,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenSearch store implementation.
|
|
4
|
+
*
|
|
5
|
+
* OpenSearch is a distributed document store forked from Elasticsearch 7.10.
|
|
6
|
+
* Like Elasticsearch it is built around an inverted index and a JSON-based
|
|
7
|
+
* Query DSL (`match`/`term`/`bool`/`range` queries, aggregations, sorting)
|
|
8
|
+
* rather than SQL: no `JOIN`, no transaction log, schema-flexible documents.
|
|
9
|
+
* It therefore does not fit the SQL-shaped `Dialect` interface used by the
|
|
10
|
+
* SQL dialects in this repo. Instead it implements the minimal `NoSqlStore`
|
|
11
|
+
* marker interface (`src/nosql/store.ts`) and exposes OpenSearch's real
|
|
12
|
+
* capabilities grouped by concern: connection lifecycle, index management,
|
|
13
|
+
* document CRUD (single + bulk), and search.
|
|
14
|
+
*
|
|
15
|
+
* Uses the official `@opensearch-project/opensearch` driver. The driver is
|
|
16
|
+
* loaded lazily via `require` so importing this module does not force the
|
|
17
|
+
* dependency to be resolved unless an OpenSearch store is actually
|
|
18
|
+
* constructed. For unit-testing without a live cluster, the constructor also
|
|
19
|
+
* accepts an already-built `client`, which `connect()` will use as-is instead
|
|
20
|
+
* of instantiating a new one.
|
|
21
|
+
*
|
|
22
|
+
* Note: the OpenSearch client wraps every response in an envelope and puts
|
|
23
|
+
* the actual payload under `.body` (`{ body, statusCode, headers, meta }`),
|
|
24
|
+
* so each wrapper here reads through `response.body`.
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.OpenSearchStore = void 0;
|
|
28
|
+
const errors_1 = require("../../errors");
|
|
29
|
+
function wrapConnectionError(err, node) {
|
|
30
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
31
|
+
const message = /econnrefused/i.test(parent.message)
|
|
32
|
+
? 'Connection refused'
|
|
33
|
+
: `Unable to connect to OpenSearch: ${parent.message}`;
|
|
34
|
+
return new errors_1.ConnectionError(message, {
|
|
35
|
+
parent,
|
|
36
|
+
database: 'opensearch',
|
|
37
|
+
host: typeof node === 'string' ? node : undefined,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function wrapDatabaseError(err, message) {
|
|
41
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
42
|
+
const statusCode = err?.meta?.statusCode;
|
|
43
|
+
const detail = statusCode ? `${parent.message} (HTTP ${statusCode})` : parent.message;
|
|
44
|
+
const combined = message ? `${message}: ${detail}` : detail;
|
|
45
|
+
return errors_1.DatabaseError.from(parent, { message: combined });
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `OpenSearchStore` wraps the official `@opensearch-project/opensearch`
|
|
49
|
+
* client and exposes index management, document CRUD (single + bulk), and
|
|
50
|
+
* Query-DSL search as a typed, promise-based API.
|
|
51
|
+
*/
|
|
52
|
+
class OpenSearchStore {
|
|
53
|
+
constructor(options) {
|
|
54
|
+
this.name = 'opensearch';
|
|
55
|
+
this.library = '@opensearch-project/opensearch';
|
|
56
|
+
this.client = null;
|
|
57
|
+
this.connected = false;
|
|
58
|
+
this.options = options;
|
|
59
|
+
}
|
|
60
|
+
// ---------------------------------------------------------------------
|
|
61
|
+
// Connection lifecycle
|
|
62
|
+
// ---------------------------------------------------------------------
|
|
63
|
+
async connect() {
|
|
64
|
+
if (this.connected && this.client) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let client = this.options.client;
|
|
68
|
+
if (!client) {
|
|
69
|
+
// Lazy-load the driver so importing this module doesn't require the
|
|
70
|
+
// dependency to be present unless a store is actually constructed.
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
72
|
+
const { Client } = require('@opensearch-project/opensearch');
|
|
73
|
+
client = new Client({
|
|
74
|
+
node: this.options.node,
|
|
75
|
+
nodes: this.options.nodes,
|
|
76
|
+
auth: this.options.auth,
|
|
77
|
+
ssl: this.options.ssl,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
// The driver connects lazily on first request; `ping()` surfaces
|
|
82
|
+
// connection failures (bad host, refused connection, TLS errors)
|
|
83
|
+
// immediately instead of on the caller's first real operation.
|
|
84
|
+
await client.ping();
|
|
85
|
+
this.client = client;
|
|
86
|
+
this.connected = true;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
await client.close?.().catch?.(() => undefined);
|
|
90
|
+
this.client = null;
|
|
91
|
+
this.connected = false;
|
|
92
|
+
throw wrapConnectionError(err, this.options.node);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async disconnect() {
|
|
96
|
+
if (this.client) {
|
|
97
|
+
await this.client.close();
|
|
98
|
+
this.client = null;
|
|
99
|
+
}
|
|
100
|
+
this.connected = false;
|
|
101
|
+
}
|
|
102
|
+
isConnected() {
|
|
103
|
+
return this.connected && this.client !== null;
|
|
104
|
+
}
|
|
105
|
+
/** Returns the underlying `@opensearch-project/opensearch` client for anything not wrapped here. */
|
|
106
|
+
getClient() {
|
|
107
|
+
return this.requireClient();
|
|
108
|
+
}
|
|
109
|
+
requireClient() {
|
|
110
|
+
if (!this.client) {
|
|
111
|
+
throw new errors_1.ConnectionError('Not connected to OpenSearch', { database: 'opensearch' });
|
|
112
|
+
}
|
|
113
|
+
return this.client;
|
|
114
|
+
}
|
|
115
|
+
async exec(fn, action) {
|
|
116
|
+
const client = this.requireClient();
|
|
117
|
+
try {
|
|
118
|
+
return await fn(client);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
throw wrapDatabaseError(err, `OpenSearch ${action} failed`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// ---------------------------------------------------------------------
|
|
125
|
+
// Index management
|
|
126
|
+
// ---------------------------------------------------------------------
|
|
127
|
+
/** Create an index, optionally with a body (mappings/settings/aliases). */
|
|
128
|
+
async createIndex(index, body) {
|
|
129
|
+
await this.exec((c) => c.indices.create({ index, body }), 'CREATE INDEX');
|
|
130
|
+
}
|
|
131
|
+
/** Delete an index. */
|
|
132
|
+
async deleteIndex(index) {
|
|
133
|
+
await this.exec((c) => c.indices.delete({ index }), 'DELETE INDEX');
|
|
134
|
+
}
|
|
135
|
+
/** Whether an index exists. */
|
|
136
|
+
async indexExists(index) {
|
|
137
|
+
const response = await this.exec((c) => c.indices.exists({ index }), 'INDICES EXISTS');
|
|
138
|
+
return response.body ?? false;
|
|
139
|
+
}
|
|
140
|
+
// ---------------------------------------------------------------------
|
|
141
|
+
// Document CRUD
|
|
142
|
+
// ---------------------------------------------------------------------
|
|
143
|
+
/** Index (create or overwrite) a document under an explicit `id`. */
|
|
144
|
+
async indexDocument(index, id, body) {
|
|
145
|
+
const response = await this.exec((c) => c.index({ index, id, body }), 'INDEX');
|
|
146
|
+
return response.body;
|
|
147
|
+
}
|
|
148
|
+
/** Get a document's `_source` by ID. */
|
|
149
|
+
async get(index, id) {
|
|
150
|
+
const response = await this.exec((c) => c.get({ index, id }), 'GET');
|
|
151
|
+
return response.body?._source;
|
|
152
|
+
}
|
|
153
|
+
/** Run a Query-DSL search and return the `hits` object from the response. */
|
|
154
|
+
async search(index, query) {
|
|
155
|
+
const response = await this.exec((c) => c.search({ index, body: query }), 'SEARCH');
|
|
156
|
+
return response.body?.hits;
|
|
157
|
+
}
|
|
158
|
+
/** Delete a document by ID. */
|
|
159
|
+
async deleteDocument(index, id) {
|
|
160
|
+
const response = await this.exec((c) => c.delete({ index, id }), 'DELETE');
|
|
161
|
+
return response.body;
|
|
162
|
+
}
|
|
163
|
+
// ---------------------------------------------------------------------
|
|
164
|
+
// Bulk operations
|
|
165
|
+
// ---------------------------------------------------------------------
|
|
166
|
+
/**
|
|
167
|
+
* Run a batch of operations (already in the driver's NDJSON action/source
|
|
168
|
+
* array form) in a single request. The real `_bulk` API rejects an empty
|
|
169
|
+
* request body outright, so short-circuit zero operations to a trivial
|
|
170
|
+
* no-op result rather than surfacing that as an error.
|
|
171
|
+
*/
|
|
172
|
+
async bulk(operations) {
|
|
173
|
+
if (operations.length === 0) {
|
|
174
|
+
return { errors: false, items: [], took: 0 };
|
|
175
|
+
}
|
|
176
|
+
const response = await this.exec((c) => c.bulk({ body: operations }), 'BULK');
|
|
177
|
+
const bodyResult = response.body;
|
|
178
|
+
return {
|
|
179
|
+
errors: bodyResult.errors,
|
|
180
|
+
items: bodyResult.items ?? [],
|
|
181
|
+
took: bodyResult.took ?? 0,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.OpenSearchStore = OpenSearchStore;
|
|
186
|
+
exports.default = OpenSearchStore;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OrientDB store implementation for the Prorm NoSQL layer.
|
|
4
|
+
*
|
|
5
|
+
* OrientDB is a multi-model database combining document, graph, key/value and
|
|
6
|
+
* object models, queried with an extended SQL dialect over a session. While
|
|
7
|
+
* its query language is SQL-like, it does not fit Prorm's SQL-shaped
|
|
8
|
+
* `Dialect` interface (no shared identifier escaping / DDL builder), so this
|
|
9
|
+
* class implements the minimal `NoSqlStore` marker interface for connection
|
|
10
|
+
* lifecycle and exposes OrientDB's real session `command`/`query` API through
|
|
11
|
+
* a small document-CRUD convenience layer.
|
|
12
|
+
*
|
|
13
|
+
* Uses the official `orientjs` driver. That driver is an optional peer
|
|
14
|
+
* dependency and is loaded lazily inside `connect()` so importing this module
|
|
15
|
+
* never requires it to be installed. Tests inject a pre-built mock session via
|
|
16
|
+
* `options.client`, which bypasses the lazy `require` entirely - no real
|
|
17
|
+
* driver and no network are needed.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.OrientDbStore = void 0;
|
|
21
|
+
const errors_1 = require("../../errors");
|
|
22
|
+
class OrientDbStore {
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.name = 'orientdb';
|
|
25
|
+
this.library = 'orientjs';
|
|
26
|
+
this.orientClient = null;
|
|
27
|
+
this.session = null;
|
|
28
|
+
this.connected = false;
|
|
29
|
+
this.options = options;
|
|
30
|
+
}
|
|
31
|
+
// ---------------------------------------------------------------------
|
|
32
|
+
// Connection lifecycle
|
|
33
|
+
// ---------------------------------------------------------------------
|
|
34
|
+
async connect() {
|
|
35
|
+
if (this.connected && this.session) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
if (this.options.client) {
|
|
40
|
+
this.session = this.options.client;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
44
|
+
const orientjs = require('orientjs');
|
|
45
|
+
const OrientDBClient = orientjs.OrientDBClient ?? orientjs;
|
|
46
|
+
this.orientClient = await OrientDBClient.connect({
|
|
47
|
+
host: this.options.host,
|
|
48
|
+
port: this.options.port,
|
|
49
|
+
});
|
|
50
|
+
this.session = await this.orientClient.session({
|
|
51
|
+
name: this.options.database,
|
|
52
|
+
username: this.options.username,
|
|
53
|
+
password: this.options.password,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
this.connected = true;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
this.session = null;
|
|
60
|
+
this.orientClient = null;
|
|
61
|
+
this.connected = false;
|
|
62
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
63
|
+
throw new errors_1.ConnectionError(`Unable to connect to OrientDB: ${parent.message}`, {
|
|
64
|
+
parent,
|
|
65
|
+
database: 'orientdb',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async disconnect() {
|
|
70
|
+
try {
|
|
71
|
+
if (this.session && typeof this.session.close === 'function') {
|
|
72
|
+
await this.session.close();
|
|
73
|
+
}
|
|
74
|
+
if (this.orientClient && typeof this.orientClient.close === 'function') {
|
|
75
|
+
await this.orientClient.close();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
throw wrapDatabaseError(err, 'OrientDB disconnect failed');
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
this.session = null;
|
|
83
|
+
this.orientClient = null;
|
|
84
|
+
this.connected = false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
isConnected() {
|
|
88
|
+
return this.connected && this.session !== null;
|
|
89
|
+
}
|
|
90
|
+
getClient() {
|
|
91
|
+
return this.requireSession();
|
|
92
|
+
}
|
|
93
|
+
requireSession() {
|
|
94
|
+
if (!this.session || !this.connected) {
|
|
95
|
+
throw new errors_1.ConnectionError('Not connected to OrientDB. Call connect() first.', {
|
|
96
|
+
database: 'orientdb',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return this.session;
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------
|
|
102
|
+
// Document CRUD (extended SQL)
|
|
103
|
+
// ---------------------------------------------------------------------
|
|
104
|
+
/** Insert a document into `collection` (class); returns its `@rid`/id. */
|
|
105
|
+
async insert(collection, doc) {
|
|
106
|
+
const session = this.requireSession();
|
|
107
|
+
try {
|
|
108
|
+
const sql = `INSERT INTO ${collection} CONTENT ${JSON.stringify(doc)}`;
|
|
109
|
+
const rows = await session.command(sql).all();
|
|
110
|
+
const record = rows?.[0];
|
|
111
|
+
const rid = record?.['@rid'];
|
|
112
|
+
return rid !== undefined ? String(rid) : record?.id;
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
throw wrapDatabaseError(err, 'OrientDB insert failed');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** Fetch a document by `@rid`. */
|
|
119
|
+
async get(collection, id) {
|
|
120
|
+
const session = this.requireSession();
|
|
121
|
+
try {
|
|
122
|
+
const sql = `SELECT FROM ${collection} WHERE @rid = ${id}`;
|
|
123
|
+
const rows = await session.query(sql).all();
|
|
124
|
+
return rows?.[0];
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
throw wrapDatabaseError(err, 'OrientDB get failed');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** Merge `patch` into an existing document identified by `@rid`. */
|
|
131
|
+
async update(collection, id, patch) {
|
|
132
|
+
const session = this.requireSession();
|
|
133
|
+
try {
|
|
134
|
+
const sql = `UPDATE ${collection} MERGE ${JSON.stringify(patch)} WHERE @rid = ${id}`;
|
|
135
|
+
return await session.command(sql).all();
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
throw wrapDatabaseError(err, 'OrientDB update failed');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** Delete a document identified by `@rid`. */
|
|
142
|
+
async delete(collection, id) {
|
|
143
|
+
const session = this.requireSession();
|
|
144
|
+
try {
|
|
145
|
+
const sql = `DELETE FROM ${collection} WHERE @rid = ${id}`;
|
|
146
|
+
return await session.command(sql).all();
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
throw wrapDatabaseError(err, 'OrientDB delete failed');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Run an OrientDB SQL `statement` and return the resulting rows.
|
|
154
|
+
* `options.params` binds parameters into the statement.
|
|
155
|
+
*/
|
|
156
|
+
async query(collection, statement, options = {}) {
|
|
157
|
+
const session = this.requireSession();
|
|
158
|
+
try {
|
|
159
|
+
const rows = await session.query(statement, options).all();
|
|
160
|
+
return rows ?? [];
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
throw wrapDatabaseError(err, 'OrientDB query failed');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.OrientDbStore = OrientDbStore;
|
|
168
|
+
function wrapDatabaseError(err, message) {
|
|
169
|
+
if (err instanceof errors_1.ConnectionError) {
|
|
170
|
+
return err;
|
|
171
|
+
}
|
|
172
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
173
|
+
return errors_1.DatabaseError.from(parent, { message: `${message}: ${parent.message}` });
|
|
174
|
+
}
|
|
175
|
+
exports.default = OrientDbStore;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Papertrail store implementation.
|
|
4
|
+
*
|
|
5
|
+
* Papertrail (by SolarWinds) is a hosted log-management service. Logs are
|
|
6
|
+
* ingested over syslog or an HTTP log destination, and searched via the REST
|
|
7
|
+
* events API. There is no SQL-shaped query surface, no row-level
|
|
8
|
+
* UPDATE/DELETE, and no identifier escaping, so Papertrail does not fit the
|
|
9
|
+
* SQL `Dialect` interface (`src/dialects/dialect.ts`). This class implements
|
|
10
|
+
* the minimal `NoSqlStore` marker interface (`src/nosql/store.ts`) and
|
|
11
|
+
* exposes Papertrail's ingest/search API.
|
|
12
|
+
*
|
|
13
|
+
* ## No canonical driver - HTTP over `fetch`
|
|
14
|
+
*
|
|
15
|
+
* Papertrail has no single canonical npm client; it is an HTTP/JSON API
|
|
16
|
+
* (`X-Papertrail-Token` auth). This store talks to it with the global
|
|
17
|
+
* `fetch` (so `library` is `'fetch'`). For tests (and custom transports) an
|
|
18
|
+
* alternative HTTP client can be injected via `PapertrailStoreOptions.client`.
|
|
19
|
+
*
|
|
20
|
+
* Search targets the REST API (`apiURL`); ingest targets the configured HTTP
|
|
21
|
+
* log destination (`ingestURL`). The internal client resolves absolute URLs
|
|
22
|
+
* verbatim, so `push()` posts to the full ingest URL while search/metadata
|
|
23
|
+
* methods use relative API paths.
|
|
24
|
+
*
|
|
25
|
+
* ## Endpoints wrapped
|
|
26
|
+
*
|
|
27
|
+
* - `push(lines)` -> `POST <ingestURL>` (HTTP/syslog ingest)
|
|
28
|
+
* - `query(q, opts?)` -> `GET /api/v1/events/search` (search events)
|
|
29
|
+
* - `labels()` -> `GET /api/v1/groups` (log groups)
|
|
30
|
+
* - `streams()` -> `GET /api/v1/systems` (systems/senders)
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.PapertrailStore = exports.DEFAULT_PAPERTRAIL_API_URL = void 0;
|
|
34
|
+
exports.createFetchClient = createFetchClient;
|
|
35
|
+
const errors_1 = require("../../errors");
|
|
36
|
+
/** Default Papertrail REST API base URL. */
|
|
37
|
+
exports.DEFAULT_PAPERTRAIL_API_URL = 'https://papertrailapp.com';
|
|
38
|
+
/** Build a `fetch`-backed client for the given base URL. */
|
|
39
|
+
function createFetchClient(baseURL, headers) {
|
|
40
|
+
const buildUrl = (path, params) => {
|
|
41
|
+
// Absolute URLs (the ingest URL) override the base entirely.
|
|
42
|
+
const url = new URL(path, baseURL.endsWith('/') ? baseURL : `${baseURL}/`);
|
|
43
|
+
for (const [key, value] of Object.entries(params ?? {})) {
|
|
44
|
+
if (value === undefined)
|
|
45
|
+
continue;
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
for (const item of value)
|
|
48
|
+
url.searchParams.append(key, item);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
url.searchParams.set(key, value);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return url.toString();
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
async get(path, params) {
|
|
58
|
+
const res = await fetch(buildUrl(path, params), {
|
|
59
|
+
method: 'GET',
|
|
60
|
+
headers: { Accept: 'application/json', ...(headers ?? {}) },
|
|
61
|
+
});
|
|
62
|
+
if (!res.ok)
|
|
63
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
64
|
+
return res.json();
|
|
65
|
+
},
|
|
66
|
+
async post(path, body, contentType) {
|
|
67
|
+
const res = await fetch(buildUrl(path), {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
body,
|
|
70
|
+
headers: { ...(headers ?? {}), ...(contentType ? { 'Content-Type': contentType } : {}) },
|
|
71
|
+
});
|
|
72
|
+
if (!res.ok)
|
|
73
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
74
|
+
const text = await res.text();
|
|
75
|
+
if (!text)
|
|
76
|
+
return undefined;
|
|
77
|
+
try {
|
|
78
|
+
return JSON.parse(text);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return text;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* `PapertrailStore` wraps Papertrail's HTTP log-destination ingest and its
|
|
88
|
+
* REST events-search API (plus group/system metadata) behind the
|
|
89
|
+
* `NoSqlStore` lifecycle.
|
|
90
|
+
*/
|
|
91
|
+
class PapertrailStore {
|
|
92
|
+
constructor(options = {}) {
|
|
93
|
+
this.name = 'papertrail';
|
|
94
|
+
this.library = 'fetch';
|
|
95
|
+
this.client = null;
|
|
96
|
+
this.connected = false;
|
|
97
|
+
this.apiURL = options.apiURL ?? exports.DEFAULT_PAPERTRAIL_API_URL;
|
|
98
|
+
this.ingestURL = options.ingestURL;
|
|
99
|
+
this.injectedClient = options.client;
|
|
100
|
+
this.headers = {
|
|
101
|
+
...(options.headers ?? {}),
|
|
102
|
+
...(options.token ? { 'X-Papertrail-Token': options.token } : {}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------
|
|
106
|
+
// Connection lifecycle
|
|
107
|
+
// ---------------------------------------------------------------------
|
|
108
|
+
async connect() {
|
|
109
|
+
if (this.connected && this.client)
|
|
110
|
+
return;
|
|
111
|
+
this.client = this.injectedClient ?? createFetchClient(this.apiURL, this.headers);
|
|
112
|
+
this.connected = true;
|
|
113
|
+
}
|
|
114
|
+
async disconnect() {
|
|
115
|
+
this.client = null;
|
|
116
|
+
this.connected = false;
|
|
117
|
+
}
|
|
118
|
+
isConnected() {
|
|
119
|
+
return this.connected && this.client !== null;
|
|
120
|
+
}
|
|
121
|
+
/** Returns the underlying (internal or injected) HTTP client. */
|
|
122
|
+
getClient() {
|
|
123
|
+
return this.requireClient();
|
|
124
|
+
}
|
|
125
|
+
requireClient() {
|
|
126
|
+
if (!this.client) {
|
|
127
|
+
throw new errors_1.ConnectionError('Not connected to Papertrail', {
|
|
128
|
+
database: 'papertrail',
|
|
129
|
+
host: this.apiURL,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return this.client;
|
|
133
|
+
}
|
|
134
|
+
async doGet(path, params, action) {
|
|
135
|
+
const client = this.requireClient();
|
|
136
|
+
try {
|
|
137
|
+
return await client.get(path, params);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
141
|
+
throw errors_1.DatabaseError.from(parent, {
|
|
142
|
+
message: `Papertrail ${action ?? 'request'} failed: ${parent.message}`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// ---------------------------------------------------------------------
|
|
147
|
+
// Ingest (HTTP log destination)
|
|
148
|
+
// ---------------------------------------------------------------------
|
|
149
|
+
/**
|
|
150
|
+
* Ingests raw log lines by POSTing them (newline-delimited) to the
|
|
151
|
+
* configured HTTP log-destination `ingestURL`. Accepts a single string or
|
|
152
|
+
* an array of lines (joined with newlines).
|
|
153
|
+
*/
|
|
154
|
+
async push(lines) {
|
|
155
|
+
if (!this.ingestURL) {
|
|
156
|
+
throw new errors_1.DatabaseError('Papertrail push requires an ingestURL to be configured');
|
|
157
|
+
}
|
|
158
|
+
const client = this.requireClient();
|
|
159
|
+
const body = Array.isArray(lines) ? lines.join('\n') : lines;
|
|
160
|
+
try {
|
|
161
|
+
return await client.post(this.ingestURL, body, 'text/plain');
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
165
|
+
throw errors_1.DatabaseError.from(parent, { message: `Papertrail push failed: ${parent.message}` });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// ---------------------------------------------------------------------
|
|
169
|
+
// Search
|
|
170
|
+
// ---------------------------------------------------------------------
|
|
171
|
+
/**
|
|
172
|
+
* Searches log events via `GET /api/v1/events/search`. Returns the parsed
|
|
173
|
+
* response (`{ events, min_id, max_id, reached_beginning, ... }`).
|
|
174
|
+
*/
|
|
175
|
+
async query(q, options = {}) {
|
|
176
|
+
return this.doGet('/api/v1/events/search.json', {
|
|
177
|
+
q,
|
|
178
|
+
system_id: options.systemId === undefined ? undefined : String(options.systemId),
|
|
179
|
+
group_id: options.groupId === undefined ? undefined : String(options.groupId),
|
|
180
|
+
min_id: options.minId,
|
|
181
|
+
max_id: options.maxId,
|
|
182
|
+
min_time: options.minTime === undefined ? undefined : String(options.minTime),
|
|
183
|
+
max_time: options.maxTime === undefined ? undefined : String(options.maxTime),
|
|
184
|
+
limit: options.limit === undefined ? undefined : String(options.limit),
|
|
185
|
+
}, 'query');
|
|
186
|
+
}
|
|
187
|
+
// ---------------------------------------------------------------------
|
|
188
|
+
// Metadata
|
|
189
|
+
// ---------------------------------------------------------------------
|
|
190
|
+
/** Lists the configured log groups via `GET /api/v1/groups`. */
|
|
191
|
+
async labels() {
|
|
192
|
+
return this.doGet('/api/v1/groups.json', undefined, 'labels');
|
|
193
|
+
}
|
|
194
|
+
/** Lists the configured systems (log senders) via `GET /api/v1/systems`. */
|
|
195
|
+
async streams() {
|
|
196
|
+
return this.doGet('/api/v1/systems.json', undefined, 'streams');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
exports.PapertrailStore = PapertrailStore;
|
|
200
|
+
exports.default = PapertrailStore;
|
|
Binary file
|