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,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Oracle Coherence store implementation.
|
|
4
|
+
*
|
|
5
|
+
* Oracle Coherence is a distributed in-memory data grid. Data lives in named
|
|
6
|
+
* caches (its distributed maps). There is no SQL-shaped `query(sql)` surface
|
|
7
|
+
* for key/value access, so this class implements the minimal `NoSqlStore`
|
|
8
|
+
* marker interface and exposes Coherence's cache operations
|
|
9
|
+
* (getMap/put/get/remove/keys/size) as a typed, promise-based API.
|
|
10
|
+
*
|
|
11
|
+
* ## Transport: the Coherence REST API over `fetch`
|
|
12
|
+
*
|
|
13
|
+
* Coherence exposes a language-neutral REST API rather than a canonical
|
|
14
|
+
* Node.js driver, so this store talks to it with the global `fetch` (exactly
|
|
15
|
+
* like `PrometheusStore`) and `library` is `'fetch'`. For tests (and callers
|
|
16
|
+
* who want their own transport) an alternative client can be injected via
|
|
17
|
+
* `CoherenceStoreOptions.client`; when omitted a tiny internal `fetch`
|
|
18
|
+
* client is built at connect time.
|
|
19
|
+
*
|
|
20
|
+
* Endpoints wrapped (cache name is the first path segment):
|
|
21
|
+
* - `mapPut` -> `PUT /<cache>/<key>`
|
|
22
|
+
* - `mapGet` -> `GET /<cache>/<key>`
|
|
23
|
+
* - `mapRemove` -> `DELETE /<cache>/<key>`
|
|
24
|
+
* - `mapKeys` -> `GET /<cache>/keys`
|
|
25
|
+
* - `mapSize` -> `GET /<cache>/count`
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.CoherenceStore = exports.DEFAULT_COHERENCE_BASE_URL = void 0;
|
|
29
|
+
exports.createFetchClient = createFetchClient;
|
|
30
|
+
const errors_1 = require("../../errors");
|
|
31
|
+
/** Default Coherence REST base URL. */
|
|
32
|
+
exports.DEFAULT_COHERENCE_BASE_URL = 'http://localhost:8080';
|
|
33
|
+
/** Build a `fetch`-backed REST client for the given base URL. */
|
|
34
|
+
function createFetchClient(baseURL, headers) {
|
|
35
|
+
const base = baseURL.endsWith('/') ? baseURL : `${baseURL}/`;
|
|
36
|
+
const buildUrl = (path) => new URL(path.startsWith('/') ? path.slice(1) : path, base).toString();
|
|
37
|
+
const parse = async (res) => {
|
|
38
|
+
const text = await res.text();
|
|
39
|
+
if (!text)
|
|
40
|
+
return null;
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(text);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return text;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
async get(path) {
|
|
50
|
+
const res = await fetch(buildUrl(path), { method: 'GET', headers });
|
|
51
|
+
if (res.status === 404)
|
|
52
|
+
return null;
|
|
53
|
+
if (!res.ok)
|
|
54
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
55
|
+
return parse(res);
|
|
56
|
+
},
|
|
57
|
+
async put(path, body, contentType = 'application/json') {
|
|
58
|
+
const res = await fetch(buildUrl(path), {
|
|
59
|
+
method: 'PUT',
|
|
60
|
+
body,
|
|
61
|
+
headers: { ...(headers ?? {}), 'Content-Type': contentType },
|
|
62
|
+
});
|
|
63
|
+
if (!res.ok)
|
|
64
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
65
|
+
return parse(res);
|
|
66
|
+
},
|
|
67
|
+
async delete(path) {
|
|
68
|
+
const res = await fetch(buildUrl(path), { method: 'DELETE', headers });
|
|
69
|
+
if (res.status === 404)
|
|
70
|
+
return null;
|
|
71
|
+
if (!res.ok)
|
|
72
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
73
|
+
return parse(res);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const enc = encodeURIComponent;
|
|
78
|
+
/**
|
|
79
|
+
* `CoherenceStore` wraps Coherence's REST API behind the `NoSqlStore`
|
|
80
|
+
* lifecycle and exposes named-cache key/value operations.
|
|
81
|
+
*/
|
|
82
|
+
class CoherenceStore {
|
|
83
|
+
constructor(options = {}) {
|
|
84
|
+
this.name = 'coherence';
|
|
85
|
+
this.library = 'fetch';
|
|
86
|
+
this.client = null;
|
|
87
|
+
this.connected = false;
|
|
88
|
+
/** Cached cache handles, keyed by name so `getMap` is idempotent. */
|
|
89
|
+
this.caches = new Map();
|
|
90
|
+
this.baseURL = options.baseURL ?? exports.DEFAULT_COHERENCE_BASE_URL;
|
|
91
|
+
this.injectedClient = options.client;
|
|
92
|
+
this.headers = options.headers;
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------
|
|
95
|
+
// Connection lifecycle
|
|
96
|
+
// ---------------------------------------------------------------------
|
|
97
|
+
async connect() {
|
|
98
|
+
if (this.connected && this.client) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.client = this.injectedClient ?? createFetchClient(this.baseURL, this.headers);
|
|
102
|
+
this.connected = true;
|
|
103
|
+
}
|
|
104
|
+
async disconnect() {
|
|
105
|
+
this.client = null;
|
|
106
|
+
this.caches.clear();
|
|
107
|
+
this.connected = false;
|
|
108
|
+
}
|
|
109
|
+
isConnected() {
|
|
110
|
+
return this.connected && this.client !== null;
|
|
111
|
+
}
|
|
112
|
+
/** Returns the underlying (internal or injected) HTTP client. */
|
|
113
|
+
getClient() {
|
|
114
|
+
return this.requireClient();
|
|
115
|
+
}
|
|
116
|
+
requireClient() {
|
|
117
|
+
if (!this.client) {
|
|
118
|
+
throw new errors_1.ConnectionError('Not connected to Coherence', {
|
|
119
|
+
database: 'coherence',
|
|
120
|
+
host: this.baseURL,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return this.client;
|
|
124
|
+
}
|
|
125
|
+
wrap(err, action) {
|
|
126
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
127
|
+
return errors_1.DatabaseError.from(parent, { message: `Coherence ${action} failed: ${parent.message}` });
|
|
128
|
+
}
|
|
129
|
+
// ---------------------------------------------------------------------
|
|
130
|
+
// Distributed cache operations
|
|
131
|
+
// ---------------------------------------------------------------------
|
|
132
|
+
/** Resolve (and cache) a named-cache handle. */
|
|
133
|
+
async getMap(name) {
|
|
134
|
+
this.requireClient();
|
|
135
|
+
let cache = this.caches.get(name);
|
|
136
|
+
if (!cache) {
|
|
137
|
+
cache = { name };
|
|
138
|
+
this.caches.set(name, cache);
|
|
139
|
+
}
|
|
140
|
+
return cache;
|
|
141
|
+
}
|
|
142
|
+
/** Store `value` under `key` in `map` (`PUT /<cache>/<key>`). */
|
|
143
|
+
async mapPut(map, key, value) {
|
|
144
|
+
const client = this.requireClient();
|
|
145
|
+
try {
|
|
146
|
+
await client.put(`/${enc(map.name)}/${enc(key)}`, JSON.stringify(value));
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
throw this.wrap(err, 'mapPut');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Read `key` from `map` (`GET /<cache>/<key>`); `null` if absent. */
|
|
153
|
+
async mapGet(map, key) {
|
|
154
|
+
const client = this.requireClient();
|
|
155
|
+
try {
|
|
156
|
+
return await client.get(`/${enc(map.name)}/${enc(key)}`);
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
throw this.wrap(err, 'mapGet');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** Remove `key` from `map` (`DELETE /<cache>/<key>`). */
|
|
163
|
+
async mapRemove(map, key) {
|
|
164
|
+
const client = this.requireClient();
|
|
165
|
+
try {
|
|
166
|
+
return await client.delete(`/${enc(map.name)}/${enc(key)}`);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
throw this.wrap(err, 'mapRemove');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** List all keys in `map` (`GET /<cache>/keys`). */
|
|
173
|
+
async mapKeys(map) {
|
|
174
|
+
const client = this.requireClient();
|
|
175
|
+
try {
|
|
176
|
+
const body = await client.get(`/${enc(map.name)}/keys`);
|
|
177
|
+
if (Array.isArray(body))
|
|
178
|
+
return body;
|
|
179
|
+
if (body && Array.isArray(body.keys))
|
|
180
|
+
return body.keys;
|
|
181
|
+
return body == null ? [] : [body];
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
throw this.wrap(err, 'mapKeys');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** Number of entries in `map` (`GET /<cache>/count`). */
|
|
188
|
+
async mapSize(map) {
|
|
189
|
+
const client = this.requireClient();
|
|
190
|
+
try {
|
|
191
|
+
const body = await client.get(`/${enc(map.name)}/count`);
|
|
192
|
+
return Number(body) || 0;
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
throw this.wrap(err, 'mapSize');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
exports.CoherenceStore = CoherenceStore;
|
|
200
|
+
exports.default = CoherenceStore;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Azure Cosmos DB store implementation for the Prorm NoSQL layer.
|
|
4
|
+
*
|
|
5
|
+
* Cosmos DB is a multi-model database (document, key/value, graph, column)
|
|
6
|
+
* exposed here through its document (SQL/Core) API. Documents live in a
|
|
7
|
+
* container within a database and are addressed by an `id`. It does not fit
|
|
8
|
+
* the SQL-shaped `Dialect` interface (no identifier escaping, no DDL
|
|
9
|
+
* builder), so this class implements the minimal `NoSqlStore` marker
|
|
10
|
+
* interface for connection lifecycle and otherwise exposes Cosmos DB's real
|
|
11
|
+
* item CRUD plus SQL query API directly.
|
|
12
|
+
*
|
|
13
|
+
* Uses the official `@azure/cosmos` SDK. 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 `client`
|
|
16
|
+
* via `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.CosmosDbStore = void 0;
|
|
21
|
+
const errors_1 = require("../../errors");
|
|
22
|
+
class CosmosDbStore {
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.name = 'cosmosdb';
|
|
25
|
+
this.library = '@azure/cosmos';
|
|
26
|
+
this.client = null;
|
|
27
|
+
this.connected = false;
|
|
28
|
+
this.options = options;
|
|
29
|
+
this.defaultDatabase = options.database ?? 'default';
|
|
30
|
+
this.defaultContainer = options.container ?? 'default';
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------
|
|
33
|
+
// Connection lifecycle
|
|
34
|
+
// ---------------------------------------------------------------------
|
|
35
|
+
async connect() {
|
|
36
|
+
if (this.connected && this.client) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
if (this.options.client) {
|
|
41
|
+
this.client = this.options.client;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
45
|
+
const mod = require('@azure/cosmos');
|
|
46
|
+
const CosmosClientCtor = mod.CosmosClient;
|
|
47
|
+
this.client = new CosmosClientCtor({
|
|
48
|
+
endpoint: this.options.endpoint,
|
|
49
|
+
key: this.options.key,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
this.connected = true;
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
this.client = null;
|
|
56
|
+
this.connected = false;
|
|
57
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
58
|
+
throw new errors_1.ConnectionError(`Unable to connect to Cosmos DB: ${parent.message}`, {
|
|
59
|
+
parent,
|
|
60
|
+
database: 'cosmosdb',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async disconnect() {
|
|
65
|
+
// The Cosmos SDK client holds no long-lived socket that must be closed;
|
|
66
|
+
// dispose the reference so subsequent calls require a fresh connect().
|
|
67
|
+
this.client = null;
|
|
68
|
+
this.connected = false;
|
|
69
|
+
}
|
|
70
|
+
isConnected() {
|
|
71
|
+
return this.connected && this.client !== null;
|
|
72
|
+
}
|
|
73
|
+
getClient() {
|
|
74
|
+
return this.requireClient();
|
|
75
|
+
}
|
|
76
|
+
requireClient() {
|
|
77
|
+
if (!this.client || !this.connected) {
|
|
78
|
+
throw new errors_1.ConnectionError('Not connected to Cosmos DB. Call connect() first.', {
|
|
79
|
+
database: 'cosmosdb',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return this.client;
|
|
83
|
+
}
|
|
84
|
+
/** Resolves a container handle via `database(db).container(container)`. */
|
|
85
|
+
container(container, database) {
|
|
86
|
+
const client = this.requireClient();
|
|
87
|
+
const db = client.database(database ?? this.defaultDatabase);
|
|
88
|
+
return db.container(container ?? this.defaultContainer);
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------
|
|
91
|
+
// Document CRUD
|
|
92
|
+
// ---------------------------------------------------------------------
|
|
93
|
+
/** Create a document; returns its `id`. */
|
|
94
|
+
async insert(collection, doc) {
|
|
95
|
+
try {
|
|
96
|
+
const result = await this.container(collection).items.create(doc);
|
|
97
|
+
return result?.resource?.id ?? doc.id;
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
throw wrapDatabaseError(err, 'Cosmos DB insert failed');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Read a document by id, returning its stored resource. */
|
|
104
|
+
async get(collection, id) {
|
|
105
|
+
try {
|
|
106
|
+
const result = await this.container(collection).item(id).read();
|
|
107
|
+
return result?.resource;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
throw wrapDatabaseError(err, 'Cosmos DB get failed');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** Merge `patch` into the existing document and replace it. */
|
|
114
|
+
async update(collection, id, patch) {
|
|
115
|
+
try {
|
|
116
|
+
const item = this.container(collection).item(id);
|
|
117
|
+
const current = await item.read();
|
|
118
|
+
const merged = { ...(current?.resource ?? {}), ...patch, id };
|
|
119
|
+
const result = await item.replace(merged);
|
|
120
|
+
return result?.resource ?? merged;
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
throw wrapDatabaseError(err, 'Cosmos DB update failed');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Delete a document by id. */
|
|
127
|
+
async delete(collection, id) {
|
|
128
|
+
try {
|
|
129
|
+
return await this.container(collection).item(id).delete();
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
throw wrapDatabaseError(err, 'Cosmos DB delete failed');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Run a Cosmos SQL query (string or `SqlQuerySpec`) against `collection`
|
|
137
|
+
* and return the matched resources.
|
|
138
|
+
*/
|
|
139
|
+
async query(collection, statement, options = {}) {
|
|
140
|
+
try {
|
|
141
|
+
const result = await this.container(collection).items.query(statement, options).fetchAll();
|
|
142
|
+
return result?.resources ?? [];
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
throw wrapDatabaseError(err, 'Cosmos DB query failed');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.CosmosDbStore = CosmosDbStore;
|
|
150
|
+
function wrapDatabaseError(err, message) {
|
|
151
|
+
if (err instanceof errors_1.ConnectionError) {
|
|
152
|
+
return err;
|
|
153
|
+
}
|
|
154
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
155
|
+
return errors_1.DatabaseError.from(parent, { message: `${message}: ${parent.message}` });
|
|
156
|
+
}
|
|
157
|
+
exports.default = CosmosDbStore;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Couchbase store implementation for the Prorm NoSQL layer.
|
|
4
|
+
*
|
|
5
|
+
* Couchbase is a distributed document/key-value store. Documents live in a
|
|
6
|
+
* bucket, are addressed by an opaque key within a scope/collection, and can
|
|
7
|
+
* additionally be queried with N1QL (SQL++). It does not fit the SQL-shaped
|
|
8
|
+
* `Dialect` interface (no identifier escaping, no DDL builder), so this class
|
|
9
|
+
* implements the minimal `NoSqlStore` marker interface for connection
|
|
10
|
+
* lifecycle and otherwise exposes Couchbase's real key/value CRUD plus N1QL
|
|
11
|
+
* query API directly rather than forcing everything through `query(sql)`.
|
|
12
|
+
*
|
|
13
|
+
* Uses the official `couchbase` Node.js SDK. That driver is an optional
|
|
14
|
+
* peer dependency and is loaded lazily inside `connect()` so importing this
|
|
15
|
+
* module never requires it to be installed. Tests inject a pre-built mock
|
|
16
|
+
* `cluster` via `options.cluster`, which bypasses the lazy `require`
|
|
17
|
+
* entirely - no real driver and no network are needed.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.CouchbaseStore = void 0;
|
|
21
|
+
const errors_1 = require("../../errors");
|
|
22
|
+
const DEFAULT_BUCKET = 'default';
|
|
23
|
+
const DEFAULT_SCOPE = '_default';
|
|
24
|
+
const DEFAULT_COLLECTION = '_default';
|
|
25
|
+
/**
|
|
26
|
+
* `CouchbaseStore` wraps the official `couchbase` SDK's
|
|
27
|
+
* `Cluster`/`Bucket`/`Collection` API in a small key/value CRUD plus N1QL
|
|
28
|
+
* convenience layer.
|
|
29
|
+
*/
|
|
30
|
+
class CouchbaseStore {
|
|
31
|
+
constructor(options = {}) {
|
|
32
|
+
this.name = 'couchbase';
|
|
33
|
+
this.library = 'couchbase';
|
|
34
|
+
this.cluster = null;
|
|
35
|
+
this.connected = false;
|
|
36
|
+
this.options = options;
|
|
37
|
+
this.defaultBucket = options.bucket ?? DEFAULT_BUCKET;
|
|
38
|
+
this.defaultScope = options.scope ?? DEFAULT_SCOPE;
|
|
39
|
+
this.defaultCollection = options.collection ?? DEFAULT_COLLECTION;
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------------
|
|
42
|
+
// Connection lifecycle
|
|
43
|
+
// ---------------------------------------------------------------------
|
|
44
|
+
async connect() {
|
|
45
|
+
if (this.connected && this.cluster) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
if (this.options.cluster) {
|
|
50
|
+
// A pre-built cluster was injected (e.g. by tests) - use it as-is
|
|
51
|
+
// and skip loading the driver entirely.
|
|
52
|
+
this.cluster = this.options.cluster;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
56
|
+
const cb = require('couchbase');
|
|
57
|
+
this.cluster = await cb.connect(this.options.connectionString, {
|
|
58
|
+
username: this.options.username,
|
|
59
|
+
password: this.options.password,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
this.connected = true;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
this.cluster = null;
|
|
66
|
+
this.connected = false;
|
|
67
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
68
|
+
throw new errors_1.ConnectionError(`Unable to connect to Couchbase: ${parent.message}`, {
|
|
69
|
+
parent,
|
|
70
|
+
database: 'couchbase',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async disconnect() {
|
|
75
|
+
if (!this.cluster) {
|
|
76
|
+
this.connected = false;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
await this.cluster.close();
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
throw wrapDatabaseError(err, 'Couchbase disconnect failed');
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
this.cluster = null;
|
|
87
|
+
this.connected = false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
isConnected() {
|
|
91
|
+
return this.connected && this.cluster !== null;
|
|
92
|
+
}
|
|
93
|
+
/** Returns the underlying native `Cluster` for anything not wrapped here. */
|
|
94
|
+
getClient() {
|
|
95
|
+
return this.requireCluster();
|
|
96
|
+
}
|
|
97
|
+
requireCluster() {
|
|
98
|
+
if (!this.cluster || !this.connected) {
|
|
99
|
+
throw new errors_1.ConnectionError('Not connected to Couchbase. Call connect() first.', {
|
|
100
|
+
database: 'couchbase',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return this.cluster;
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------
|
|
106
|
+
// Collection resolution
|
|
107
|
+
// ---------------------------------------------------------------------
|
|
108
|
+
/**
|
|
109
|
+
* Resolves a collection handle. With no arguments (or only a bucket) it
|
|
110
|
+
* uses the store's configured defaults; passing an explicit
|
|
111
|
+
* `scope`/`collection` targets a non-default collection via
|
|
112
|
+
* `bucket.scope(scope).collection(collection)`, otherwise it falls back to
|
|
113
|
+
* `bucket.defaultCollection()`.
|
|
114
|
+
*/
|
|
115
|
+
collection(bucket, scope, collection) {
|
|
116
|
+
const cluster = this.requireCluster();
|
|
117
|
+
try {
|
|
118
|
+
const bucketName = bucket ?? this.defaultBucket;
|
|
119
|
+
const scopeName = scope ?? this.defaultScope;
|
|
120
|
+
const collectionName = collection ?? this.defaultCollection;
|
|
121
|
+
const bucketHandle = cluster.bucket(bucketName);
|
|
122
|
+
if (scopeName === DEFAULT_SCOPE && collectionName === DEFAULT_COLLECTION) {
|
|
123
|
+
return bucketHandle.defaultCollection();
|
|
124
|
+
}
|
|
125
|
+
return bucketHandle.scope(scopeName).collection(collectionName);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
throw wrapDatabaseError(err, 'Couchbase collection resolution failed');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------
|
|
132
|
+
// Key/value CRUD (against the default collection)
|
|
133
|
+
// ---------------------------------------------------------------------
|
|
134
|
+
/** Insert a new document; fails if the key already exists. */
|
|
135
|
+
async insert(id, doc) {
|
|
136
|
+
try {
|
|
137
|
+
return await this.collection().insert(id, doc);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
throw wrapDatabaseError(err, 'Couchbase insert failed');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** Insert or replace a document by key. */
|
|
144
|
+
async upsert(id, doc) {
|
|
145
|
+
try {
|
|
146
|
+
return await this.collection().upsert(id, doc);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
throw wrapDatabaseError(err, 'Couchbase upsert failed');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Fetch a document by key, returning its `.content` (the stored value). */
|
|
153
|
+
async get(id) {
|
|
154
|
+
try {
|
|
155
|
+
const result = await this.collection().get(id);
|
|
156
|
+
return result?.content;
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
throw wrapDatabaseError(err, 'Couchbase get failed');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** Replace an existing document; fails if the key does not exist. */
|
|
163
|
+
async replace(id, doc) {
|
|
164
|
+
try {
|
|
165
|
+
return await this.collection().replace(id, doc);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
throw wrapDatabaseError(err, 'Couchbase replace failed');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/** Remove a document by key. */
|
|
172
|
+
async remove(id) {
|
|
173
|
+
try {
|
|
174
|
+
return await this.collection().remove(id);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
throw wrapDatabaseError(err, 'Couchbase remove failed');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// ---------------------------------------------------------------------
|
|
181
|
+
// N1QL (SQL++) queries
|
|
182
|
+
// ---------------------------------------------------------------------
|
|
183
|
+
/**
|
|
184
|
+
* Run a N1QL/SQL++ `statement` against the cluster and return its result
|
|
185
|
+
* rows. `options.parameters` binds positional (array) or named (object)
|
|
186
|
+
* parameters into the statement.
|
|
187
|
+
*/
|
|
188
|
+
async query(statement, options = {}) {
|
|
189
|
+
const cluster = this.requireCluster();
|
|
190
|
+
try {
|
|
191
|
+
const { parameters, ...rest } = options;
|
|
192
|
+
const result = await cluster.query(statement, { parameters, ...rest });
|
|
193
|
+
return result?.rows ?? [];
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
throw wrapDatabaseError(err, 'Couchbase query failed');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.CouchbaseStore = CouchbaseStore;
|
|
201
|
+
/**
|
|
202
|
+
* Wrap a raw driver error in a `DatabaseError`, preserving the original text.
|
|
203
|
+
* A `ConnectionError` (e.g. "not connected") is passed through unchanged so
|
|
204
|
+
* callers can still distinguish connection failures from operation failures.
|
|
205
|
+
*/
|
|
206
|
+
function wrapDatabaseError(err, message) {
|
|
207
|
+
if (err instanceof errors_1.ConnectionError) {
|
|
208
|
+
return err;
|
|
209
|
+
}
|
|
210
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
211
|
+
return errors_1.DatabaseError.from(parent, { message: `${message}: ${parent.message}` });
|
|
212
|
+
}
|
|
213
|
+
exports.default = CouchbaseStore;
|