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.
Files changed (310) hide show
  1. package/CHANGELOG.md +1111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +573 -0
  4. package/dist/audit/history-query.js +180 -0
  5. package/dist/audit/index.js +23 -0
  6. package/dist/audit/logger.js +236 -0
  7. package/dist/cache/cache-manager.js +84 -0
  8. package/dist/cache/index.js +16 -0
  9. package/dist/cache/redis-cluster-cache.js +557 -0
  10. package/dist/cli.js +2200 -0
  11. package/dist/compliance/audit-trail.js +68 -0
  12. package/dist/compliance/backup-verification.js +685 -0
  13. package/dist/compliance/breach-detector.js +505 -0
  14. package/dist/compliance/consent-record.js +227 -0
  15. package/dist/compliance/consent-versioning.js +331 -0
  16. package/dist/compliance/cross-border-log.js +530 -0
  17. package/dist/compliance/data-classifier.js +258 -0
  18. package/dist/compliance/data-lineage.js +565 -0
  19. package/dist/compliance/data-masker.js +303 -0
  20. package/dist/compliance/data-portability.js +265 -0
  21. package/dist/compliance/data-retention.js +195 -0
  22. package/dist/compliance/dsar-workflow.js +342 -0
  23. package/dist/compliance/field-encryption.js +223 -0
  24. package/dist/compliance/immutable-record.js +148 -0
  25. package/dist/compliance/index.js +260 -0
  26. package/dist/compliance/privacy-impact-assessment.js +364 -0
  27. package/dist/compliance/pseudonymization.js +269 -0
  28. package/dist/compliance/query-firewall.js +1182 -0
  29. package/dist/compliance/rate-limiter.js +580 -0
  30. package/dist/compliance/right-to-erasure.js +117 -0
  31. package/dist/compliance/row-level-security.js +246 -0
  32. package/dist/compliance/security-decorator.js +574 -0
  33. package/dist/compliance/security-monitor.js +525 -0
  34. package/dist/compliance/sensitive-data-discovery.js +476 -0
  35. package/dist/compliance/session-isolation.js +472 -0
  36. package/dist/compliance/tls-enforcer.js +108 -0
  37. package/dist/compliance/worm-storage.js +712 -0
  38. package/dist/connection-manager.js +198 -0
  39. package/dist/connection-pool.js +519 -0
  40. package/dist/decorators/audit.js +136 -0
  41. package/dist/decorators/belongs-to-many.js +115 -0
  42. package/dist/decorators/belongs-to.js +115 -0
  43. package/dist/decorators/check.js +435 -0
  44. package/dist/decorators/collate.js +329 -0
  45. package/dist/decorators/comment.js +205 -0
  46. package/dist/decorators/database-settings.js +236 -0
  47. package/dist/decorators/default.js +244 -0
  48. package/dist/decorators/encryption.js +235 -0
  49. package/dist/decorators/engine.js +97 -0
  50. package/dist/decorators/fk-constraints.js +594 -0
  51. package/dist/decorators/foreign-table.js +136 -0
  52. package/dist/decorators/generated.js +274 -0
  53. package/dist/decorators/has-many.js +127 -0
  54. package/dist/decorators/has-one.js +116 -0
  55. package/dist/decorators/hstore.js +129 -0
  56. package/dist/decorators/index.js +355 -0
  57. package/dist/decorators/json-column.js +83 -0
  58. package/dist/decorators/jsonb.js +101 -0
  59. package/dist/decorators/orm-decorators.js +425 -0
  60. package/dist/decorators/permissions.js +294 -0
  61. package/dist/decorators/procedure.js +210 -0
  62. package/dist/decorators/query-options.js +556 -0
  63. package/dist/decorators/range.js +167 -0
  64. package/dist/decorators/set-column.js +83 -0
  65. package/dist/decorators/spatial.js +114 -0
  66. package/dist/decorators/storage.js +580 -0
  67. package/dist/decorators/timezone.js +512 -0
  68. package/dist/decorators/trigger.js +90 -0
  69. package/dist/decorators/uuid.js +135 -0
  70. package/dist/decorators/view.js +258 -0
  71. package/dist/diagrams/chen-diagram.js +354 -0
  72. package/dist/diagrams/class-diagram.js +384 -0
  73. package/dist/diagrams/dependency-diagram.js +432 -0
  74. package/dist/diagrams/er-diagram.js +605 -0
  75. package/dist/diagrams/flow-diagram.js +394 -0
  76. package/dist/diagrams/gantt-diagram.js +411 -0
  77. package/dist/diagrams/index-diagram.js +353 -0
  78. package/dist/diagrams/index.js +184 -0
  79. package/dist/diagrams/migration-diagram.js +316 -0
  80. package/dist/diagrams/model-diagram.js +616 -0
  81. package/dist/diagrams/package-diagram.js +376 -0
  82. package/dist/diagrams/palette.js +85 -0
  83. package/dist/diagrams/relational-diagram.js +455 -0
  84. package/dist/diagrams/schemadoc-diagram.js +309 -0
  85. package/dist/diagrams/sequence-diagram.js +307 -0
  86. package/dist/diagrams/state-diagram.js +344 -0
  87. package/dist/diagrams/svg-dom.js +111 -0
  88. package/dist/diagrams/tree-diagram.js +250 -0
  89. package/dist/dialects/clickhouse/index.js +1742 -0
  90. package/dist/dialects/cockroachdb/index.js +4677 -0
  91. package/dist/dialects/cratedb/index.js +441 -0
  92. package/dist/dialects/databricks/index.js +517 -0
  93. package/dist/dialects/db2/index.js +2225 -0
  94. package/dist/dialects/dialect.js +720 -0
  95. package/dist/dialects/duckdb/index.js +2014 -0
  96. package/dist/dialects/exasol/index.js +357 -0
  97. package/dist/dialects/firebird/index.js +495 -0
  98. package/dist/dialects/greenplum/index.js +457 -0
  99. package/dist/dialects/hana/index.js +1741 -0
  100. package/dist/dialects/mariadb/index.js +3590 -0
  101. package/dist/dialects/mssql/index.js +2296 -0
  102. package/dist/dialects/mysql/index.js +4058 -0
  103. package/dist/dialects/oracle/index.js +2999 -0
  104. package/dist/dialects/postgres/index.js +5319 -0
  105. package/dist/dialects/query-stream-helper.js +152 -0
  106. package/dist/dialects/questdb/index.js +433 -0
  107. package/dist/dialects/redshift/index.js +2277 -0
  108. package/dist/dialects/singlestore/index.js +354 -0
  109. package/dist/dialects/snowflake/index.js +2082 -0
  110. package/dist/dialects/spanner/index.js +1768 -0
  111. package/dist/dialects/sqlite/index.js +3382 -0
  112. package/dist/dialects/tidb/index.js +377 -0
  113. package/dist/dialects/timescaledb/index.js +164 -0
  114. package/dist/dialects/trino/index.js +420 -0
  115. package/dist/dialects/turso/index.js +227 -0
  116. package/dist/dialects/vertica/index.js +317 -0
  117. package/dist/dialects/yugabytedb/index.js +424 -0
  118. package/dist/errors/index.js +472 -0
  119. package/dist/errors/utils.js +340 -0
  120. package/dist/errors.js +21 -0
  121. package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
  122. package/dist/extensions/catalog/mssql-features.js +147 -0
  123. package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
  124. package/dist/extensions/catalog/oracle-db2-features.js +196 -0
  125. package/dist/extensions/catalog/postgres-extensions.js +516 -0
  126. package/dist/extensions/index.js +71 -0
  127. package/dist/extensions/types.js +13 -0
  128. package/dist/foreign-data.js +173 -0
  129. package/dist/hooks/hooks-manager.js +350 -0
  130. package/dist/hooks/index.js +37 -0
  131. package/dist/index.js +463 -0
  132. package/dist/logging.js +335 -0
  133. package/dist/migrations/index.js +40 -0
  134. package/dist/migrations/migration.js +196 -0
  135. package/dist/migrations/migrator.js +411 -0
  136. package/dist/migrations/prormmigration.js +275 -0
  137. package/dist/migrations/query-interface.js +435 -0
  138. package/dist/migrations/seeder.js +353 -0
  139. package/dist/models/associations.js +852 -0
  140. package/dist/models/constraints.js +288 -0
  141. package/dist/models/data-types.js +2518 -0
  142. package/dist/models/decorators.js +445 -0
  143. package/dist/models/index.js +33 -0
  144. package/dist/models/indexes.js +531 -0
  145. package/dist/models/methods.js +382 -0
  146. package/dist/models/model-manager.js +103 -0
  147. package/dist/models/model.js +5349 -0
  148. package/dist/models/operators.js +67 -0
  149. package/dist/models/scopes.js +189 -0
  150. package/dist/models/typescript-types.js +26 -0
  151. package/dist/nosql/aerospike/index.js +205 -0
  152. package/dist/nosql/allegrograph/index.js +169 -0
  153. package/dist/nosql/arangodb/index.js +364 -0
  154. package/dist/nosql/azure-blob/index.js +206 -0
  155. package/dist/nosql/beanstalkd/index.js +231 -0
  156. package/dist/nosql/beequeue/index.js +210 -0
  157. package/dist/nosql/bigchaindb/index.js +195 -0
  158. package/dist/nosql/bigtable/index.js +224 -0
  159. package/dist/nosql/blazegraph/index.js +173 -0
  160. package/dist/nosql/bullmq/index.js +191 -0
  161. package/dist/nosql/cassandra/index.js +174 -0
  162. package/dist/nosql/chroma/index.js +190 -0
  163. package/dist/nosql/cloudflare-kv/index.js +220 -0
  164. package/dist/nosql/coherence/index.js +200 -0
  165. package/dist/nosql/cosmosdb/index.js +157 -0
  166. package/dist/nosql/couchbase/index.js +213 -0
  167. package/dist/nosql/dax/index.js +212 -0
  168. package/dist/nosql/deno-kv/index.js +206 -0
  169. package/dist/nosql/dgraph/index.js +171 -0
  170. package/dist/nosql/doris/index.js +169 -0
  171. package/dist/nosql/druid/index.js +162 -0
  172. package/dist/nosql/dynamodb/index.js +937 -0
  173. package/dist/nosql/elasticsearch/index.js +377 -0
  174. package/dist/nosql/etcd/index.js +502 -0
  175. package/dist/nosql/eventhubs/index.js +213 -0
  176. package/dist/nosql/eventstore/index.js +254 -0
  177. package/dist/nosql/faunadb/index.js +188 -0
  178. package/dist/nosql/firestore/index.js +177 -0
  179. package/dist/nosql/fluree/index.js +148 -0
  180. package/dist/nosql/fuseki/index.js +170 -0
  181. package/dist/nosql/gcs/index.js +172 -0
  182. package/dist/nosql/gearman/index.js +160 -0
  183. package/dist/nosql/geode/index.js +196 -0
  184. package/dist/nosql/graphdb/index.js +169 -0
  185. package/dist/nosql/graylog/index.js +188 -0
  186. package/dist/nosql/gridgain/index.js +171 -0
  187. package/dist/nosql/hazelcast/index.js +162 -0
  188. package/dist/nosql/hbase/index.js +230 -0
  189. package/dist/nosql/ignite/index.js +173 -0
  190. package/dist/nosql/immudb/index.js +184 -0
  191. package/dist/nosql/index.js +232 -0
  192. package/dist/nosql/infinispan/index.js +200 -0
  193. package/dist/nosql/influxdb/index.js +0 -0
  194. package/dist/nosql/kafka/index.js +234 -0
  195. package/dist/nosql/keyspaces/index.js +189 -0
  196. package/dist/nosql/kinesis/index.js +253 -0
  197. package/dist/nosql/leveldb/index.js +153 -0
  198. package/dist/nosql/lmdb/index.js +160 -0
  199. package/dist/nosql/loki/index.js +201 -0
  200. package/dist/nosql/marklogic/index.js +204 -0
  201. package/dist/nosql/materialize/index.js +145 -0
  202. package/dist/nosql/meilisearch/index.js +154 -0
  203. package/dist/nosql/memcached/index.js +223 -0
  204. package/dist/nosql/milvus/index.js +410 -0
  205. package/dist/nosql/minio/index.js +265 -0
  206. package/dist/nosql/momento/index.js +179 -0
  207. package/dist/nosql/mongodb/index.js +461 -0
  208. package/dist/nosql/nats/index.js +247 -0
  209. package/dist/nosql/nedb/index.js +164 -0
  210. package/dist/nosql/neo4j/index.js +450 -0
  211. package/dist/nosql/neptune/index.js +470 -0
  212. package/dist/nosql/nsq/index.js +200 -0
  213. package/dist/nosql/opensearch/index.js +186 -0
  214. package/dist/nosql/orientdb/index.js +175 -0
  215. package/dist/nosql/papertrail/index.js +200 -0
  216. package/dist/nosql/pinecone/index.js +0 -0
  217. package/dist/nosql/pinot/index.js +133 -0
  218. package/dist/nosql/pouchdb/index.js +172 -0
  219. package/dist/nosql/prometheus/index.js +174 -0
  220. package/dist/nosql/provendb/index.js +147 -0
  221. package/dist/nosql/pubsub/index.js +187 -0
  222. package/dist/nosql/pulsar/index.js +232 -0
  223. package/dist/nosql/qdrant/index.js +295 -0
  224. package/dist/nosql/qldb/index.js +192 -0
  225. package/dist/nosql/r2/index.js +281 -0
  226. package/dist/nosql/rabbitmq/index.js +237 -0
  227. package/dist/nosql/ravendb/index.js +175 -0
  228. package/dist/nosql/redis/index.js +607 -0
  229. package/dist/nosql/redpanda/index.js +237 -0
  230. package/dist/nosql/resque/index.js +203 -0
  231. package/dist/nosql/rethinkdb/index.js +232 -0
  232. package/dist/nosql/rocksdb/index.js +152 -0
  233. package/dist/nosql/rockset/index.js +126 -0
  234. package/dist/nosql/s3/index.js +298 -0
  235. package/dist/nosql/scylladb/index.js +178 -0
  236. package/dist/nosql/signoz/index.js +227 -0
  237. package/dist/nosql/sns/index.js +201 -0
  238. package/dist/nosql/solr/index.js +231 -0
  239. package/dist/nosql/splunk/index.js +227 -0
  240. package/dist/nosql/sqs/index.js +246 -0
  241. package/dist/nosql/stardog/index.js +169 -0
  242. package/dist/nosql/starrocks/index.js +170 -0
  243. package/dist/nosql/store.js +2 -0
  244. package/dist/nosql/sumologic/index.js +213 -0
  245. package/dist/nosql/surrealdb/index.js +179 -0
  246. package/dist/nosql/terminusdb/index.js +151 -0
  247. package/dist/nosql/tigergraph/index.js +469 -0
  248. package/dist/nosql/typesense/index.js +148 -0
  249. package/dist/nosql/unqlite/index.js +157 -0
  250. package/dist/nosql/upstash/index.js +167 -0
  251. package/dist/nosql/vercel-kv/index.js +166 -0
  252. package/dist/nosql/victoriametrics/index.js +213 -0
  253. package/dist/nosql/virtuoso/index.js +169 -0
  254. package/dist/nosql/weaviate/index.js +276 -0
  255. package/dist/operators/index.js +108 -0
  256. package/dist/operators.js +2690 -0
  257. package/dist/prisma-migrate/index.js +38 -0
  258. package/dist/prisma-migrate/migration-generator.js +125 -0
  259. package/dist/prisma-migrate/model-generator.js +172 -0
  260. package/dist/prisma-migrate/relations.js +100 -0
  261. package/dist/prisma-migrate/schema-parser.js +167 -0
  262. package/dist/prisma-migrate/type-mapper.js +40 -0
  263. package/dist/prorm.js +6832 -0
  264. package/dist/query-builders/cte-builder.js +80 -0
  265. package/dist/query-builders/functions/aggregate.js +390 -0
  266. package/dist/query-builders/functions/conditional.js +503 -0
  267. package/dist/query-builders/functions/datetime.js +695 -0
  268. package/dist/query-builders/functions/fulltext.js +439 -0
  269. package/dist/query-builders/functions/index.js +93 -0
  270. package/dist/query-builders/functions/json.js +427 -0
  271. package/dist/query-builders/functions/math.js +399 -0
  272. package/dist/query-builders/functions/string.js +518 -0
  273. package/dist/query-builders/functions/window.js +328 -0
  274. package/dist/query-builders/include-builder.js +323 -0
  275. package/dist/query-builders/index-expression-builder.js +242 -0
  276. package/dist/query-builders/index.js +161 -0
  277. package/dist/query-builders/insert-builder.js +164 -0
  278. package/dist/query-builders/model-helpers.js +38 -0
  279. package/dist/query-builders/order-limit-builder.js +239 -0
  280. package/dist/query-builders/sql-compiler.js +2040 -0
  281. package/dist/query-builders/subquery-builder.js +152 -0
  282. package/dist/query-builders/update-builder.js +182 -0
  283. package/dist/query-builders/view-builder.js +218 -0
  284. package/dist/query-builders/where-builder.js +1532 -0
  285. package/dist/query-interface.js +622 -0
  286. package/dist/query-optimizers/batch-optimizer.js +426 -0
  287. package/dist/query-optimizers/explain-plans.js +415 -0
  288. package/dist/query-optimizers/index.js +51 -0
  289. package/dist/query-optimizers/prepared-statement-cache.js +423 -0
  290. package/dist/query-optimizers/query-hints.js +438 -0
  291. package/dist/query-optimizers/query-optimizer.js +278 -0
  292. package/dist/query-optimizers/slow-query-logger.js +271 -0
  293. package/dist/replica-manager.js +507 -0
  294. package/dist/schema/index.js +15 -0
  295. package/dist/schema/migration-generator.js +374 -0
  296. package/dist/schema/schema-differ.js +549 -0
  297. package/dist/schema/types.js +6 -0
  298. package/dist/sql-constants.js +300 -0
  299. package/dist/sqlite-advanced.js +1047 -0
  300. package/dist/streams/index.js +12 -0
  301. package/dist/streams/transforms.js +178 -0
  302. package/dist/transaction.js +456 -0
  303. package/dist/types/index.js +180 -0
  304. package/dist/user-management.js +127 -0
  305. package/dist/utils/date.js +300 -0
  306. package/dist/utils/index.js +1079 -0
  307. package/dist/utils/string.js +161 -0
  308. package/dist/validators/index.js +19 -0
  309. package/dist/validators/validator.js +911 -0
  310. 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;