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,461 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MongoDB store implementation for the Prorm NoSQL layer.
|
|
4
|
+
*
|
|
5
|
+
* MongoDB is a document store, not a SQL engine, so this class does not
|
|
6
|
+
* implement the SQL-shaped `Dialect` interface (see src/dialects/dialect.ts).
|
|
7
|
+
* It implements the minimal `NoSqlStore` marker interface (src/nosql/store.ts)
|
|
8
|
+
* for connection lifecycle, and otherwise exposes MongoDB's real API shape
|
|
9
|
+
* directly: filters, projections, aggregation pipelines, sessions/
|
|
10
|
+
* transactions, and typed collections - rather than forcing everything
|
|
11
|
+
* through a `query(sql)` method that doesn't make sense for a document
|
|
12
|
+
* database.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.MongoStore = void 0;
|
|
16
|
+
const mongodb_1 = require("mongodb");
|
|
17
|
+
const index_1 = require("../../errors/index");
|
|
18
|
+
/**
|
|
19
|
+
* `MongoStore` wraps the official `mongodb` driver's `MongoClient`/`Db`/
|
|
20
|
+
* `Collection` API in a small, typed convenience layer.
|
|
21
|
+
*/
|
|
22
|
+
class MongoStore {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.name = 'mongodb';
|
|
25
|
+
this.library = 'mongodb';
|
|
26
|
+
this.client = null;
|
|
27
|
+
this.db = null;
|
|
28
|
+
this._isConnected = false;
|
|
29
|
+
if (!options || !options.uri) {
|
|
30
|
+
throw new index_1.DatabaseError('MongoStore requires a connection `uri`', {
|
|
31
|
+
code: index_1.ErrorCodes.INVALID_CONNECTION,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (!options.database) {
|
|
35
|
+
throw new index_1.DatabaseError('MongoStore requires a `database` name', {
|
|
36
|
+
code: index_1.ErrorCodes.INVALID_CONNECTION,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
this.options = options;
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------------
|
|
42
|
+
// Connection lifecycle
|
|
43
|
+
// ---------------------------------------------------------------------
|
|
44
|
+
async connect() {
|
|
45
|
+
try {
|
|
46
|
+
const client = new mongodb_1.MongoClient(this.options.uri, this.options.clientOptions);
|
|
47
|
+
await client.connect();
|
|
48
|
+
this.client = client;
|
|
49
|
+
this.db = client.db(this.options.database);
|
|
50
|
+
this._isConnected = true;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
this.client = null;
|
|
54
|
+
this.db = null;
|
|
55
|
+
this._isConnected = false;
|
|
56
|
+
throw new index_1.DatabaseError('Failed to connect to MongoDB', {
|
|
57
|
+
code: index_1.ErrorCodes.CONNECTION_ERROR,
|
|
58
|
+
parent: error instanceof Error ? error : undefined,
|
|
59
|
+
original: error instanceof Error ? error.message : String(error),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async disconnect() {
|
|
64
|
+
if (!this.client) {
|
|
65
|
+
this._isConnected = false;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
await this.client.close();
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new index_1.DatabaseError('Failed to disconnect from MongoDB', {
|
|
73
|
+
code: index_1.ErrorCodes.CONNECTION_ERROR,
|
|
74
|
+
parent: error instanceof Error ? error : undefined,
|
|
75
|
+
original: error instanceof Error ? error.message : String(error),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
this.client = null;
|
|
80
|
+
this.db = null;
|
|
81
|
+
this._isConnected = false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
isConnected() {
|
|
85
|
+
return this._isConnected;
|
|
86
|
+
}
|
|
87
|
+
/** Returns the underlying native `MongoClient`. */
|
|
88
|
+
getClient() {
|
|
89
|
+
return this.requireClient();
|
|
90
|
+
}
|
|
91
|
+
/** Returns the underlying native `Db` handle for the configured database. */
|
|
92
|
+
getDb() {
|
|
93
|
+
return this.requireDb();
|
|
94
|
+
}
|
|
95
|
+
requireClient() {
|
|
96
|
+
if (!this.client || !this._isConnected) {
|
|
97
|
+
throw new index_1.DatabaseError('MongoStore is not connected. Call connect() first.', {
|
|
98
|
+
code: index_1.ErrorCodes.INVALID_CONNECTION,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return this.client;
|
|
102
|
+
}
|
|
103
|
+
requireDb() {
|
|
104
|
+
if (!this.db || !this._isConnected) {
|
|
105
|
+
throw new index_1.DatabaseError('MongoStore is not connected. Call connect() first.', {
|
|
106
|
+
code: index_1.ErrorCodes.INVALID_CONNECTION,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return this.db;
|
|
110
|
+
}
|
|
111
|
+
/** Typed collection accessor, e.g. `store.collection<User>('users')`. */
|
|
112
|
+
collection(name) {
|
|
113
|
+
return this.requireDb().collection(name);
|
|
114
|
+
}
|
|
115
|
+
wrapError(op, error) {
|
|
116
|
+
throw new index_1.DatabaseError(`MongoDB operation "${op}" failed`, {
|
|
117
|
+
code: this.mapErrorCode(error),
|
|
118
|
+
parent: error instanceof Error ? error : undefined,
|
|
119
|
+
original: error instanceof Error ? error.message : String(error),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Maps a raw MongoDB driver error to one of our well-known `ErrorCodes`.
|
|
124
|
+
*
|
|
125
|
+
* MongoDB surfaces most server-side failures as a numeric `code` (and a
|
|
126
|
+
* human-readable `codeName`) on the error object itself - unlike some SQL
|
|
127
|
+
* drivers, this is not tucked away behind `.parent`/`.metadata.original`.
|
|
128
|
+
* We sniff those fields here so callers get a meaningful, dialect-
|
|
129
|
+
* agnostic error code (e.g. `UNIQUE_CONSTRAINT_ERROR` for duplicate key
|
|
130
|
+
* violations) instead of a generic `QUERY_ERROR` for everything.
|
|
131
|
+
*/
|
|
132
|
+
mapErrorCode(error) {
|
|
133
|
+
if (error && typeof error === 'object') {
|
|
134
|
+
const mongoCode = error.code;
|
|
135
|
+
const codeName = error.codeName;
|
|
136
|
+
// MongoDB duplicate-key error: code 11000 (or 11001 for legacy
|
|
137
|
+
// insertMany-old-style errors), codeName "DuplicateKey".
|
|
138
|
+
if (mongoCode === 11000 || mongoCode === '11000' || mongoCode === 11001 || codeName === 'DuplicateKey') {
|
|
139
|
+
return index_1.ErrorCodes.UNIQUE_CONSTRAINT_ERROR;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return index_1.ErrorCodes.QUERY_ERROR;
|
|
143
|
+
}
|
|
144
|
+
// ---------------------------------------------------------------------
|
|
145
|
+
// Reads
|
|
146
|
+
// ---------------------------------------------------------------------
|
|
147
|
+
async findOne(collectionName, filter = {}, options) {
|
|
148
|
+
try {
|
|
149
|
+
return await this.collection(collectionName).findOne(filter, options);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
return this.wrapError('findOne', error);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async find(collectionName, filter = {}, options = {}) {
|
|
156
|
+
try {
|
|
157
|
+
const { sort, limit, skip, projection, ...rest } = options;
|
|
158
|
+
const cursor = this.collection(collectionName).find(filter, { ...rest, projection, sort });
|
|
159
|
+
if (typeof skip === 'number')
|
|
160
|
+
cursor.skip(skip);
|
|
161
|
+
if (typeof limit === 'number')
|
|
162
|
+
cursor.limit(limit);
|
|
163
|
+
return (await cursor.toArray());
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
return this.wrapError('find', error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Like {@link find}, but returns the native `FindCursor` instead of
|
|
171
|
+
* materializing the results with `toArray()`. Use this for large result
|
|
172
|
+
* sets that shouldn't be pulled fully into memory - iterate with
|
|
173
|
+
* `for await (const doc of cursor)` or use `cursor.next()`/`cursor.forEach()`.
|
|
174
|
+
*/
|
|
175
|
+
findCursor(collectionName, filter = {}, options = {}) {
|
|
176
|
+
try {
|
|
177
|
+
const { sort, limit, skip, projection, ...rest } = options;
|
|
178
|
+
const cursor = this.collection(collectionName).find(filter, { ...rest, projection, sort });
|
|
179
|
+
if (typeof skip === 'number')
|
|
180
|
+
cursor.skip(skip);
|
|
181
|
+
if (typeof limit === 'number')
|
|
182
|
+
cursor.limit(limit);
|
|
183
|
+
return cursor;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
return this.wrapError('findCursor', error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async countDocuments(collectionName, filter = {}, options) {
|
|
190
|
+
try {
|
|
191
|
+
return await this.collection(collectionName).countDocuments(filter, options);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
return this.wrapError('countDocuments', error);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Returns a fast, metadata-based approximate count of all documents in
|
|
199
|
+
* `collectionName`. Unlike {@link countDocuments}, this does not accept a
|
|
200
|
+
* filter and does not scan the collection - it reads the collection's
|
|
201
|
+
* cached document count, so it's cheap but can be stale/approximate
|
|
202
|
+
* (e.g. immediately after bulk writes, or on a sharded cluster).
|
|
203
|
+
*/
|
|
204
|
+
async estimatedDocumentCount(collectionName, options) {
|
|
205
|
+
try {
|
|
206
|
+
return await this.collection(collectionName).estimatedDocumentCount(options);
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
return this.wrapError('estimatedDocumentCount', error);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async aggregate(collectionName, pipeline, options) {
|
|
213
|
+
try {
|
|
214
|
+
const cursor = this.collection(collectionName).aggregate(pipeline, options);
|
|
215
|
+
return await cursor.toArray();
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
return this.wrapError('aggregate', error);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/** Returns the distinct values for `field` across documents matching `filter`. */
|
|
222
|
+
async distinct(collectionName, field, filter = {}, options) {
|
|
223
|
+
try {
|
|
224
|
+
return await this.collection(collectionName).distinct(field, filter, options);
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
return this.wrapError('distinct', error);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// ---------------------------------------------------------------------
|
|
231
|
+
// Writes
|
|
232
|
+
// ---------------------------------------------------------------------
|
|
233
|
+
async insertOne(collectionName, doc, options) {
|
|
234
|
+
try {
|
|
235
|
+
return await this.collection(collectionName).insertOne(doc, options);
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
return this.wrapError('insertOne', error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async insertMany(collectionName, docs, options) {
|
|
242
|
+
try {
|
|
243
|
+
return await this.collection(collectionName).insertMany(docs, options);
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
return this.wrapError('insertMany', error);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Executes a mix of insert/update/delete/upsert operations against a
|
|
251
|
+
* single collection in one round trip. Thin passthrough to the native
|
|
252
|
+
* driver's `Collection.bulkWrite()`.
|
|
253
|
+
*/
|
|
254
|
+
async bulkWrite(collectionName, operations, options) {
|
|
255
|
+
try {
|
|
256
|
+
return await this.collection(collectionName).bulkWrite(operations, options);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
return this.wrapError('bulkWrite', error);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async updateOne(collectionName, filter, update, options) {
|
|
263
|
+
try {
|
|
264
|
+
return await this.collection(collectionName).updateOne(filter, update, options);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
return this.wrapError('updateOne', error);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async updateMany(collectionName, filter, update, options) {
|
|
271
|
+
try {
|
|
272
|
+
return await this.collection(collectionName).updateMany(filter, update, options);
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
return this.wrapError('updateMany', error);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/** Atomically finds a document matching `filter` and updates it, returning it (or `null`). */
|
|
279
|
+
async findOneAndUpdate(collectionName, filter, update, options) {
|
|
280
|
+
try {
|
|
281
|
+
return await this.collection(collectionName).findOneAndUpdate(filter, update, options ?? {});
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
return this.wrapError('findOneAndUpdate', error);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async deleteOne(collectionName, filter, options) {
|
|
288
|
+
try {
|
|
289
|
+
return await this.collection(collectionName).deleteOne(filter, options);
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
return this.wrapError('deleteOne', error);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
async deleteMany(collectionName, filter, options) {
|
|
296
|
+
try {
|
|
297
|
+
return await this.collection(collectionName).deleteMany(filter, options);
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
return this.wrapError('deleteMany', error);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/** Atomically finds a document matching `filter` and deletes it, returning it (or `null`). */
|
|
304
|
+
async findOneAndDelete(collectionName, filter, options) {
|
|
305
|
+
try {
|
|
306
|
+
return await this.collection(collectionName).findOneAndDelete(filter, options ?? {});
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
return this.wrapError('findOneAndDelete', error);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// ---------------------------------------------------------------------
|
|
313
|
+
// Indexes
|
|
314
|
+
// ---------------------------------------------------------------------
|
|
315
|
+
async createIndex(collectionName, indexSpec, options) {
|
|
316
|
+
try {
|
|
317
|
+
return await this.collection(collectionName).createIndex(indexSpec, options);
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
return this.wrapError('createIndex', error);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
async dropIndex(collectionName, indexName) {
|
|
324
|
+
try {
|
|
325
|
+
return await this.collection(collectionName).dropIndex(indexName);
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
return this.wrapError('dropIndex', error);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Lists the indexes defined on `collectionName`. Fills the asymmetry with
|
|
333
|
+
* {@link createIndex}/{@link dropIndex}, which have no built-in way to
|
|
334
|
+
* inspect what indexes already exist. Thin passthrough to the native
|
|
335
|
+
* driver's `Collection.listIndexes().toArray()`.
|
|
336
|
+
*/
|
|
337
|
+
async listIndexes(collectionName, options) {
|
|
338
|
+
try {
|
|
339
|
+
return await this.collection(collectionName).listIndexes(options).toArray();
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
return this.wrapError('listIndexes', error);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// ---------------------------------------------------------------------
|
|
346
|
+
// Collection administration
|
|
347
|
+
// ---------------------------------------------------------------------
|
|
348
|
+
/**
|
|
349
|
+
* Explicitly creates `collectionName`, rather than relying on MongoDB's
|
|
350
|
+
* implicit creation of a collection on first write. This is the only way
|
|
351
|
+
* to create a **timeseries collection** (`options.timeseries: { timeField,
|
|
352
|
+
* metaField?, granularity? }`) or a **view** (`options.viewOn` +
|
|
353
|
+
* `options.pipeline`), since both must be declared at creation time -
|
|
354
|
+
* previously this required dropping down to `getDb().createCollection(...)`
|
|
355
|
+
* directly.
|
|
356
|
+
*/
|
|
357
|
+
async createCollection(collectionName, options) {
|
|
358
|
+
try {
|
|
359
|
+
return await this.requireDb().createCollection(collectionName, options);
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
return this.wrapError('createCollection', error);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Lists the collections (and views) defined in the configured database.
|
|
367
|
+
* Thin passthrough to the native driver's `Db.listCollections().toArray()`.
|
|
368
|
+
*/
|
|
369
|
+
async listCollections(filter = {}, options) {
|
|
370
|
+
try {
|
|
371
|
+
return (await this.requireDb().listCollections(filter, options).toArray());
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
return this.wrapError('listCollections', error);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Renames `oldName` to `newName`. Uses `Db.renameCollection()` (rather
|
|
379
|
+
* than `Collection.rename()`) because it's the driver API that stays
|
|
380
|
+
* generic over the document type, matching the rest of this class's
|
|
381
|
+
* typed-collection conventions.
|
|
382
|
+
*/
|
|
383
|
+
async renameCollection(oldName, newName, options) {
|
|
384
|
+
try {
|
|
385
|
+
return await this.requireDb().renameCollection(oldName, newName, options);
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
return this.wrapError('renameCollection', error);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/** Drops `collectionName` entirely. Thin passthrough to `Collection.drop()`. */
|
|
392
|
+
async dropCollection(collectionName, options) {
|
|
393
|
+
try {
|
|
394
|
+
return await this.collection(collectionName).drop(options);
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
return this.wrapError('dropCollection', error);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// ---------------------------------------------------------------------
|
|
401
|
+
// Change streams
|
|
402
|
+
// ---------------------------------------------------------------------
|
|
403
|
+
/**
|
|
404
|
+
* Opens a change stream on `collectionName`, delivering real-time
|
|
405
|
+
* notifications of insert/update/replace/delete operations. Thin
|
|
406
|
+
* passthrough to the native driver's `Collection.watch()`.
|
|
407
|
+
*
|
|
408
|
+
* Like {@link withTransaction}, this requires a replica set / sharded
|
|
409
|
+
* cluster deployment - a standalone `mongod` does not support change
|
|
410
|
+
* streams (see README "Known limitations").
|
|
411
|
+
*
|
|
412
|
+
* Returns the native `ChangeStream`, which is itself an async iterable
|
|
413
|
+
* and event emitter (`on('change', ...)`, `on('error', ...)`, `close()`).
|
|
414
|
+
*
|
|
415
|
+
* ```typescript
|
|
416
|
+
* const stream = store.watch<User>('users', [{ $match: { operationType: 'insert' } }]);
|
|
417
|
+
* stream.on('change', (change) => {
|
|
418
|
+
* // change.operationType, change.fullDocument, ...
|
|
419
|
+
* });
|
|
420
|
+
* // later: await stream.close();
|
|
421
|
+
* ```
|
|
422
|
+
*/
|
|
423
|
+
watch(collectionName, pipeline, options) {
|
|
424
|
+
try {
|
|
425
|
+
return this.collection(collectionName).watch(pipeline, options);
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
return this.wrapError('watch', error);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// ---------------------------------------------------------------------
|
|
432
|
+
// Sessions / transactions
|
|
433
|
+
// ---------------------------------------------------------------------
|
|
434
|
+
/** Starts a new client session (for multi-document transactions). */
|
|
435
|
+
startSession(options) {
|
|
436
|
+
return this.requireClient().startSession(options);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Runs `fn` inside a MongoDB multi-document transaction. Requires a
|
|
440
|
+
* replica set / mongos deployment - standalone servers do not support
|
|
441
|
+
* transactions (see README "Known limitations").
|
|
442
|
+
*/
|
|
443
|
+
async withTransaction(fn, options) {
|
|
444
|
+
const session = this.requireClient().startSession();
|
|
445
|
+
let result;
|
|
446
|
+
try {
|
|
447
|
+
await session.withTransaction(async () => {
|
|
448
|
+
result = await fn(session);
|
|
449
|
+
}, options);
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
return this.wrapError('withTransaction', error);
|
|
453
|
+
}
|
|
454
|
+
finally {
|
|
455
|
+
await session.endSession();
|
|
456
|
+
}
|
|
457
|
+
return result;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
exports.MongoStore = MongoStore;
|
|
461
|
+
exports.default = MongoStore;
|