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,377 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Elasticsearch store implementation.
|
|
4
|
+
*
|
|
5
|
+
* Elasticsearch is a distributed document store built around an inverted
|
|
6
|
+
* index and a JSON-based Query DSL (`match`/`term`/`bool`/`range` queries,
|
|
7
|
+
* aggregations, sorting) rather than SQL. It has no `JOIN`, no transaction
|
|
8
|
+
* log, and documents are schema-flexible (mappings describe *how* fields
|
|
9
|
+
* are indexed, not a hard constraint like a SQL column type), so it does
|
|
10
|
+
* not fit the SQL-shaped `Dialect` interface used by the SQL dialects in
|
|
11
|
+
* this repo. Instead it implements the minimal `NoSqlStore` marker
|
|
12
|
+
* interface (`src/nosql/store.ts`) and exposes Elasticsearch's real
|
|
13
|
+
* capabilities grouped by concern: connection lifecycle, index management,
|
|
14
|
+
* document CRUD (single + bulk), search, and alias management.
|
|
15
|
+
*
|
|
16
|
+
* Uses the official `@elastic/elasticsearch` driver (v9). This client
|
|
17
|
+
* speaks the Elasticsearch REST API and is also broadly compatible with
|
|
18
|
+
* OpenSearch clusters (which forked from Elasticsearch 7.10) for the
|
|
19
|
+
* subset of the API surface wrapped here - see the README for details and
|
|
20
|
+
* caveats.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.ElasticsearchStore = void 0;
|
|
24
|
+
exports.isElasticsearchNotFoundError = isNotFoundError;
|
|
25
|
+
exports.isElasticsearchConflictError = isConflictError;
|
|
26
|
+
const elasticsearch_1 = require("@elastic/elasticsearch");
|
|
27
|
+
const errors_1 = require("../../errors");
|
|
28
|
+
function isNotFoundError(err) {
|
|
29
|
+
const meta = err?.meta;
|
|
30
|
+
return meta?.statusCode === 404;
|
|
31
|
+
}
|
|
32
|
+
function isConflictError(err) {
|
|
33
|
+
const meta = err?.meta;
|
|
34
|
+
return meta?.statusCode === 409;
|
|
35
|
+
}
|
|
36
|
+
function statusCodeOf(err) {
|
|
37
|
+
return err?.meta?.statusCode;
|
|
38
|
+
}
|
|
39
|
+
function wrapConnectionError(err, node) {
|
|
40
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
41
|
+
const message = /econnrefused/i.test(parent.message)
|
|
42
|
+
? 'Connection refused'
|
|
43
|
+
: `Unable to connect to Elasticsearch: ${parent.message}`;
|
|
44
|
+
return new errors_1.ConnectionError(message, {
|
|
45
|
+
parent,
|
|
46
|
+
database: 'elasticsearch',
|
|
47
|
+
host: typeof node === 'string' ? node : undefined,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function wrapDatabaseError(err, message) {
|
|
51
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
52
|
+
const statusCode = statusCodeOf(err);
|
|
53
|
+
const detail = statusCode ? `${parent.message} (HTTP ${statusCode})` : parent.message;
|
|
54
|
+
const combined = message ? `${message}: ${detail}` : detail;
|
|
55
|
+
return errors_1.DatabaseError.from(parent, { message: combined });
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* `ElasticsearchStore` wraps the official `@elastic/elasticsearch` v9
|
|
59
|
+
* client and exposes index management, document CRUD (single + bulk),
|
|
60
|
+
* Query-DSL search, and alias management as a typed, promise-based API.
|
|
61
|
+
*/
|
|
62
|
+
class ElasticsearchStore {
|
|
63
|
+
constructor(options) {
|
|
64
|
+
this.name = 'elasticsearch';
|
|
65
|
+
this.library = '@elastic/elasticsearch';
|
|
66
|
+
this.client = null;
|
|
67
|
+
this.connected = false;
|
|
68
|
+
this.options = options;
|
|
69
|
+
}
|
|
70
|
+
// ---------------------------------------------------------------------
|
|
71
|
+
// Connection lifecycle
|
|
72
|
+
// ---------------------------------------------------------------------
|
|
73
|
+
async connect() {
|
|
74
|
+
if (this.connected && this.client) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const client = new elasticsearch_1.Client(this.options);
|
|
78
|
+
try {
|
|
79
|
+
// The driver connects lazily on first request; `ping()` surfaces
|
|
80
|
+
// connection failures (bad host, refused connection, TLS errors)
|
|
81
|
+
// immediately instead of on the caller's first real operation.
|
|
82
|
+
await client.ping();
|
|
83
|
+
this.client = client;
|
|
84
|
+
this.connected = true;
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
await client.close().catch(() => undefined);
|
|
88
|
+
this.client = null;
|
|
89
|
+
this.connected = false;
|
|
90
|
+
throw wrapConnectionError(err, this.options.node);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async disconnect() {
|
|
94
|
+
if (this.client) {
|
|
95
|
+
await this.client.close();
|
|
96
|
+
this.client = null;
|
|
97
|
+
}
|
|
98
|
+
this.connected = false;
|
|
99
|
+
}
|
|
100
|
+
isConnected() {
|
|
101
|
+
return this.connected && this.client !== null;
|
|
102
|
+
}
|
|
103
|
+
/** Returns the underlying `@elastic/elasticsearch` client for anything not wrapped here. */
|
|
104
|
+
getClient() {
|
|
105
|
+
return this.requireClient();
|
|
106
|
+
}
|
|
107
|
+
requireClient() {
|
|
108
|
+
if (!this.client) {
|
|
109
|
+
throw new errors_1.ConnectionError('Not connected to Elasticsearch', { database: 'elasticsearch' });
|
|
110
|
+
}
|
|
111
|
+
return this.client;
|
|
112
|
+
}
|
|
113
|
+
async exec(fn, action) {
|
|
114
|
+
const client = this.requireClient();
|
|
115
|
+
try {
|
|
116
|
+
return await fn(client);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
throw wrapDatabaseError(err, `Elasticsearch ${action} failed`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// ---------------------------------------------------------------------
|
|
123
|
+
// Index management
|
|
124
|
+
// ---------------------------------------------------------------------
|
|
125
|
+
/** Create an index, optionally with mappings/settings/aliases. */
|
|
126
|
+
async createIndex(index, options = {}) {
|
|
127
|
+
await this.exec((c) => c.indices.create({
|
|
128
|
+
index,
|
|
129
|
+
mappings: options.mappings,
|
|
130
|
+
settings: options.settings,
|
|
131
|
+
aliases: options.aliases,
|
|
132
|
+
}), 'CREATE INDEX');
|
|
133
|
+
}
|
|
134
|
+
/** Delete an index. Resolves without error if the index doesn't exist. */
|
|
135
|
+
async deleteIndex(index) {
|
|
136
|
+
try {
|
|
137
|
+
await this.exec((c) => c.indices.delete({ index }), 'DELETE INDEX');
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
if (!isNotFoundError(err.parent)) {
|
|
141
|
+
throw err;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** Whether an index exists. */
|
|
146
|
+
async indexExists(index) {
|
|
147
|
+
return this.exec((c) => c.indices.exists({ index }), 'INDICES EXISTS');
|
|
148
|
+
}
|
|
149
|
+
/** Get the field mappings for an index. */
|
|
150
|
+
async getMapping(index) {
|
|
151
|
+
const result = await this.exec((c) => c.indices.getMapping({ index }), 'GET MAPPING');
|
|
152
|
+
return result[index]?.mappings;
|
|
153
|
+
}
|
|
154
|
+
/** Add/update field mappings on an existing index. Mapping updates are additive - existing field mappings cannot be changed, only new fields added. */
|
|
155
|
+
async putMapping(index, mappings) {
|
|
156
|
+
await this.exec((c) => c.indices.putMapping({ index, ...mappings }), 'PUT MAPPING');
|
|
157
|
+
}
|
|
158
|
+
/** Get an index's settings. */
|
|
159
|
+
async getSettings(index) {
|
|
160
|
+
const result = await this.exec((c) => c.indices.getSettings({ index }), 'GET SETTINGS');
|
|
161
|
+
return result[index]?.settings?.index;
|
|
162
|
+
}
|
|
163
|
+
/** Update dynamic index settings (e.g. `number_of_replicas`, `refresh_interval`). Static settings like `number_of_shards` require closing the index first (not wrapped here - use `getClient()`). */
|
|
164
|
+
async putSettings(index, settings) {
|
|
165
|
+
await this.exec((c) => c.indices.putSettings({ index, settings }), 'PUT SETTINGS');
|
|
166
|
+
}
|
|
167
|
+
/** Refresh an index so recently-written documents become visible to search immediately, rather than waiting for the automatic refresh interval. */
|
|
168
|
+
async refreshIndex(index) {
|
|
169
|
+
await this.exec((c) => c.indices.refresh({ index }), 'REFRESH');
|
|
170
|
+
}
|
|
171
|
+
// ---------------------------------------------------------------------
|
|
172
|
+
// Document CRUD
|
|
173
|
+
// ---------------------------------------------------------------------
|
|
174
|
+
/**
|
|
175
|
+
* Index (create or overwrite) a document. Omit `id` to let Elasticsearch
|
|
176
|
+
* auto-generate one. Returns the assigned `_id`.
|
|
177
|
+
*/
|
|
178
|
+
async indexDocument(index, document, options = {}) {
|
|
179
|
+
const { id, ...rest } = options;
|
|
180
|
+
const result = await this.exec((c) => c.index({
|
|
181
|
+
index,
|
|
182
|
+
id,
|
|
183
|
+
document,
|
|
184
|
+
op_type: rest.opType,
|
|
185
|
+
refresh: rest.refresh,
|
|
186
|
+
routing: rest.routing,
|
|
187
|
+
}), 'INDEX');
|
|
188
|
+
return result._id;
|
|
189
|
+
}
|
|
190
|
+
/** Get a document by ID. Returns `null` if it doesn't exist. */
|
|
191
|
+
async getDocument(index, id) {
|
|
192
|
+
try {
|
|
193
|
+
const result = await this.exec((c) => c.get({ index, id }), 'GET');
|
|
194
|
+
return (result._source ?? null);
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
if (err instanceof errors_1.DatabaseError && isNotFoundError(err.parent)) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
throw err;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/** Whether a document exists. */
|
|
204
|
+
async documentExists(index, id) {
|
|
205
|
+
return this.exec((c) => c.exists({ index, id }), 'EXISTS');
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Partially update a document by merging `partial` into the stored
|
|
209
|
+
* `_source`. Pass `options.upsert` to insert that document if `id`
|
|
210
|
+
* doesn't already exist yet. Throws `EmptyResultError` if the document
|
|
211
|
+
* doesn't exist and no `upsert` was provided.
|
|
212
|
+
*/
|
|
213
|
+
async updateDocument(index, id, partial, options = {}) {
|
|
214
|
+
try {
|
|
215
|
+
await this.exec((c) => c.update({
|
|
216
|
+
index,
|
|
217
|
+
id,
|
|
218
|
+
doc: partial,
|
|
219
|
+
upsert: options.upsert,
|
|
220
|
+
refresh: options.refresh,
|
|
221
|
+
retry_on_conflict: options.retryOnConflict,
|
|
222
|
+
}), 'UPDATE');
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
if (err instanceof errors_1.DatabaseError && isNotFoundError(err.parent)) {
|
|
226
|
+
throw new errors_1.EmptyResultError(`Document "${id}" not found in index "${index}"`, {
|
|
227
|
+
model: index,
|
|
228
|
+
primaryKey: id,
|
|
229
|
+
parent: err.parent,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
throw err;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Delete a document by ID. Returns `true` if a document was deleted,
|
|
237
|
+
* `false` if it didn't exist (rather than throwing, since "already
|
|
238
|
+
* gone" is a common, non-exceptional outcome for a delete).
|
|
239
|
+
*/
|
|
240
|
+
async deleteDocument(index, id, options = {}) {
|
|
241
|
+
try {
|
|
242
|
+
await this.exec((c) => c.delete({ index, id, refresh: options.refresh, routing: options.routing }), 'DELETE');
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
if (err instanceof errors_1.DatabaseError && isNotFoundError(err.parent)) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
throw err;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// ---------------------------------------------------------------------
|
|
253
|
+
// Bulk operations
|
|
254
|
+
// ---------------------------------------------------------------------
|
|
255
|
+
/**
|
|
256
|
+
* Run a batch of index/create/update/delete operations in a single
|
|
257
|
+
* request. Unlike a SQL transaction, this is not atomic - each item
|
|
258
|
+
* succeeds or fails independently; check `result.errors` and each
|
|
259
|
+
* item's `error` field rather than assuming all-or-nothing.
|
|
260
|
+
*/
|
|
261
|
+
async bulk(actions) {
|
|
262
|
+
// The real `_bulk` API rejects an empty request body outright
|
|
263
|
+
// (`parse_exception: request body is required`, HTTP 400) rather than
|
|
264
|
+
// treating zero operations as a trivial no-op, so short-circuit before
|
|
265
|
+
// making the request instead of surfacing that as a DatabaseError for
|
|
266
|
+
// what is a completely valid (if pointless) caller input.
|
|
267
|
+
if (actions.length === 0) {
|
|
268
|
+
return { errors: false, items: [], took: 0 };
|
|
269
|
+
}
|
|
270
|
+
const operations = [];
|
|
271
|
+
for (const action of actions) {
|
|
272
|
+
if (action.action === 'index' || action.action === 'create') {
|
|
273
|
+
operations.push({ [action.action]: { _index: action.index, _id: action.id } });
|
|
274
|
+
operations.push(action.document);
|
|
275
|
+
}
|
|
276
|
+
else if (action.action === 'update') {
|
|
277
|
+
operations.push({ update: { _index: action.index, _id: action.id } });
|
|
278
|
+
operations.push({ doc: action.document, upsert: action.upsert });
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
operations.push({ delete: { _index: action.index, _id: action.id } });
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const result = await this.exec((c) => c.bulk({ operations }), 'BULK');
|
|
285
|
+
const items = result.items.map((item) => {
|
|
286
|
+
const [actionName, detail] = Object.entries(item)[0];
|
|
287
|
+
return {
|
|
288
|
+
action: actionName,
|
|
289
|
+
id: detail._id ?? undefined,
|
|
290
|
+
status: detail.status ?? 0,
|
|
291
|
+
error: detail.error
|
|
292
|
+
? { type: detail.error.type ?? 'unknown', reason: detail.error.reason ?? 'unknown error' }
|
|
293
|
+
: undefined,
|
|
294
|
+
};
|
|
295
|
+
});
|
|
296
|
+
return { errors: result.errors, items, took: result.took };
|
|
297
|
+
}
|
|
298
|
+
/** Convenience wrapper around `bulk()` for indexing many documents into one index at once. */
|
|
299
|
+
async bulkIndex(index, documents) {
|
|
300
|
+
return this.bulk(documents.map((d) => ({ action: 'index', index, id: d.id, document: d.document })));
|
|
301
|
+
}
|
|
302
|
+
/** Convenience wrapper around `bulk()` for deleting many documents from one index at once. */
|
|
303
|
+
async bulkDelete(index, ids) {
|
|
304
|
+
return this.bulk(ids.map((id) => ({ action: 'delete', index, id })));
|
|
305
|
+
}
|
|
306
|
+
// ---------------------------------------------------------------------
|
|
307
|
+
// Search
|
|
308
|
+
// ---------------------------------------------------------------------
|
|
309
|
+
/**
|
|
310
|
+
* Run a Query DSL search (`match`/`term`/`bool`/`range`/etc.) against
|
|
311
|
+
* one or more indices (comma-separated, or a wildcard pattern). Supports
|
|
312
|
+
* `from`/`size` pagination, `sort`, and named `aggs`.
|
|
313
|
+
*/
|
|
314
|
+
async search(index, params = {}) {
|
|
315
|
+
const result = await this.exec((c) => c.search({
|
|
316
|
+
index,
|
|
317
|
+
query: params.query,
|
|
318
|
+
from: params.from,
|
|
319
|
+
size: params.size,
|
|
320
|
+
sort: params.sort,
|
|
321
|
+
aggs: params.aggs,
|
|
322
|
+
_source: params.source,
|
|
323
|
+
track_total_hits: params.trackTotalHits,
|
|
324
|
+
}), 'SEARCH');
|
|
325
|
+
const totalRaw = result.hits.total;
|
|
326
|
+
const total = typeof totalRaw === 'number'
|
|
327
|
+
? { value: totalRaw, relation: 'eq' }
|
|
328
|
+
: { value: totalRaw?.value ?? 0, relation: (totalRaw?.relation ?? 'eq') };
|
|
329
|
+
return {
|
|
330
|
+
hits: result.hits.hits.map((hit) => ({
|
|
331
|
+
id: hit._id,
|
|
332
|
+
index: hit._index,
|
|
333
|
+
score: hit._score ?? null,
|
|
334
|
+
source: hit._source,
|
|
335
|
+
sort: hit.sort,
|
|
336
|
+
})),
|
|
337
|
+
total,
|
|
338
|
+
maxScore: result.hits.max_score ?? null,
|
|
339
|
+
tookMs: result.took ?? 0,
|
|
340
|
+
aggregations: result.aggregations,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/** Count documents matching a query (or all documents, if `query` is omitted) without fetching them. */
|
|
344
|
+
async count(index, query) {
|
|
345
|
+
const result = await this.exec((c) => c.count({ index, query }), 'COUNT');
|
|
346
|
+
return result.count;
|
|
347
|
+
}
|
|
348
|
+
// ---------------------------------------------------------------------
|
|
349
|
+
// Alias management
|
|
350
|
+
// ---------------------------------------------------------------------
|
|
351
|
+
/** Point an alias at an index, creating the alias if it doesn't exist. */
|
|
352
|
+
async putAlias(index, alias) {
|
|
353
|
+
await this.exec((c) => c.indices.putAlias({ index, name: alias }), 'PUT ALIAS');
|
|
354
|
+
}
|
|
355
|
+
/** Remove an alias from an index. */
|
|
356
|
+
async deleteAlias(index, alias) {
|
|
357
|
+
await this.exec((c) => c.indices.deleteAlias({ index, name: alias }), 'DELETE ALIAS');
|
|
358
|
+
}
|
|
359
|
+
/** List the indices an alias currently points at. */
|
|
360
|
+
async getAlias(alias) {
|
|
361
|
+
const result = await this.exec((c) => c.indices.getAlias({ name: alias }), 'GET ALIAS');
|
|
362
|
+
return Object.keys(result);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Atomically repoint an alias from one index to another - the standard
|
|
366
|
+
* zero-downtime reindex pattern (build the new index, then swap the
|
|
367
|
+
* alias in one request so readers never see a moment with no index
|
|
368
|
+
* behind the alias).
|
|
369
|
+
*/
|
|
370
|
+
async swapAlias(alias, fromIndex, toIndex) {
|
|
371
|
+
await this.exec((c) => c.indices.updateAliases({
|
|
372
|
+
actions: [{ remove: { index: fromIndex, alias } }, { add: { index: toIndex, alias } }],
|
|
373
|
+
}), 'UPDATE ALIASES');
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
exports.ElasticsearchStore = ElasticsearchStore;
|
|
377
|
+
exports.default = ElasticsearchStore;
|