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,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CassandraStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Apache Cassandra (CQL) store.
|
|
6
|
+
*
|
|
7
|
+
* Cassandra is a wide-column, partition-key-based distributed store queried
|
|
8
|
+
* with CQL (Cassandra Query Language). While CQL looks superficially like
|
|
9
|
+
* SQL, it deliberately omits joins, arbitrary WHERE-clause filtering, and
|
|
10
|
+
* subqueries: every query must be answerable from a single partition (or an
|
|
11
|
+
* explicitly designed secondary index / materialized view), and data is
|
|
12
|
+
* modelled query-first around partition and clustering keys. That model does
|
|
13
|
+
* not fit the SQL-shaped `Dialect` interface (`src/dialects/dialect.ts`), so
|
|
14
|
+
* this store implements the minimal `NoSqlStore` marker interface
|
|
15
|
+
* (`src/nosql/store.ts`) and exposes Cassandra's own CQL execution surface
|
|
16
|
+
* directly rather than pretending to be a relational dialect.
|
|
17
|
+
*
|
|
18
|
+
* Built on the `cassandra-driver` (DataStax Node.js driver). The driver is an
|
|
19
|
+
* optional peer dependency and is loaded lazily inside `connect()` (via
|
|
20
|
+
* `require`) so importing this module never forces the driver to be
|
|
21
|
+
* installed; tests inject a pre-built mock `Client` instead.
|
|
22
|
+
*/
|
|
23
|
+
const errors_1 = require("../../errors");
|
|
24
|
+
/**
|
|
25
|
+
* `CassandraStore` wraps a `cassandra-driver` `Client` and exposes CQL
|
|
26
|
+
* execution (`execute`), atomic multi-statement batches (`batch`), and a few
|
|
27
|
+
* parameterized convenience helpers (`insert`, `selectAll`).
|
|
28
|
+
*
|
|
29
|
+
* Statements are prepared by default (`prepare: true`) so the driver can cache
|
|
30
|
+
* query metadata, infer parameter types, and route requests to replica nodes
|
|
31
|
+
* that own the partition — the recommended default for anything run more than
|
|
32
|
+
* once.
|
|
33
|
+
*/
|
|
34
|
+
class CassandraStore {
|
|
35
|
+
constructor(options = {}) {
|
|
36
|
+
this.name = 'cassandra';
|
|
37
|
+
this.library = 'cassandra-driver';
|
|
38
|
+
this.client = null;
|
|
39
|
+
this.connected = false;
|
|
40
|
+
this.options = options;
|
|
41
|
+
}
|
|
42
|
+
// ---------------------------------------------------------------------
|
|
43
|
+
// NoSqlStore lifecycle
|
|
44
|
+
// ---------------------------------------------------------------------
|
|
45
|
+
async connect() {
|
|
46
|
+
if (this.connected && this.client) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
let client = this.options.client;
|
|
51
|
+
if (!client) {
|
|
52
|
+
// Lazy-load the optional driver so importing this module never
|
|
53
|
+
// requires `cassandra-driver` to be installed. Tests inject a mock
|
|
54
|
+
// `client` above and never reach this branch.
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
56
|
+
const cql = require('cassandra-driver');
|
|
57
|
+
client = new cql.Client({
|
|
58
|
+
contactPoints: this.options.contactPoints,
|
|
59
|
+
localDataCenter: this.options.localDataCenter,
|
|
60
|
+
keyspace: this.options.keyspace,
|
|
61
|
+
credentials: this.options.credentials,
|
|
62
|
+
...this.options.clientOptions,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
await client.connect();
|
|
66
|
+
this.client = client;
|
|
67
|
+
this.connected = true;
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
this.client = null;
|
|
71
|
+
this.connected = false;
|
|
72
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
73
|
+
throw new errors_1.ConnectionError(`Unable to connect to Cassandra: ${parent.message}`, {
|
|
74
|
+
parent,
|
|
75
|
+
database: 'cassandra',
|
|
76
|
+
host: this.options.contactPoints?.[0],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async disconnect() {
|
|
81
|
+
if (this.client) {
|
|
82
|
+
try {
|
|
83
|
+
await this.client.shutdown();
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
this.client = null;
|
|
87
|
+
this.connected = false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
this.connected = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
isConnected() {
|
|
95
|
+
return this.connected && this.client !== null;
|
|
96
|
+
}
|
|
97
|
+
/** Returns the underlying `cassandra-driver` `Client` for anything not wrapped here. */
|
|
98
|
+
getClient() {
|
|
99
|
+
return this.requireClient();
|
|
100
|
+
}
|
|
101
|
+
requireClient() {
|
|
102
|
+
if (!this.client || !this.connected) {
|
|
103
|
+
throw new errors_1.ConnectionError('Cassandra client is not connected. Call connect() first.', {
|
|
104
|
+
database: 'cassandra',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return this.client;
|
|
108
|
+
}
|
|
109
|
+
wrapError(action, err) {
|
|
110
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
111
|
+
return errors_1.DatabaseError.from(parent, { message: `Cassandra ${action} failed: ${parent.message}` });
|
|
112
|
+
}
|
|
113
|
+
// ---------------------------------------------------------------------
|
|
114
|
+
// CQL execution
|
|
115
|
+
// ---------------------------------------------------------------------
|
|
116
|
+
/**
|
|
117
|
+
* Execute a single CQL statement with optional bound `params`. Statements
|
|
118
|
+
* are prepared by default (`prepare: true`); pass `opts.prepare = false` to
|
|
119
|
+
* run a one-off unprepared. Any other driver query options (consistency,
|
|
120
|
+
* fetchSize, pageState, ...) are forwarded via `opts`. Returns the full
|
|
121
|
+
* driver result (with `.rows`).
|
|
122
|
+
*/
|
|
123
|
+
async execute(query, params = [], opts = {}) {
|
|
124
|
+
const client = this.requireClient();
|
|
125
|
+
try {
|
|
126
|
+
return (await client.execute(query, params, { prepare: true, ...opts }));
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
throw this.wrapError(`execute (${query})`, err);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Execute multiple statements as a single logged batch (atomic across the
|
|
134
|
+
* statements, though not isolated — Cassandra batches are not SQL
|
|
135
|
+
* transactions). Each entry is a `{ query, params }` pair. Prepared by
|
|
136
|
+
* default; forward other driver batch options via `opts`.
|
|
137
|
+
*/
|
|
138
|
+
async batch(queries, opts = {}) {
|
|
139
|
+
const client = this.requireClient();
|
|
140
|
+
try {
|
|
141
|
+
return await client.batch(queries, { prepare: true, ...opts });
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
throw this.wrapError('batch', err);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ---------------------------------------------------------------------
|
|
148
|
+
// Convenience helpers
|
|
149
|
+
// ---------------------------------------------------------------------
|
|
150
|
+
/**
|
|
151
|
+
* Convenience `INSERT`: builds a parameterized
|
|
152
|
+
* `INSERT INTO table (cols...) VALUES (?, ?, ...)` from `obj`'s keys and
|
|
153
|
+
* executes it (prepared). For upserts with TTL, IF NOT EXISTS, or other
|
|
154
|
+
* clauses, write the CQL yourself and call `execute()`.
|
|
155
|
+
*/
|
|
156
|
+
async insert(table, obj, opts = {}) {
|
|
157
|
+
const columns = Object.keys(obj);
|
|
158
|
+
if (columns.length === 0) {
|
|
159
|
+
throw new errors_1.DatabaseError('insert() requires at least one column', {
|
|
160
|
+
original: 'empty insert object',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const placeholders = columns.map(() => '?').join(', ');
|
|
164
|
+
const query = `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${placeholders})`;
|
|
165
|
+
const params = columns.map((c) => obj[c]);
|
|
166
|
+
return this.execute(query, params, opts);
|
|
167
|
+
}
|
|
168
|
+
/** Convenience `SELECT * FROM table`. Returns the full driver result (with `.rows`). */
|
|
169
|
+
async selectAll(table, opts = {}) {
|
|
170
|
+
return this.execute(`SELECT * FROM ${table}`, [], opts);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
exports.CassandraStore = CassandraStore;
|
|
174
|
+
exports.default = CassandraStore;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Chroma (ChromaDB) vector-database store.
|
|
4
|
+
*
|
|
5
|
+
* Chroma is an embedding database organized around *collections*: a
|
|
6
|
+
* collection holds records that are `{ id, embedding, metadata?, document? }`
|
|
7
|
+
* tuples, and the core operation is an approximate-nearest-neighbor `query`
|
|
8
|
+
* over a collection's embeddings (optionally narrowed by a metadata `where`
|
|
9
|
+
* filter) - not SQL, not joins, not a transaction log. None of that fits
|
|
10
|
+
* the SQL-shaped `Dialect` interface used by the SQL dialects in this repo,
|
|
11
|
+
* so this class implements the minimal `NoSqlStore` marker interface
|
|
12
|
+
* (`src/nosql/store.ts`) and exposes Chroma's real collection- and
|
|
13
|
+
* embedding-level operations directly.
|
|
14
|
+
*
|
|
15
|
+
* Uses the `chromadb` driver, lazy-loaded inside `connect()` via `require()`
|
|
16
|
+
* so the dependency is only needed when a Chroma store is actually
|
|
17
|
+
* constructed (tests inject a pre-built mock `client` instead). The client
|
|
18
|
+
* talks to Chroma's HTTP API and is stateless, so `connect()`/`disconnect()`
|
|
19
|
+
* construct/discard the client rather than opening a real socket.
|
|
20
|
+
*
|
|
21
|
+
* Every embedding-level method takes a collection *name*; the underlying
|
|
22
|
+
* `Collection` handle is resolved (and cached) via
|
|
23
|
+
* `client.getOrCreateCollection(...)` so callers never have to thread a
|
|
24
|
+
* collection object through by hand.
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.ChromaStore = void 0;
|
|
28
|
+
const errors_1 = require("../../errors");
|
|
29
|
+
function wrapConnectionError(err, path) {
|
|
30
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
31
|
+
const message = /econnrefused|fetch failed/i.test(parent.message)
|
|
32
|
+
? 'Connection refused'
|
|
33
|
+
: `Unable to connect to Chroma: ${parent.message}`;
|
|
34
|
+
return new errors_1.ConnectionError(message, { parent, database: 'chroma', host: path });
|
|
35
|
+
}
|
|
36
|
+
function wrapDatabaseError(err, message) {
|
|
37
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
38
|
+
const combined = message ? `${message}: ${parent.message}` : parent.message;
|
|
39
|
+
return errors_1.DatabaseError.from(parent, { message: combined });
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `ChromaStore` wraps a `chromadb` `ChromaClient` and exposes Chroma's
|
|
43
|
+
* collection management plus the embedding data-plane operations
|
|
44
|
+
* (add/query/get/delete) as a typed, promise-based API.
|
|
45
|
+
*/
|
|
46
|
+
class ChromaStore {
|
|
47
|
+
constructor(options = {}) {
|
|
48
|
+
this.name = 'chroma';
|
|
49
|
+
this.library = 'chromadb';
|
|
50
|
+
this.client = null;
|
|
51
|
+
this.connected = false;
|
|
52
|
+
/** One `Collection` handle per collection name, reused across calls. */
|
|
53
|
+
this.collectionCache = new Map();
|
|
54
|
+
this.options = options;
|
|
55
|
+
}
|
|
56
|
+
// ---------------------------------------------------------------------
|
|
57
|
+
// Connection lifecycle
|
|
58
|
+
// ---------------------------------------------------------------------
|
|
59
|
+
async connect() {
|
|
60
|
+
if (this.connected && this.client) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
if (this.options.client) {
|
|
65
|
+
// A client was injected (e.g. a test mock) - use it as-is and skip
|
|
66
|
+
// the driver require()/new ChromaClient() step.
|
|
67
|
+
this.client = this.options.client;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
71
|
+
const { ChromaClient } = require('chromadb');
|
|
72
|
+
this.client = new ChromaClient({ path: this.options.path });
|
|
73
|
+
}
|
|
74
|
+
this.connected = true;
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
this.client = null;
|
|
78
|
+
this.connected = false;
|
|
79
|
+
throw wrapConnectionError(err, this.options.path);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async disconnect() {
|
|
83
|
+
// The Chroma client is a stateless HTTP client - there is no socket to
|
|
84
|
+
// close, so "disconnecting" just drops the client + cached handles.
|
|
85
|
+
this.client = null;
|
|
86
|
+
this.connected = false;
|
|
87
|
+
this.collectionCache.clear();
|
|
88
|
+
}
|
|
89
|
+
isConnected() {
|
|
90
|
+
return this.connected && this.client !== null;
|
|
91
|
+
}
|
|
92
|
+
/** Returns the underlying `ChromaClient` for anything not wrapped here. */
|
|
93
|
+
getClient() {
|
|
94
|
+
return this.requireClient();
|
|
95
|
+
}
|
|
96
|
+
requireClient() {
|
|
97
|
+
if (!this.client) {
|
|
98
|
+
throw new errors_1.ConnectionError('Not connected to Chroma', { database: 'chroma' });
|
|
99
|
+
}
|
|
100
|
+
return this.client;
|
|
101
|
+
}
|
|
102
|
+
async exec(fn, action) {
|
|
103
|
+
const client = this.requireClient();
|
|
104
|
+
try {
|
|
105
|
+
return await fn(client);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
throw wrapDatabaseError(err, `Chroma ${action} failed`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Resolve (and cache) a `Collection` handle for `name` via `getOrCreateCollection`. */
|
|
112
|
+
async resolveCollection(name) {
|
|
113
|
+
const cached = this.collectionCache.get(name);
|
|
114
|
+
if (cached) {
|
|
115
|
+
return cached;
|
|
116
|
+
}
|
|
117
|
+
const collection = await this.requireClient().getOrCreateCollection({ name });
|
|
118
|
+
this.collectionCache.set(name, collection);
|
|
119
|
+
return collection;
|
|
120
|
+
}
|
|
121
|
+
// ---------------------------------------------------------------------
|
|
122
|
+
// Collection management
|
|
123
|
+
// ---------------------------------------------------------------------
|
|
124
|
+
/** Create a new collection. Fails if a collection with `name` already exists. */
|
|
125
|
+
async createCollection(name, options = {}) {
|
|
126
|
+
return this.exec(async (c) => {
|
|
127
|
+
const collection = await c.createCollection({ name, ...options });
|
|
128
|
+
this.collectionCache.set(name, collection);
|
|
129
|
+
return collection;
|
|
130
|
+
}, 'CREATE COLLECTION');
|
|
131
|
+
}
|
|
132
|
+
/** Get an existing collection, creating it if it doesn't exist. Idempotent. */
|
|
133
|
+
async getOrCreateCollection(name, options = {}) {
|
|
134
|
+
return this.exec(async (c) => {
|
|
135
|
+
const collection = await c.getOrCreateCollection({ name, ...options });
|
|
136
|
+
this.collectionCache.set(name, collection);
|
|
137
|
+
return collection;
|
|
138
|
+
}, 'GET OR CREATE COLLECTION');
|
|
139
|
+
}
|
|
140
|
+
/** Delete a collection and all of its embeddings. */
|
|
141
|
+
async deleteCollection(name) {
|
|
142
|
+
return this.exec(async (c) => {
|
|
143
|
+
const result = await c.deleteCollection({ name });
|
|
144
|
+
this.collectionCache.delete(name);
|
|
145
|
+
return result;
|
|
146
|
+
}, 'DELETE COLLECTION');
|
|
147
|
+
}
|
|
148
|
+
// ---------------------------------------------------------------------
|
|
149
|
+
// Embedding data plane
|
|
150
|
+
// ---------------------------------------------------------------------
|
|
151
|
+
/**
|
|
152
|
+
* Add embeddings to a collection. `ids`/`embeddings` (and optional
|
|
153
|
+
* `metadatas`/`documents`) are index-aligned parallel arrays - the i-th
|
|
154
|
+
* id/embedding/metadata/document all describe the same record.
|
|
155
|
+
*/
|
|
156
|
+
async addEmbeddings(collection, params) {
|
|
157
|
+
return this.exec(async () => {
|
|
158
|
+
const col = await this.resolveCollection(collection);
|
|
159
|
+
return col.add(params);
|
|
160
|
+
}, 'ADD');
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Find, for each query embedding, the `nResults` closest records in a
|
|
164
|
+
* collection (optionally narrowed by a metadata `where` filter). Returns
|
|
165
|
+
* the driver's raw response (`{ ids, distances, metadatas, documents, ... }`,
|
|
166
|
+
* each an array-per-query-embedding).
|
|
167
|
+
*/
|
|
168
|
+
async query(collection, params) {
|
|
169
|
+
return this.exec(async () => {
|
|
170
|
+
const col = await this.resolveCollection(collection);
|
|
171
|
+
return col.query(params);
|
|
172
|
+
}, 'QUERY');
|
|
173
|
+
}
|
|
174
|
+
/** Fetch records by id (and/or a metadata `where` filter) from a collection. */
|
|
175
|
+
async get(collection, params) {
|
|
176
|
+
return this.exec(async () => {
|
|
177
|
+
const col = await this.resolveCollection(collection);
|
|
178
|
+
return col.get(params);
|
|
179
|
+
}, 'GET');
|
|
180
|
+
}
|
|
181
|
+
/** Delete records from a collection by id (and/or a metadata `where` filter). */
|
|
182
|
+
async deleteEmbeddings(collection, params) {
|
|
183
|
+
return this.exec(async () => {
|
|
184
|
+
const col = await this.resolveCollection(collection);
|
|
185
|
+
return col.delete(params);
|
|
186
|
+
}, 'DELETE');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
exports.ChromaStore = ChromaStore;
|
|
190
|
+
exports.default = ChromaStore;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cloudflare Workers KV store implementation.
|
|
4
|
+
*
|
|
5
|
+
* Cloudflare Workers KV is a globally-distributed, eventually-consistent
|
|
6
|
+
* key-value store exposed over Cloudflare's REST API. It has no query
|
|
7
|
+
* language and does not fit the SQL-shaped `Dialect` interface, so this
|
|
8
|
+
* class implements the minimal `NoSqlStore` marker interface and exposes a
|
|
9
|
+
* small edge-KV surface (`get`/`set`/`del`/`list`/`incr`) mapped onto the
|
|
10
|
+
* REST endpoints.
|
|
11
|
+
*
|
|
12
|
+
* ## No canonical driver - HTTP over `fetch`
|
|
13
|
+
*
|
|
14
|
+
* Workers KV has no first-party Node client; it is just an HTTP/JSON API.
|
|
15
|
+
* This store talks to it with the global `fetch` (so `library` is
|
|
16
|
+
* `'fetch'`). For tests (and callers who want their own transport) an
|
|
17
|
+
* alternative HTTP client can be injected via `client`; when omitted a tiny
|
|
18
|
+
* internal `fetch`-based client is built at `connect()` time using the
|
|
19
|
+
* account/namespace/token options.
|
|
20
|
+
*
|
|
21
|
+
* ## Endpoints wrapped
|
|
22
|
+
*
|
|
23
|
+
* All under `/accounts/<accountId>/storage/kv/namespaces/<namespaceId>`:
|
|
24
|
+
* - `get(key)` -> `GET .../values/<key>` (404 => `null`)
|
|
25
|
+
* - `set(k,v)` -> `PUT .../values/<key>` (body + optional expiration)
|
|
26
|
+
* - `del(key)` -> `DELETE .../values/<key>`
|
|
27
|
+
* - `list(pref?)` -> `GET .../keys?prefix=` (returns the key names)
|
|
28
|
+
* - `incr(k,by?)` -> read-modify-write over `get`/`set` (KV has no atomic
|
|
29
|
+
* increment; documented as non-atomic).
|
|
30
|
+
*
|
|
31
|
+
* ## Serialization
|
|
32
|
+
*
|
|
33
|
+
* String values are stored verbatim; every other value is `JSON.stringify`'d
|
|
34
|
+
* before being written.
|
|
35
|
+
*/
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.CloudflareKvStore = exports.DEFAULT_CLOUDFLARE_API_BASE_URL = void 0;
|
|
38
|
+
exports.createFetchClient = createFetchClient;
|
|
39
|
+
const errors_1 = require("../../errors");
|
|
40
|
+
/** Default Cloudflare API base URL. */
|
|
41
|
+
exports.DEFAULT_CLOUDFLARE_API_BASE_URL = 'https://api.cloudflare.com/client/v4';
|
|
42
|
+
function serialize(value) {
|
|
43
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
44
|
+
}
|
|
45
|
+
/** Build a `fetch`-backed HTTP client for the Cloudflare KV REST API. */
|
|
46
|
+
function createFetchClient(baseURL, apiToken) {
|
|
47
|
+
const root = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;
|
|
48
|
+
return {
|
|
49
|
+
async request(method, path, init) {
|
|
50
|
+
const url = new URL(root + path);
|
|
51
|
+
for (const [key, value] of Object.entries(init?.query ?? {})) {
|
|
52
|
+
if (value !== undefined)
|
|
53
|
+
url.searchParams.set(key, value);
|
|
54
|
+
}
|
|
55
|
+
const headers = {};
|
|
56
|
+
if (apiToken)
|
|
57
|
+
headers.Authorization = `Bearer ${apiToken}`;
|
|
58
|
+
if (init?.body !== undefined)
|
|
59
|
+
headers['Content-Type'] = 'text/plain';
|
|
60
|
+
return fetch(url.toString(), { method, headers, body: init?.body });
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* `CloudflareKvStore` wraps the Cloudflare Workers KV REST API behind the
|
|
66
|
+
* `NoSqlStore` lifecycle and an edge-KV `get`/`set`/`del`/`list`/`incr`
|
|
67
|
+
* surface.
|
|
68
|
+
*/
|
|
69
|
+
class CloudflareKvStore {
|
|
70
|
+
constructor(options = {}) {
|
|
71
|
+
this.name = 'cloudflare-kv';
|
|
72
|
+
this.library = 'fetch';
|
|
73
|
+
this.client = null;
|
|
74
|
+
this.connected = false;
|
|
75
|
+
this.options = options;
|
|
76
|
+
this.baseURL = options.baseURL ?? exports.DEFAULT_CLOUDFLARE_API_BASE_URL;
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------
|
|
79
|
+
// Connection lifecycle
|
|
80
|
+
// ---------------------------------------------------------------------
|
|
81
|
+
async connect() {
|
|
82
|
+
if (this.connected && this.client) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
this.client =
|
|
87
|
+
this.options.client ?? createFetchClient(this.baseURL, this.options.apiToken);
|
|
88
|
+
this.connected = true;
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
this.client = null;
|
|
92
|
+
this.connected = false;
|
|
93
|
+
throw wrapConnectionError(err, this.baseURL);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async disconnect() {
|
|
97
|
+
this.client = null;
|
|
98
|
+
this.connected = false;
|
|
99
|
+
}
|
|
100
|
+
isConnected() {
|
|
101
|
+
return this.connected && this.client !== null;
|
|
102
|
+
}
|
|
103
|
+
/** Returns the underlying (internal or injected) HTTP client. */
|
|
104
|
+
getClient() {
|
|
105
|
+
return this.requireClient();
|
|
106
|
+
}
|
|
107
|
+
requireClient() {
|
|
108
|
+
if (!this.client) {
|
|
109
|
+
throw new errors_1.ConnectionError('Not connected to Cloudflare KV', {
|
|
110
|
+
database: 'cloudflare-kv',
|
|
111
|
+
host: this.baseURL,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return this.client;
|
|
115
|
+
}
|
|
116
|
+
namespacePath() {
|
|
117
|
+
const { accountId, namespaceId } = this.options;
|
|
118
|
+
return `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}`;
|
|
119
|
+
}
|
|
120
|
+
valuePath(key) {
|
|
121
|
+
return `${this.namespacePath()}/values/${encodeURIComponent(key)}`;
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------
|
|
124
|
+
// Key-value operations
|
|
125
|
+
// ---------------------------------------------------------------------
|
|
126
|
+
/** Read a key. Returns `null` on a 404 (missing key). */
|
|
127
|
+
async get(key) {
|
|
128
|
+
const client = this.requireClient();
|
|
129
|
+
try {
|
|
130
|
+
const res = await client.request('GET', this.valuePath(key));
|
|
131
|
+
if (res.status === 404)
|
|
132
|
+
return null;
|
|
133
|
+
if (!res.ok)
|
|
134
|
+
throw new Error(`HTTP ${res.status}`);
|
|
135
|
+
return await res.text();
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
throw wrapDatabaseError(err, 'GET');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Write `value` under `key`. Strings are stored verbatim; other values are
|
|
143
|
+
* JSON-serialized. `options.ttl` maps to `expiration_ttl` (seconds),
|
|
144
|
+
* `options.expiration` to `expiration` (absolute Unix seconds).
|
|
145
|
+
*/
|
|
146
|
+
async set(key, value, options = {}) {
|
|
147
|
+
const client = this.requireClient();
|
|
148
|
+
const query = {};
|
|
149
|
+
if (options.ttl !== undefined)
|
|
150
|
+
query.expiration_ttl = String(options.ttl);
|
|
151
|
+
if (options.expiration !== undefined)
|
|
152
|
+
query.expiration = String(options.expiration);
|
|
153
|
+
try {
|
|
154
|
+
const res = await client.request('PUT', this.valuePath(key), {
|
|
155
|
+
body: serialize(value),
|
|
156
|
+
query,
|
|
157
|
+
});
|
|
158
|
+
if (!res.ok)
|
|
159
|
+
throw new Error(`HTTP ${res.status}`);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
throw wrapDatabaseError(err, 'SET');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/** Delete a key. */
|
|
166
|
+
async del(key) {
|
|
167
|
+
const client = this.requireClient();
|
|
168
|
+
try {
|
|
169
|
+
const res = await client.request('DELETE', this.valuePath(key));
|
|
170
|
+
if (!res.ok && res.status !== 404)
|
|
171
|
+
throw new Error(`HTTP ${res.status}`);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
throw wrapDatabaseError(err, 'DEL');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** List key names, optionally filtered by `prefix`. */
|
|
178
|
+
async list(prefix) {
|
|
179
|
+
const client = this.requireClient();
|
|
180
|
+
try {
|
|
181
|
+
const res = await client.request('GET', `${this.namespacePath()}/keys`, {
|
|
182
|
+
query: { prefix },
|
|
183
|
+
});
|
|
184
|
+
if (!res.ok)
|
|
185
|
+
throw new Error(`HTTP ${res.status}`);
|
|
186
|
+
const body = await res.json();
|
|
187
|
+
const result = body?.result ?? [];
|
|
188
|
+
return result.map((entry) => entry.name);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
throw wrapDatabaseError(err, 'LIST');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Increment the numeric value at `key` by `by` (default `1`). Workers KV
|
|
196
|
+
* has no atomic increment, so this is a non-atomic read-modify-write.
|
|
197
|
+
*/
|
|
198
|
+
async incr(key, by = 1) {
|
|
199
|
+
const current = await this.get(key);
|
|
200
|
+
const next = (current === null ? 0 : Number(current)) + by;
|
|
201
|
+
await this.set(key, String(next));
|
|
202
|
+
return next;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
exports.CloudflareKvStore = CloudflareKvStore;
|
|
206
|
+
function wrapConnectionError(err, host) {
|
|
207
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
208
|
+
return new errors_1.ConnectionError(`Unable to connect to Cloudflare KV: ${parent.message}`, {
|
|
209
|
+
parent,
|
|
210
|
+
database: 'cloudflare-kv',
|
|
211
|
+
host,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
function wrapDatabaseError(err, action) {
|
|
215
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
216
|
+
return errors_1.DatabaseError.from(parent, {
|
|
217
|
+
message: `Cloudflare KV ${action} failed: ${parent.message}`,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
exports.default = CloudflareKvStore;
|