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,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DAX (Amazon DynamoDB Accelerator) store implementation.
|
|
4
|
+
*
|
|
5
|
+
* DAX is a fully managed, in-memory, write-through cache for Amazon
|
|
6
|
+
* DynamoDB. It is not a standalone database - it is a DynamoDB *cache* that
|
|
7
|
+
* speaks the DynamoDB wire API, so the `amazon-dax-client` driver is a
|
|
8
|
+
* drop-in replacement for the low-level `AWS.DynamoDB` client
|
|
9
|
+
* (`getItem`/`putItem`/`deleteItem`/`scan`, each returning a request with a
|
|
10
|
+
* `.promise()`).
|
|
11
|
+
*
|
|
12
|
+
* This class implements the minimal `NoSqlStore` marker interface and maps a
|
|
13
|
+
* simple edge-KV surface onto a single DynamoDB table used as a key-value
|
|
14
|
+
* bucket:
|
|
15
|
+
*
|
|
16
|
+
* - `get(key)` -> `getItem` (Key = { <keyAttr>: key })
|
|
17
|
+
* - `set(k,v)` -> `putItem` (Item = { <keyAttr>: key, <valueAttr>: value })
|
|
18
|
+
* - `del(key)` -> `deleteItem`
|
|
19
|
+
* - `list(pref?)` -> `scan` (returns the `<keyAttr>` of each item)
|
|
20
|
+
* - `incr(k,by?)` -> read-modify-write over `getItem`/`putItem`
|
|
21
|
+
* (non-atomic; documented).
|
|
22
|
+
*
|
|
23
|
+
* ## Driver
|
|
24
|
+
*
|
|
25
|
+
* Uses `amazon-dax-client`. The driver is loaded lazily inside `connect()`
|
|
26
|
+
* (or supplied pre-built via the `client` option) so importing this module
|
|
27
|
+
* never requires `amazon-dax-client` to be installed unless a store is
|
|
28
|
+
* actually connected. Tests inject a mock `client`.
|
|
29
|
+
*
|
|
30
|
+
* ## Serialization
|
|
31
|
+
*
|
|
32
|
+
* Values are stored as DynamoDB string (`S`) attributes: strings verbatim,
|
|
33
|
+
* every other value `JSON.stringify`'d first.
|
|
34
|
+
*/
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DaxStore = void 0;
|
|
37
|
+
const errors_1 = require("../../errors");
|
|
38
|
+
function serialize(value) {
|
|
39
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `DaxStore` wraps an `amazon-dax-client` (DynamoDB-compatible) client behind
|
|
43
|
+
* the `NoSqlStore` lifecycle and an edge-KV `get`/`set`/`del`/`list`/`incr`
|
|
44
|
+
* surface over a single DynamoDB table.
|
|
45
|
+
*/
|
|
46
|
+
class DaxStore {
|
|
47
|
+
constructor(options = {}) {
|
|
48
|
+
this.name = 'dax';
|
|
49
|
+
this.library = 'amazon-dax-client';
|
|
50
|
+
this.client = null;
|
|
51
|
+
this.connected = false;
|
|
52
|
+
this.options = options;
|
|
53
|
+
}
|
|
54
|
+
get tableName() {
|
|
55
|
+
return this.options.tableName ?? '';
|
|
56
|
+
}
|
|
57
|
+
get keyAttr() {
|
|
58
|
+
return this.options.keyAttr ?? 'key';
|
|
59
|
+
}
|
|
60
|
+
get valueAttr() {
|
|
61
|
+
return this.options.valueAttr ?? 'value';
|
|
62
|
+
}
|
|
63
|
+
get ttlAttr() {
|
|
64
|
+
return this.options.ttlAttr ?? 'ttl';
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------
|
|
67
|
+
// Connection lifecycle
|
|
68
|
+
// ---------------------------------------------------------------------
|
|
69
|
+
async connect() {
|
|
70
|
+
if (this.connected && this.client) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
if (this.options.client) {
|
|
75
|
+
this.client = this.options.client;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
79
|
+
const mod = require('amazon-dax-client');
|
|
80
|
+
const AmazonDaxClient = mod.default ?? mod;
|
|
81
|
+
this.client = new AmazonDaxClient({
|
|
82
|
+
endpoints: this.options.endpoints,
|
|
83
|
+
region: this.options.region,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
this.connected = true;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
this.client = null;
|
|
90
|
+
this.connected = false;
|
|
91
|
+
throw wrapConnectionError(err, this.options.endpoints?.[0]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async disconnect() {
|
|
95
|
+
this.client = null;
|
|
96
|
+
this.connected = false;
|
|
97
|
+
}
|
|
98
|
+
isConnected() {
|
|
99
|
+
return this.connected && this.client !== null;
|
|
100
|
+
}
|
|
101
|
+
/** Returns the underlying DAX (DynamoDB-compatible) client for anything not wrapped here. */
|
|
102
|
+
getClient() {
|
|
103
|
+
return this.requireClient();
|
|
104
|
+
}
|
|
105
|
+
requireClient() {
|
|
106
|
+
if (!this.client) {
|
|
107
|
+
throw new errors_1.ConnectionError('Not connected to DAX', {
|
|
108
|
+
database: 'dax',
|
|
109
|
+
host: this.options.endpoints?.[0],
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return this.client;
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------
|
|
115
|
+
// Key-value operations
|
|
116
|
+
// ---------------------------------------------------------------------
|
|
117
|
+
/** Read a key via `getItem`. Returns the stored string, or `null` if missing. */
|
|
118
|
+
async get(key) {
|
|
119
|
+
const client = this.requireClient();
|
|
120
|
+
try {
|
|
121
|
+
const res = await client
|
|
122
|
+
.getItem({ TableName: this.tableName, Key: { [this.keyAttr]: { S: key } } })
|
|
123
|
+
.promise();
|
|
124
|
+
const attr = res.Item?.[this.valueAttr];
|
|
125
|
+
return attr?.S ?? null;
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
throw wrapDatabaseError(err, 'GET');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Write `value` under `key` via `putItem`. Strings are stored verbatim;
|
|
133
|
+
* other values are JSON-serialized. `options.ttl`/`options.expiration`
|
|
134
|
+
* populate the table's TTL attribute (`ttlAttr`).
|
|
135
|
+
*/
|
|
136
|
+
async set(key, value, options = {}) {
|
|
137
|
+
const client = this.requireClient();
|
|
138
|
+
const item = {
|
|
139
|
+
[this.keyAttr]: { S: key },
|
|
140
|
+
[this.valueAttr]: { S: serialize(value) },
|
|
141
|
+
};
|
|
142
|
+
if (options.expiration !== undefined) {
|
|
143
|
+
item[this.ttlAttr] = { N: String(options.expiration) };
|
|
144
|
+
}
|
|
145
|
+
else if (options.ttl !== undefined) {
|
|
146
|
+
item[this.ttlAttr] = { N: String(Math.floor(Date.now() / 1000) + options.ttl) };
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
await client.putItem({ TableName: this.tableName, Item: item }).promise();
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
throw wrapDatabaseError(err, 'SET');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** Delete a key via `deleteItem`. */
|
|
156
|
+
async del(key) {
|
|
157
|
+
const client = this.requireClient();
|
|
158
|
+
try {
|
|
159
|
+
await client
|
|
160
|
+
.deleteItem({ TableName: this.tableName, Key: { [this.keyAttr]: { S: key } } })
|
|
161
|
+
.promise();
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
throw wrapDatabaseError(err, 'DEL');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** List key names via `scan`, optionally filtered to those beginning with `prefix`. */
|
|
168
|
+
async list(prefix) {
|
|
169
|
+
const client = this.requireClient();
|
|
170
|
+
const params = {
|
|
171
|
+
TableName: this.tableName,
|
|
172
|
+
ProjectionExpression: '#k',
|
|
173
|
+
ExpressionAttributeNames: { '#k': this.keyAttr },
|
|
174
|
+
};
|
|
175
|
+
if (prefix !== undefined) {
|
|
176
|
+
params.FilterExpression = 'begins_with(#k, :p)';
|
|
177
|
+
params.ExpressionAttributeValues = { ':p': { S: prefix } };
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const res = await client.scan(params).promise();
|
|
181
|
+
const items = res.Items ?? [];
|
|
182
|
+
return items.map((item) => item[this.keyAttr]?.S).filter((k) => k !== undefined);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
throw wrapDatabaseError(err, 'LIST');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Increment the numeric value at `key` by `by` (default `1`). Implemented
|
|
190
|
+
* as a non-atomic read-modify-write over `getItem`/`putItem`.
|
|
191
|
+
*/
|
|
192
|
+
async incr(key, by = 1) {
|
|
193
|
+
const current = await this.get(key);
|
|
194
|
+
const next = (current === null ? 0 : Number(current)) + by;
|
|
195
|
+
await this.set(key, String(next));
|
|
196
|
+
return next;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
exports.DaxStore = DaxStore;
|
|
200
|
+
function wrapConnectionError(err, host) {
|
|
201
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
202
|
+
return new errors_1.ConnectionError(`Unable to connect to DAX: ${parent.message}`, {
|
|
203
|
+
parent,
|
|
204
|
+
database: 'dax',
|
|
205
|
+
host,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function wrapDatabaseError(err, action) {
|
|
209
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
210
|
+
return errors_1.DatabaseError.from(parent, { message: `DAX ${action} failed: ${parent.message}` });
|
|
211
|
+
}
|
|
212
|
+
exports.default = DaxStore;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Deno KV store implementation.
|
|
4
|
+
*
|
|
5
|
+
* Deno KV is a globally-distributed, serverless key-value database. Outside
|
|
6
|
+
* a Deno runtime it is reached over the network with the KV Connect
|
|
7
|
+
* protocol, which is an HTTP/JSON transport. This class implements the
|
|
8
|
+
* minimal `NoSqlStore` marker interface and exposes an edge-KV
|
|
9
|
+
* `get`/`set`/`del`/`list`/`incr` surface.
|
|
10
|
+
*
|
|
11
|
+
* ## No canonical Node driver - HTTP over `fetch` (KV Connect assumption)
|
|
12
|
+
*
|
|
13
|
+
* There is no first-party Node client for Deno KV, so `library` is
|
|
14
|
+
* `'fetch'`. This store assumes a **KV Connect-style HTTP gateway** that
|
|
15
|
+
* exposes a small REST surface for the underlying database:
|
|
16
|
+
*
|
|
17
|
+
* - `get(key)` -> `GET /kv/values/<key>` (404 => `null`)
|
|
18
|
+
* - `set(k,v)` -> `PUT /kv/values/<key>` (body + optional `expireIn`)
|
|
19
|
+
* - `del(key)` -> `DELETE /kv/values/<key>`
|
|
20
|
+
* - `list(pref?)` -> `GET /kv/keys?prefix=` (returns the key names)
|
|
21
|
+
* - `incr(k,by?)` -> read-modify-write over `get`/`set` (documented as
|
|
22
|
+
* non-atomic; the native `atomic().sum()` op is not modeled here).
|
|
23
|
+
*
|
|
24
|
+
* Keys are treated as opaque strings (Deno KV's array key parts are joined
|
|
25
|
+
* by the caller). For tests (and callers with their own transport) an
|
|
26
|
+
* alternative HTTP client can be injected via `client`; when omitted a tiny
|
|
27
|
+
* internal `fetch`-based client is built at `connect()` time.
|
|
28
|
+
*
|
|
29
|
+
* ## Serialization
|
|
30
|
+
*
|
|
31
|
+
* String values are stored verbatim; every other value is `JSON.stringify`'d
|
|
32
|
+
* before being written.
|
|
33
|
+
*/
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.DenoKvStore = void 0;
|
|
36
|
+
exports.createFetchClient = createFetchClient;
|
|
37
|
+
const errors_1 = require("../../errors");
|
|
38
|
+
function serialize(value) {
|
|
39
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
40
|
+
}
|
|
41
|
+
/** Build a `fetch`-backed HTTP client for the KV Connect gateway. */
|
|
42
|
+
function createFetchClient(baseURL, accessToken) {
|
|
43
|
+
const root = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;
|
|
44
|
+
return {
|
|
45
|
+
async request(method, path, init) {
|
|
46
|
+
const url = new URL(root + path);
|
|
47
|
+
for (const [key, value] of Object.entries(init?.query ?? {})) {
|
|
48
|
+
if (value !== undefined)
|
|
49
|
+
url.searchParams.set(key, value);
|
|
50
|
+
}
|
|
51
|
+
const headers = {};
|
|
52
|
+
if (accessToken)
|
|
53
|
+
headers.Authorization = `Bearer ${accessToken}`;
|
|
54
|
+
if (init?.body !== undefined)
|
|
55
|
+
headers['Content-Type'] = 'application/json';
|
|
56
|
+
return fetch(url.toString(), { method, headers, body: init?.body });
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* `DenoKvStore` wraps a KV Connect HTTP gateway behind the `NoSqlStore`
|
|
62
|
+
* lifecycle and an edge-KV `get`/`set`/`del`/`list`/`incr` surface.
|
|
63
|
+
*/
|
|
64
|
+
class DenoKvStore {
|
|
65
|
+
constructor(options = {}) {
|
|
66
|
+
this.name = 'deno-kv';
|
|
67
|
+
this.library = 'fetch';
|
|
68
|
+
this.client = null;
|
|
69
|
+
this.connected = false;
|
|
70
|
+
this.options = options;
|
|
71
|
+
}
|
|
72
|
+
// ---------------------------------------------------------------------
|
|
73
|
+
// Connection lifecycle
|
|
74
|
+
// ---------------------------------------------------------------------
|
|
75
|
+
async connect() {
|
|
76
|
+
if (this.connected && this.client) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
this.client =
|
|
81
|
+
this.options.client ?? createFetchClient(this.options.url ?? '', this.options.accessToken);
|
|
82
|
+
this.connected = true;
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
this.client = null;
|
|
86
|
+
this.connected = false;
|
|
87
|
+
throw wrapConnectionError(err, this.options.url);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async disconnect() {
|
|
91
|
+
this.client = null;
|
|
92
|
+
this.connected = false;
|
|
93
|
+
}
|
|
94
|
+
isConnected() {
|
|
95
|
+
return this.connected && this.client !== null;
|
|
96
|
+
}
|
|
97
|
+
/** Returns the underlying (internal or injected) HTTP client. */
|
|
98
|
+
getClient() {
|
|
99
|
+
return this.requireClient();
|
|
100
|
+
}
|
|
101
|
+
requireClient() {
|
|
102
|
+
if (!this.client) {
|
|
103
|
+
throw new errors_1.ConnectionError('Not connected to Deno KV', {
|
|
104
|
+
database: 'deno-kv',
|
|
105
|
+
host: this.options.url,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return this.client;
|
|
109
|
+
}
|
|
110
|
+
valuePath(key) {
|
|
111
|
+
return `/kv/values/${encodeURIComponent(key)}`;
|
|
112
|
+
}
|
|
113
|
+
// ---------------------------------------------------------------------
|
|
114
|
+
// Key-value operations
|
|
115
|
+
// ---------------------------------------------------------------------
|
|
116
|
+
/** Read a key. Returns `null` on a 404 (missing key). */
|
|
117
|
+
async get(key) {
|
|
118
|
+
const client = this.requireClient();
|
|
119
|
+
try {
|
|
120
|
+
const res = await client.request('GET', this.valuePath(key));
|
|
121
|
+
if (res.status === 404)
|
|
122
|
+
return null;
|
|
123
|
+
if (!res.ok)
|
|
124
|
+
throw new Error(`HTTP ${res.status}`);
|
|
125
|
+
return await res.text();
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
throw wrapDatabaseError(err, 'GET');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Write `value` under `key`. Strings are stored verbatim; other values are
|
|
133
|
+
* JSON-serialized. `options.ttl` maps to `expireIn` (ms), `options.expiration`
|
|
134
|
+
* to `expireAt` (absolute Unix ms).
|
|
135
|
+
*/
|
|
136
|
+
async set(key, value, options = {}) {
|
|
137
|
+
const client = this.requireClient();
|
|
138
|
+
const query = {};
|
|
139
|
+
if (options.ttl !== undefined)
|
|
140
|
+
query.expireIn = String(options.ttl);
|
|
141
|
+
if (options.expiration !== undefined)
|
|
142
|
+
query.expireAt = String(options.expiration);
|
|
143
|
+
try {
|
|
144
|
+
const res = await client.request('PUT', this.valuePath(key), {
|
|
145
|
+
body: serialize(value),
|
|
146
|
+
query,
|
|
147
|
+
});
|
|
148
|
+
if (!res.ok)
|
|
149
|
+
throw new Error(`HTTP ${res.status}`);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
throw wrapDatabaseError(err, 'SET');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** Delete a key. */
|
|
156
|
+
async del(key) {
|
|
157
|
+
const client = this.requireClient();
|
|
158
|
+
try {
|
|
159
|
+
const res = await client.request('DELETE', this.valuePath(key));
|
|
160
|
+
if (!res.ok && res.status !== 404)
|
|
161
|
+
throw new Error(`HTTP ${res.status}`);
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
throw wrapDatabaseError(err, 'DEL');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** List key names, optionally filtered by `prefix`. */
|
|
168
|
+
async list(prefix) {
|
|
169
|
+
const client = this.requireClient();
|
|
170
|
+
try {
|
|
171
|
+
const res = await client.request('GET', '/kv/keys', { query: { prefix } });
|
|
172
|
+
if (!res.ok)
|
|
173
|
+
throw new Error(`HTTP ${res.status}`);
|
|
174
|
+
const body = await res.json();
|
|
175
|
+
const keys = body?.keys ?? [];
|
|
176
|
+
return keys;
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
throw wrapDatabaseError(err, 'LIST');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Increment the numeric value at `key` by `by` (default `1`). Implemented
|
|
184
|
+
* as a non-atomic read-modify-write over `get`/`set`.
|
|
185
|
+
*/
|
|
186
|
+
async incr(key, by = 1) {
|
|
187
|
+
const current = await this.get(key);
|
|
188
|
+
const next = (current === null ? 0 : Number(current)) + by;
|
|
189
|
+
await this.set(key, String(next));
|
|
190
|
+
return next;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
exports.DenoKvStore = DenoKvStore;
|
|
194
|
+
function wrapConnectionError(err, host) {
|
|
195
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
196
|
+
return new errors_1.ConnectionError(`Unable to connect to Deno KV: ${parent.message}`, {
|
|
197
|
+
parent,
|
|
198
|
+
database: 'deno-kv',
|
|
199
|
+
host,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function wrapDatabaseError(err, action) {
|
|
203
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
204
|
+
return errors_1.DatabaseError.from(parent, { message: `Deno KV ${action} failed: ${parent.message}` });
|
|
205
|
+
}
|
|
206
|
+
exports.default = DenoKvStore;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DgraphStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Dgraph store.
|
|
6
|
+
*
|
|
7
|
+
* Dgraph is a distributed, native graph database queried with DQL (its
|
|
8
|
+
* GraphQL-derived query language) rather than SQL. Data is modeled as nodes
|
|
9
|
+
* (identified by UIDs) and typed predicates/edges between them, with an
|
|
10
|
+
* optional schema defined via `alter`. It has no `Dialect`-shaped
|
|
11
|
+
* `query(sql)`/identifier-escaping surface, so this class implements the
|
|
12
|
+
* minimal `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes
|
|
13
|
+
* Dgraph's real primitives — parameterized DQL queries, JSON mutations, and
|
|
14
|
+
* schema `alter`/`dropAll` operations — directly.
|
|
15
|
+
*
|
|
16
|
+
* Built on the official `dgraph-js` gRPC driver. That driver is an optional
|
|
17
|
+
* peer dependency loaded lazily inside `connect()` (via `require`) so importing
|
|
18
|
+
* this module never forces the driver to be installed; tests inject a pre-built
|
|
19
|
+
* mock `client` instead and never reach the `require`.
|
|
20
|
+
*/
|
|
21
|
+
const errors_1 = require("../../errors");
|
|
22
|
+
/**
|
|
23
|
+
* `DgraphStore` wraps a `dgraph-js` `DgraphClient` and exposes Dgraph's real
|
|
24
|
+
* surface: `query()` for parameterized DQL reads, `mutate()` for JSON
|
|
25
|
+
* mutations (auto-committed), and `alter()`/`dropAll()` for schema/data
|
|
26
|
+
* management.
|
|
27
|
+
*/
|
|
28
|
+
class DgraphStore {
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.name = 'dgraph';
|
|
31
|
+
this.library = 'dgraph-js';
|
|
32
|
+
this.client = null;
|
|
33
|
+
/** The client stub, kept so `disconnect()` can close its gRPC channel. Null when a client is injected. */
|
|
34
|
+
this.stub = null;
|
|
35
|
+
this.connected = false;
|
|
36
|
+
this.options = options;
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------
|
|
39
|
+
// NoSqlStore lifecycle
|
|
40
|
+
// ---------------------------------------------------------------------
|
|
41
|
+
async connect() {
|
|
42
|
+
if (this.connected && this.client) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
if (this.options.client) {
|
|
47
|
+
// Injected mock: use it directly and never touch the real driver.
|
|
48
|
+
this.client = this.options.client;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Lazy-load the optional driver so importing this module never
|
|
52
|
+
// requires `dgraph-js` to be installed.
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
54
|
+
const dgraph = require('dgraph-js');
|
|
55
|
+
const stub = new dgraph.DgraphClientStub(this.options.address);
|
|
56
|
+
this.stub = stub;
|
|
57
|
+
this.client = new dgraph.DgraphClient(stub);
|
|
58
|
+
}
|
|
59
|
+
this.connected = true;
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
this.client = null;
|
|
63
|
+
this.stub = null;
|
|
64
|
+
this.connected = false;
|
|
65
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
66
|
+
throw new errors_1.ConnectionError(`Unable to connect to Dgraph: ${parent.message}`, {
|
|
67
|
+
parent,
|
|
68
|
+
database: 'dgraph',
|
|
69
|
+
host: this.options.address,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async disconnect() {
|
|
74
|
+
if (this.stub) {
|
|
75
|
+
this.stub.close();
|
|
76
|
+
this.stub = null;
|
|
77
|
+
}
|
|
78
|
+
this.client = null;
|
|
79
|
+
this.connected = false;
|
|
80
|
+
}
|
|
81
|
+
isConnected() {
|
|
82
|
+
return this.connected && this.client !== null;
|
|
83
|
+
}
|
|
84
|
+
/** Returns the underlying `dgraph-js` `DgraphClient` for anything not wrapped here. */
|
|
85
|
+
getClient() {
|
|
86
|
+
return this.requireClient();
|
|
87
|
+
}
|
|
88
|
+
requireClient() {
|
|
89
|
+
if (!this.client || !this.connected) {
|
|
90
|
+
throw new errors_1.ConnectionError('Dgraph client is not connected. Call connect() first.', {
|
|
91
|
+
database: 'dgraph',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return this.client;
|
|
95
|
+
}
|
|
96
|
+
wrapError(action, err) {
|
|
97
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
98
|
+
return errors_1.DatabaseError.from(parent, { message: `Dgraph ${action} failed: ${parent.message}` });
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------
|
|
101
|
+
// Query / mutate
|
|
102
|
+
// ---------------------------------------------------------------------
|
|
103
|
+
/**
|
|
104
|
+
* Runs a parameterized DQL query in a fresh transaction and returns the
|
|
105
|
+
* parsed JSON result. `vars` binds DQL query variables (e.g.
|
|
106
|
+
* `{ $name: 'alice' }`) sent separately from the query text. The
|
|
107
|
+
* transaction is always discarded in a `finally` — a read-only query never
|
|
108
|
+
* needs committing, and discarding releases its server-side resources.
|
|
109
|
+
*/
|
|
110
|
+
async query(dql, vars = {}) {
|
|
111
|
+
const client = this.requireClient();
|
|
112
|
+
const txn = client.newTxn();
|
|
113
|
+
try {
|
|
114
|
+
const res = await txn.queryWithVars(dql, vars);
|
|
115
|
+
return JSON.parse(res.getJson());
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
throw this.wrapError('query', err);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await txn.discard();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Applies a JSON mutation (`setJson`) and commits it immediately
|
|
126
|
+
* (`commitNow: true`), so no separate commit round trip is needed. The
|
|
127
|
+
* transaction is discarded in a `finally` as a safety net (committed
|
|
128
|
+
* transactions treat discard as a no-op).
|
|
129
|
+
*/
|
|
130
|
+
async mutate(setJson) {
|
|
131
|
+
const client = this.requireClient();
|
|
132
|
+
const txn = client.newTxn();
|
|
133
|
+
try {
|
|
134
|
+
return await txn.mutate({ setJson, commitNow: true });
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
throw this.wrapError('mutate', err);
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
await txn.discard();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ---------------------------------------------------------------------
|
|
144
|
+
// Schema / data management
|
|
145
|
+
// ---------------------------------------------------------------------
|
|
146
|
+
/**
|
|
147
|
+
* Alters the schema by forwarding a DQL schema definition (DDL) to
|
|
148
|
+
* `client.alter({ schema })`, e.g. `'name: string @index(exact) .'`.
|
|
149
|
+
*/
|
|
150
|
+
async alter(schema) {
|
|
151
|
+
const client = this.requireClient();
|
|
152
|
+
try {
|
|
153
|
+
return await client.alter({ schema });
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
throw this.wrapError('alter', err);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** Drops all data and schema in the cluster via `client.alter({ dropAll: true })`. */
|
|
160
|
+
async dropAll() {
|
|
161
|
+
const client = this.requireClient();
|
|
162
|
+
try {
|
|
163
|
+
return await client.alter({ dropAll: true });
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
throw this.wrapError('dropAll', err);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.DgraphStore = DgraphStore;
|
|
171
|
+
exports.default = DgraphStore;
|