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,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PubSubStore = void 0;
4
+ /**
5
+ * Google Cloud Pub/Sub store.
6
+ *
7
+ * Pub/Sub is a managed, topic-and-subscription messaging service. It has no
8
+ * query language and no SQL-shaped access pattern, so this store implements the
9
+ * minimal `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes
10
+ * Pub/Sub's real operations: publishing messages to a topic (`publish`),
11
+ * receiving messages on a subscription via an event listener (`subscribe`), and
12
+ * topic/subscription administration (`createTopic`, `createSubscription`).
13
+ *
14
+ * Built on `@google-cloud/pubsub`: `new PubSub()` yields a client whose
15
+ * `topic(name).publishMessage(...)` publishes and whose
16
+ * `subscription(name).on('message', ...)` streams messages. The driver is
17
+ * loaded lazily inside `connect()` via `require`, and tests inject a mock
18
+ * client through the `client` option so no real driver or network is used.
19
+ *
20
+ * Message encoding: `publish()` accepts a `string` (UTF-8 encoded), a `Buffer`
21
+ * (sent as-is), or any other JSON-serializable value (`JSON.stringify`d then
22
+ * UTF-8 encoded). The bytes become the message `data`.
23
+ */
24
+ const errors_1 = require("../../errors");
25
+ /** Encode a message into the `Buffer` Pub/Sub carries as message `data`. */
26
+ function toData(message) {
27
+ if (Buffer.isBuffer(message))
28
+ return message;
29
+ if (typeof message === 'string')
30
+ return Buffer.from(message, 'utf8');
31
+ return Buffer.from(JSON.stringify(message), 'utf8');
32
+ }
33
+ /**
34
+ * `PubSubStore` wraps a `@google-cloud/pubsub` client and exposes topic
35
+ * publishing, subscription listening, and topic/subscription administration.
36
+ */
37
+ class PubSubStore {
38
+ constructor(options = {}) {
39
+ this.name = 'pubsub';
40
+ this.library = '@google-cloud/pubsub';
41
+ this.client = null;
42
+ this.connected = false;
43
+ /** Subscription objects that have live listeners, tracked for `disconnect()`. */
44
+ this.subscriptions = new Set();
45
+ this.options = options;
46
+ }
47
+ // ---------------------------------------------------------------------
48
+ // Lifecycle
49
+ // ---------------------------------------------------------------------
50
+ async connect() {
51
+ if (this.connected && this.client)
52
+ return;
53
+ try {
54
+ if (this.options.client) {
55
+ this.client = this.options.client;
56
+ }
57
+ else {
58
+ const { PubSub } = require('@google-cloud/pubsub');
59
+ this.client = new PubSub({
60
+ projectId: this.options.projectId,
61
+ keyFilename: this.options.keyFilename,
62
+ apiEndpoint: this.options.apiEndpoint,
63
+ });
64
+ }
65
+ this.connected = true;
66
+ }
67
+ catch (err) {
68
+ this.client = null;
69
+ this.connected = false;
70
+ throw new errors_1.ConnectionError(`Failed to connect to Pub/Sub: ${err instanceof Error ? err.message : String(err)}`, { parent: err instanceof Error ? err : undefined, database: 'pubsub' });
71
+ }
72
+ }
73
+ async disconnect() {
74
+ for (const subscription of this.subscriptions) {
75
+ try {
76
+ subscription.removeAllListeners?.();
77
+ await subscription.close?.();
78
+ }
79
+ catch {
80
+ // Best-effort teardown.
81
+ }
82
+ }
83
+ this.subscriptions.clear();
84
+ try {
85
+ await this.client?.close?.();
86
+ }
87
+ finally {
88
+ this.client = null;
89
+ this.connected = false;
90
+ }
91
+ }
92
+ isConnected() {
93
+ return this.connected && this.client !== null;
94
+ }
95
+ /** Returns the underlying `PubSub` client for anything not wrapped here. */
96
+ getClient() {
97
+ return this.requireClient();
98
+ }
99
+ requireClient() {
100
+ if (!this.client || !this.connected) {
101
+ throw new errors_1.ConnectionError('Pub/Sub client is not connected. Call connect() first.', {
102
+ database: 'pubsub',
103
+ });
104
+ }
105
+ return this.client;
106
+ }
107
+ wrapError(action, err) {
108
+ const parent = err instanceof Error ? err : new Error(String(err));
109
+ return new errors_1.DatabaseError(`Pub/Sub ${action} failed: ${parent.message}`, {
110
+ parent,
111
+ original: parent.message,
112
+ });
113
+ }
114
+ // ---------------------------------------------------------------------
115
+ // Producing
116
+ // ---------------------------------------------------------------------
117
+ /**
118
+ * Publish one `message` to `topic` via `topic(name).publishMessage`. The
119
+ * message is encoded per the module's rules (string → UTF-8, Buffer → as-is,
120
+ * else JSON). Returns the server-assigned message id.
121
+ */
122
+ async publish(topic, message, attributes) {
123
+ const client = this.requireClient();
124
+ try {
125
+ return await client.topic(topic).publishMessage({ data: toData(message), attributes });
126
+ }
127
+ catch (err) {
128
+ throw this.wrapError(`publish to topic '${topic}'`, err);
129
+ }
130
+ }
131
+ // ---------------------------------------------------------------------
132
+ // Administration
133
+ // ---------------------------------------------------------------------
134
+ /** `createTopic` — create a new topic. */
135
+ async createTopic(name) {
136
+ const client = this.requireClient();
137
+ try {
138
+ await client.createTopic(name);
139
+ }
140
+ catch (err) {
141
+ throw this.wrapError(`createTopic '${name}'`, err);
142
+ }
143
+ }
144
+ /** `createSubscription` — attach a new subscription `name` to `topic`. */
145
+ async createSubscription(topic, name, options) {
146
+ const client = this.requireClient();
147
+ try {
148
+ await client.createSubscription(topic, name, options);
149
+ }
150
+ catch (err) {
151
+ throw this.wrapError(`createSubscription '${name}' on topic '${topic}'`, err);
152
+ }
153
+ }
154
+ // ---------------------------------------------------------------------
155
+ // Consuming
156
+ // ---------------------------------------------------------------------
157
+ /**
158
+ * Subscribe to `subscription`, invoking `handler` for each streamed message
159
+ * (the driver's `Message` object; call `.ack()` / `.nack()` on it). Attaches
160
+ * a `'message'` listener via `subscription(name).on('message', ...)` and
161
+ * returns a subscription handle whose `stop()` detaches the listener; it is
162
+ * also tracked so `disconnect()` detaches it.
163
+ */
164
+ async subscribe(subscription, handler) {
165
+ const client = this.requireClient();
166
+ let sub;
167
+ try {
168
+ sub = client.subscription(subscription);
169
+ sub.on('message', (message) => {
170
+ void handler(message);
171
+ });
172
+ }
173
+ catch (err) {
174
+ throw this.wrapError(`subscribe to '${subscription}'`, err);
175
+ }
176
+ this.subscriptions.add(sub);
177
+ return {
178
+ stop: async () => {
179
+ this.subscriptions.delete(sub);
180
+ sub.removeAllListeners?.();
181
+ await sub.close?.();
182
+ },
183
+ };
184
+ }
185
+ }
186
+ exports.PubSubStore = PubSubStore;
187
+ exports.default = PubSubStore;
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ /**
3
+ * Apache Pulsar store implementation.
4
+ *
5
+ * Pulsar is a distributed pub/sub messaging and streaming platform. It has no
6
+ * query language and does not fit the SQL-shaped `Dialect` interface, so this
7
+ * class implements the minimal `NoSqlStore` marker interface and exposes
8
+ * Pulsar's real operations - producing to topics, subscribing consumers, and
9
+ * creating readers - instead of forcing everything into a `query(sql)` shape.
10
+ *
11
+ * Uses the `pulsar-client` driver. `pulsar-client` is loaded lazily inside
12
+ * `connect()` (or supplied pre-built via `options.client`) so importing this
13
+ * module does not require the driver to be installed.
14
+ *
15
+ * ## Message serialization
16
+ *
17
+ * Pulsar sends and receives raw bytes. `produce()` accepts a `string` or a
18
+ * `Buffer`: strings are UTF-8 encoded to a `Buffer` and Buffers are passed
19
+ * through untouched, then handed to the producer as `{ data: Buffer }`.
20
+ * Consumers receive Pulsar `Message` objects; use `msg.getData()` to read the
21
+ * raw bytes back.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.PulsarStore = void 0;
25
+ const errors_1 = require("../../errors");
26
+ function wrapConnectionError(err, serviceUrl) {
27
+ const parent = err instanceof Error ? err : new Error(String(err));
28
+ const message = /econnrefused/i.test(parent.message)
29
+ ? 'Connection refused'
30
+ : `Unable to connect to Pulsar: ${parent.message}`;
31
+ return new errors_1.ConnectionError(message, {
32
+ parent,
33
+ database: 'pulsar',
34
+ host: serviceUrl,
35
+ });
36
+ }
37
+ function wrapDatabaseError(err, message) {
38
+ const parent = err instanceof Error ? err : new Error(String(err));
39
+ const combined = message ? `${message}: ${parent.message}` : parent.message;
40
+ return errors_1.DatabaseError.from(parent, { message: combined });
41
+ }
42
+ /** Serialize a `string`/`Buffer` message into the raw bytes Pulsar expects. */
43
+ function toBuffer(message) {
44
+ return Buffer.isBuffer(message) ? message : Buffer.from(message, 'utf8');
45
+ }
46
+ /**
47
+ * `PulsarStore` wraps a `pulsar-client` `Client` and exposes Pulsar's core
48
+ * operations: producing messages, consumer subscriptions, and readers.
49
+ */
50
+ class PulsarStore {
51
+ constructor(options = {}) {
52
+ this.name = 'pulsar';
53
+ this.library = 'pulsar-client';
54
+ this.client = null;
55
+ /** One cached producer per topic, so repeated `produce()` calls reuse it. */
56
+ this.producers = new Map();
57
+ /** Consumers created via `subscribe()`, tracked so `disconnect()` can close them. */
58
+ this.consumers = [];
59
+ /** Readers created via `createReader()`, tracked so `disconnect()` can close them. */
60
+ this.readers = [];
61
+ /** Set false on `disconnect()` to stop live `subscribe()` receive loops. */
62
+ this.receiving = false;
63
+ this.connected = false;
64
+ this.options = options;
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
+ // Lazy-load the driver so importing this module doesn't require
79
+ // `pulsar-client` to be installed unless a real connection is made.
80
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
81
+ const Pulsar = require('pulsar-client');
82
+ this.client = new Pulsar.Client({
83
+ serviceUrl: this.options.serviceUrl,
84
+ });
85
+ }
86
+ this.receiving = true;
87
+ this.connected = true;
88
+ }
89
+ catch (err) {
90
+ this.client = null;
91
+ this.connected = false;
92
+ throw wrapConnectionError(err, this.options.serviceUrl);
93
+ }
94
+ }
95
+ async disconnect() {
96
+ // Stop receive loops before closing anything.
97
+ this.receiving = false;
98
+ for (const consumer of this.consumers.splice(0)) {
99
+ try {
100
+ await consumer.close();
101
+ }
102
+ catch {
103
+ // Best-effort teardown - keep closing the rest.
104
+ }
105
+ }
106
+ for (const reader of this.readers.splice(0)) {
107
+ try {
108
+ await reader.close();
109
+ }
110
+ catch {
111
+ // Best-effort teardown.
112
+ }
113
+ }
114
+ for (const producer of this.producers.values()) {
115
+ try {
116
+ await producer.close();
117
+ }
118
+ catch {
119
+ // Best-effort teardown.
120
+ }
121
+ }
122
+ this.producers.clear();
123
+ if (this.client) {
124
+ try {
125
+ await this.client.close();
126
+ }
127
+ catch {
128
+ // Best-effort teardown.
129
+ }
130
+ this.client = null;
131
+ }
132
+ this.connected = false;
133
+ }
134
+ isConnected() {
135
+ return this.connected && this.client !== null;
136
+ }
137
+ /** Returns the underlying `pulsar-client` `Client` for anything not wrapped here. */
138
+ getClient() {
139
+ return this.requireClient();
140
+ }
141
+ requireClient() {
142
+ if (!this.client) {
143
+ throw new errors_1.ConnectionError('Not connected to Pulsar', { database: 'pulsar' });
144
+ }
145
+ return this.client;
146
+ }
147
+ // ---------------------------------------------------------------------
148
+ // Producing
149
+ // ---------------------------------------------------------------------
150
+ /**
151
+ * Produce `message` to `topic`. The producer for a topic is created on first
152
+ * use and cached, so repeated `produce()` calls to the same topic reuse it.
153
+ * `message` may be a UTF-8 `string` or a `Buffer`; it is serialized to raw
154
+ * bytes and sent as `{ data: Buffer }`. Returns the producer's send result.
155
+ */
156
+ async produce(topic, message) {
157
+ const client = this.requireClient();
158
+ try {
159
+ let producer = this.producers.get(topic);
160
+ if (!producer) {
161
+ producer = await client.createProducer({ topic });
162
+ this.producers.set(topic, producer);
163
+ }
164
+ return await producer.send({ data: toBuffer(message) });
165
+ }
166
+ catch (err) {
167
+ throw wrapDatabaseError(err, `Pulsar produce to "${topic}" failed`);
168
+ }
169
+ }
170
+ // ---------------------------------------------------------------------
171
+ // Consuming
172
+ // ---------------------------------------------------------------------
173
+ /**
174
+ * Subscribe a consumer to `topic` under `subscription` and invoke `handler`
175
+ * for every received message. Runs a background receive loop that calls
176
+ * `consumer.receive()`, passes each message to `handler`, then
177
+ * acknowledges it with `consumer.acknowledge(msg)`. The loop stops on
178
+ * `disconnect()`. The consumer is tracked so `disconnect()` closes it.
179
+ * Returns the created consumer.
180
+ */
181
+ async subscribe(topic, subscription, handler, options = {}) {
182
+ const client = this.requireClient();
183
+ let consumer;
184
+ try {
185
+ consumer = await client.subscribe({ topic, subscription, ...options });
186
+ this.consumers.push(consumer);
187
+ }
188
+ catch (err) {
189
+ throw wrapDatabaseError(err, `Pulsar subscribe to "${topic}" failed`);
190
+ }
191
+ // Background receive loop: pull, dispatch to handler, acknowledge. Stops
192
+ // when `disconnect()` flips `this.receiving` to false.
193
+ void (async () => {
194
+ while (this.receiving) {
195
+ let msg;
196
+ try {
197
+ msg = await consumer.receive();
198
+ }
199
+ catch {
200
+ // Consumer closed (typically during disconnect) - end the loop.
201
+ break;
202
+ }
203
+ try {
204
+ await handler(msg);
205
+ await consumer.acknowledge(msg);
206
+ }
207
+ catch {
208
+ // Handler/ack failure: don't kill the loop, move to the next message.
209
+ }
210
+ }
211
+ })();
212
+ return consumer;
213
+ }
214
+ /**
215
+ * Create a Pulsar reader over `topic`. Readers give non-destructive,
216
+ * position-controlled reads (no subscription/acks). The reader is tracked so
217
+ * `disconnect()` closes it. Returns the created reader.
218
+ */
219
+ async createReader(topic, options = {}) {
220
+ const client = this.requireClient();
221
+ try {
222
+ const reader = await client.createReader({ topic, ...options });
223
+ this.readers.push(reader);
224
+ return reader;
225
+ }
226
+ catch (err) {
227
+ throw wrapDatabaseError(err, `Pulsar createReader for "${topic}" failed`);
228
+ }
229
+ }
230
+ }
231
+ exports.PulsarStore = PulsarStore;
232
+ exports.default = PulsarStore;