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,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScyllaStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ScyllaDB (CQL) store.
|
|
6
|
+
*
|
|
7
|
+
* ScyllaDB is a wide-column, partition-key-based distributed store that is
|
|
8
|
+
* wire- and query-compatible with Apache Cassandra: it speaks the same CQL
|
|
9
|
+
* (Cassandra Query Language) and native protocol, so the same `cassandra-driver`
|
|
10
|
+
* (DataStax Node.js driver) connects to it unchanged. Its distinguishing trait
|
|
11
|
+
* is a C++, shard-per-core (seastar) architecture aimed at much higher
|
|
12
|
+
* throughput and lower, more predictable latency than the JVM-based Cassandra.
|
|
13
|
+
*
|
|
14
|
+
* Like Cassandra, ScyllaDB deliberately omits joins, arbitrary WHERE-clause
|
|
15
|
+
* filtering, and subqueries: every query must be answerable from a single
|
|
16
|
+
* partition (or an explicitly designed secondary index / materialized view),
|
|
17
|
+
* and data is modelled query-first around partition and clustering keys. That
|
|
18
|
+
* model does not fit the SQL-shaped `Dialect` interface
|
|
19
|
+
* (`src/dialects/dialect.ts`), so this store implements the minimal
|
|
20
|
+
* `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes CQL
|
|
21
|
+
* execution directly rather than pretending to be a relational dialect.
|
|
22
|
+
*
|
|
23
|
+
* Built on the `cassandra-driver`. The driver is an optional peer dependency
|
|
24
|
+
* and is loaded lazily inside `connect()` (via `require`) so importing this
|
|
25
|
+
* module never forces the driver to be installed; tests inject a pre-built
|
|
26
|
+
* mock `Client` instead.
|
|
27
|
+
*/
|
|
28
|
+
const errors_1 = require("../../errors");
|
|
29
|
+
/**
|
|
30
|
+
* `ScyllaStore` wraps a `cassandra-driver` `Client` and exposes CQL execution
|
|
31
|
+
* (`execute`), atomic multi-statement batches (`batch`), and a few
|
|
32
|
+
* parameterized convenience helpers (`insert`, `selectAll`).
|
|
33
|
+
*
|
|
34
|
+
* Statements are prepared by default (`prepare: true`) so the driver can cache
|
|
35
|
+
* query metadata, infer parameter types, and route requests to the shard/replica
|
|
36
|
+
* that owns the partition — the recommended default for anything run more than
|
|
37
|
+
* once, and especially valuable on ScyllaDB's shard-aware driver path.
|
|
38
|
+
*/
|
|
39
|
+
class ScyllaStore {
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.name = 'scylladb';
|
|
42
|
+
this.library = 'cassandra-driver';
|
|
43
|
+
this.client = null;
|
|
44
|
+
this.connected = false;
|
|
45
|
+
this.options = options;
|
|
46
|
+
}
|
|
47
|
+
// ---------------------------------------------------------------------
|
|
48
|
+
// NoSqlStore lifecycle
|
|
49
|
+
// ---------------------------------------------------------------------
|
|
50
|
+
async connect() {
|
|
51
|
+
if (this.connected && this.client) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
let client = this.options.client;
|
|
56
|
+
if (!client) {
|
|
57
|
+
// Lazy-load the optional driver so importing this module never
|
|
58
|
+
// requires `cassandra-driver` to be installed. Tests inject a mock
|
|
59
|
+
// `client` above and never reach this branch.
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
61
|
+
const cql = require('cassandra-driver');
|
|
62
|
+
client = new cql.Client({
|
|
63
|
+
contactPoints: this.options.contactPoints,
|
|
64
|
+
localDataCenter: this.options.localDataCenter,
|
|
65
|
+
keyspace: this.options.keyspace,
|
|
66
|
+
credentials: this.options.credentials,
|
|
67
|
+
...this.options.clientOptions,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
await client.connect();
|
|
71
|
+
this.client = client;
|
|
72
|
+
this.connected = true;
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
this.client = null;
|
|
76
|
+
this.connected = false;
|
|
77
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
78
|
+
throw new errors_1.ConnectionError(`Unable to connect to ScyllaDB: ${parent.message}`, {
|
|
79
|
+
parent,
|
|
80
|
+
database: 'scylladb',
|
|
81
|
+
host: this.options.contactPoints?.[0],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async disconnect() {
|
|
86
|
+
if (this.client) {
|
|
87
|
+
try {
|
|
88
|
+
await this.client.shutdown();
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
this.client = null;
|
|
92
|
+
this.connected = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
this.connected = false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
isConnected() {
|
|
100
|
+
return this.connected && this.client !== null;
|
|
101
|
+
}
|
|
102
|
+
/** Returns the underlying `cassandra-driver` `Client` for anything not wrapped here. */
|
|
103
|
+
getClient() {
|
|
104
|
+
return this.requireClient();
|
|
105
|
+
}
|
|
106
|
+
requireClient() {
|
|
107
|
+
if (!this.client || !this.connected) {
|
|
108
|
+
throw new errors_1.ConnectionError('ScyllaDB client is not connected. Call connect() first.', {
|
|
109
|
+
database: 'scylladb',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return this.client;
|
|
113
|
+
}
|
|
114
|
+
wrapError(action, err) {
|
|
115
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
116
|
+
return errors_1.DatabaseError.from(parent, { message: `ScyllaDB ${action} failed: ${parent.message}` });
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------
|
|
119
|
+
// CQL execution
|
|
120
|
+
// ---------------------------------------------------------------------
|
|
121
|
+
/**
|
|
122
|
+
* Execute a single CQL statement with optional bound `params`. Statements
|
|
123
|
+
* are prepared by default (`prepare: true`); pass `opts.prepare = false` to
|
|
124
|
+
* run a one-off unprepared. Any other driver query options are forwarded via
|
|
125
|
+
* `opts`. Returns the full driver result (with `.rows`).
|
|
126
|
+
*/
|
|
127
|
+
async execute(query, params = [], opts = {}) {
|
|
128
|
+
const client = this.requireClient();
|
|
129
|
+
try {
|
|
130
|
+
return (await client.execute(query, params, { prepare: true, ...opts }));
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
throw this.wrapError(`execute (${query})`, err);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Execute multiple statements as a single logged batch (atomic across the
|
|
138
|
+
* statements, though not isolated — CQL batches are not SQL transactions).
|
|
139
|
+
* Each entry is a `{ query, params }` pair. Prepared by default; forward
|
|
140
|
+
* other driver batch options via `opts`.
|
|
141
|
+
*/
|
|
142
|
+
async batch(queries, opts = {}) {
|
|
143
|
+
const client = this.requireClient();
|
|
144
|
+
try {
|
|
145
|
+
return await client.batch(queries, { prepare: true, ...opts });
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
throw this.wrapError('batch', err);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// ---------------------------------------------------------------------
|
|
152
|
+
// Convenience helpers
|
|
153
|
+
// ---------------------------------------------------------------------
|
|
154
|
+
/**
|
|
155
|
+
* Convenience `INSERT`: builds a parameterized
|
|
156
|
+
* `INSERT INTO table (cols...) VALUES (?, ?, ...)` from `obj`'s keys and
|
|
157
|
+
* executes it (prepared). For upserts with TTL, IF NOT EXISTS, or other
|
|
158
|
+
* clauses, write the CQL yourself and call `execute()`.
|
|
159
|
+
*/
|
|
160
|
+
async insert(table, obj, opts = {}) {
|
|
161
|
+
const columns = Object.keys(obj);
|
|
162
|
+
if (columns.length === 0) {
|
|
163
|
+
throw new errors_1.DatabaseError('insert() requires at least one column', {
|
|
164
|
+
original: 'empty insert object',
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const placeholders = columns.map(() => '?').join(', ');
|
|
168
|
+
const query = `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${placeholders})`;
|
|
169
|
+
const params = columns.map((c) => obj[c]);
|
|
170
|
+
return this.execute(query, params, opts);
|
|
171
|
+
}
|
|
172
|
+
/** Convenience `SELECT * FROM table`. Returns the full driver result (with `.rows`). */
|
|
173
|
+
async selectAll(table, opts = {}) {
|
|
174
|
+
return this.execute(`SELECT * FROM ${table}`, [], opts);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
exports.ScyllaStore = ScyllaStore;
|
|
178
|
+
exports.default = ScyllaStore;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SigNoz store implementation.
|
|
4
|
+
*
|
|
5
|
+
* SigNoz is an open-source, ClickHouse-backed observability platform for
|
|
6
|
+
* logs, traces, and metrics. Logs are ingested over OTLP/HTTP (the
|
|
7
|
+
* OpenTelemetry logs protocol) and queried through SigNoz's query-range API
|
|
8
|
+
* (a builder-style JSON body over its ClickHouse store). There is no
|
|
9
|
+
* SQL-shaped query surface exposed to clients, no row-level UPDATE/DELETE,
|
|
10
|
+
* and no identifier escaping, so SigNoz does not fit the SQL `Dialect`
|
|
11
|
+
* interface (`src/dialects/dialect.ts`). This class implements the minimal
|
|
12
|
+
* `NoSqlStore` marker interface (`src/nosql/store.ts`) and exposes SigNoz's
|
|
13
|
+
* OTLP ingest + query API.
|
|
14
|
+
*
|
|
15
|
+
* ## No canonical driver - HTTP over `fetch`
|
|
16
|
+
*
|
|
17
|
+
* SigNoz has no single canonical npm client; ingest is OTLP/HTTP JSON and
|
|
18
|
+
* query is a REST/JSON API. This store talks to both with the global `fetch`
|
|
19
|
+
* (so `library` is `'fetch'`). For tests (and custom transports) an
|
|
20
|
+
* alternative HTTP client can be injected via `SigNozStoreOptions.client`.
|
|
21
|
+
*
|
|
22
|
+
* ## Endpoints wrapped
|
|
23
|
+
*
|
|
24
|
+
* - `push(resource, entries)` -> `POST /v1/logs` (OTLP/HTTP ingest)
|
|
25
|
+
* - `query(builder, opts?)` -> `POST /api/v4/query_range` (query-range)
|
|
26
|
+
* - `labels()` -> `GET /api/v1/logs/fields` (log field keys)
|
|
27
|
+
* - `streams()` -> `GET /api/v1/services` (services)
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.SigNozStore = exports.DEFAULT_SIGNOZ_BASE_URL = void 0;
|
|
31
|
+
exports.createFetchClient = createFetchClient;
|
|
32
|
+
const errors_1 = require("../../errors");
|
|
33
|
+
/** Default SigNoz base URL (query service). */
|
|
34
|
+
exports.DEFAULT_SIGNOZ_BASE_URL = 'http://localhost:8080';
|
|
35
|
+
/** Build a `fetch`-backed client for the given base URL. */
|
|
36
|
+
function createFetchClient(baseURL, headers) {
|
|
37
|
+
const buildUrl = (path, params) => {
|
|
38
|
+
const url = new URL(path, baseURL.endsWith('/') ? baseURL : `${baseURL}/`);
|
|
39
|
+
for (const [key, value] of Object.entries(params ?? {})) {
|
|
40
|
+
if (value === undefined)
|
|
41
|
+
continue;
|
|
42
|
+
if (Array.isArray(value)) {
|
|
43
|
+
for (const item of value)
|
|
44
|
+
url.searchParams.append(key, item);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
url.searchParams.set(key, value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return url.toString();
|
|
51
|
+
};
|
|
52
|
+
return {
|
|
53
|
+
async get(path, params) {
|
|
54
|
+
const res = await fetch(buildUrl(path, params), {
|
|
55
|
+
method: 'GET',
|
|
56
|
+
headers: { Accept: 'application/json', ...(headers ?? {}) },
|
|
57
|
+
});
|
|
58
|
+
if (!res.ok)
|
|
59
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
60
|
+
return res.json();
|
|
61
|
+
},
|
|
62
|
+
async post(path, body, contentType) {
|
|
63
|
+
const res = await fetch(buildUrl(path), {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
body,
|
|
66
|
+
headers: { ...(headers ?? {}), ...(contentType ? { 'Content-Type': contentType } : {}) },
|
|
67
|
+
});
|
|
68
|
+
if (!res.ok)
|
|
69
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
70
|
+
const text = await res.text();
|
|
71
|
+
if (!text)
|
|
72
|
+
return undefined;
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(text);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return text;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** Map a simplified attribute value into an OTLP AnyValue. */
|
|
83
|
+
function toAnyValue(value) {
|
|
84
|
+
if (typeof value === 'number') {
|
|
85
|
+
return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
|
|
86
|
+
}
|
|
87
|
+
if (typeof value === 'boolean')
|
|
88
|
+
return { boolValue: value };
|
|
89
|
+
return { stringValue: value };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* `SigNozStore` wraps SigNoz's OTLP/HTTP log ingest and its query-range API
|
|
93
|
+
* (plus log-field and service metadata) behind the `NoSqlStore` lifecycle.
|
|
94
|
+
*/
|
|
95
|
+
class SigNozStore {
|
|
96
|
+
constructor(options = {}) {
|
|
97
|
+
this.name = 'signoz';
|
|
98
|
+
this.library = 'fetch';
|
|
99
|
+
this.client = null;
|
|
100
|
+
this.connected = false;
|
|
101
|
+
this.baseURL = options.baseURL ?? exports.DEFAULT_SIGNOZ_BASE_URL;
|
|
102
|
+
this.injectedClient = options.client;
|
|
103
|
+
this.headers = options.headers;
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------
|
|
106
|
+
// Connection lifecycle
|
|
107
|
+
// ---------------------------------------------------------------------
|
|
108
|
+
async connect() {
|
|
109
|
+
if (this.connected && this.client)
|
|
110
|
+
return;
|
|
111
|
+
this.client = this.injectedClient ?? createFetchClient(this.baseURL, this.headers);
|
|
112
|
+
this.connected = true;
|
|
113
|
+
}
|
|
114
|
+
async disconnect() {
|
|
115
|
+
this.client = null;
|
|
116
|
+
this.connected = false;
|
|
117
|
+
}
|
|
118
|
+
isConnected() {
|
|
119
|
+
return this.connected && this.client !== null;
|
|
120
|
+
}
|
|
121
|
+
/** Returns the underlying (internal or injected) HTTP client. */
|
|
122
|
+
getClient() {
|
|
123
|
+
return this.requireClient();
|
|
124
|
+
}
|
|
125
|
+
requireClient() {
|
|
126
|
+
if (!this.client) {
|
|
127
|
+
throw new errors_1.ConnectionError('Not connected to SigNoz', {
|
|
128
|
+
database: 'signoz',
|
|
129
|
+
host: this.baseURL,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return this.client;
|
|
133
|
+
}
|
|
134
|
+
async doGet(path, params, action) {
|
|
135
|
+
const client = this.requireClient();
|
|
136
|
+
try {
|
|
137
|
+
return await client.get(path, params);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
141
|
+
throw errors_1.DatabaseError.from(parent, {
|
|
142
|
+
message: `SigNoz ${action ?? 'request'} failed: ${parent.message}`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// ---------------------------------------------------------------------
|
|
147
|
+
// Ingest (OTLP/HTTP)
|
|
148
|
+
// ---------------------------------------------------------------------
|
|
149
|
+
/**
|
|
150
|
+
* Ingests log records over OTLP/HTTP via `POST /v1/logs`. The simplified
|
|
151
|
+
* `entries` are assembled into the OTLP `resourceLogs -> scopeLogs ->
|
|
152
|
+
* logRecords` envelope, tagged with the shared `resource` attributes.
|
|
153
|
+
*/
|
|
154
|
+
async push(resource, entries) {
|
|
155
|
+
const client = this.requireClient();
|
|
156
|
+
const payload = {
|
|
157
|
+
resourceLogs: [
|
|
158
|
+
{
|
|
159
|
+
resource: {
|
|
160
|
+
attributes: Object.entries(resource).map(([key, value]) => ({
|
|
161
|
+
key,
|
|
162
|
+
value: toAnyValue(value),
|
|
163
|
+
})),
|
|
164
|
+
},
|
|
165
|
+
scopeLogs: [
|
|
166
|
+
{
|
|
167
|
+
logRecords: entries.map((e) => ({
|
|
168
|
+
timeUnixNano: e.timeUnixNano === undefined ? undefined : String(e.timeUnixNano),
|
|
169
|
+
severityText: e.severity,
|
|
170
|
+
body: { stringValue: e.body },
|
|
171
|
+
attributes: Object.entries(e.attributes ?? {}).map(([key, value]) => ({
|
|
172
|
+
key,
|
|
173
|
+
value: toAnyValue(value),
|
|
174
|
+
})),
|
|
175
|
+
})),
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
try {
|
|
182
|
+
return await client.post('/v1/logs', JSON.stringify(payload), 'application/json');
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
186
|
+
throw errors_1.DatabaseError.from(parent, { message: `SigNoz push failed: ${parent.message}` });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// ---------------------------------------------------------------------
|
|
190
|
+
// Query
|
|
191
|
+
// ---------------------------------------------------------------------
|
|
192
|
+
/**
|
|
193
|
+
* Runs a query-range request via `POST /api/v4/query_range`. The
|
|
194
|
+
* `builder` is SigNoz's composite query payload (`compositeQuery` /
|
|
195
|
+
* builder queries); `start`/`end`/`step` fill the time window. Returns the
|
|
196
|
+
* parsed response.
|
|
197
|
+
*/
|
|
198
|
+
async query(builder, options = {}) {
|
|
199
|
+
const client = this.requireClient();
|
|
200
|
+
const payload = {
|
|
201
|
+
start: options.start,
|
|
202
|
+
end: options.end,
|
|
203
|
+
step: options.step,
|
|
204
|
+
...builder,
|
|
205
|
+
};
|
|
206
|
+
try {
|
|
207
|
+
return await client.post('/api/v4/query_range', JSON.stringify(payload), 'application/json');
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
211
|
+
throw errors_1.DatabaseError.from(parent, { message: `SigNoz query failed: ${parent.message}` });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// ---------------------------------------------------------------------
|
|
215
|
+
// Metadata
|
|
216
|
+
// ---------------------------------------------------------------------
|
|
217
|
+
/** Lists the known log field/attribute keys via `GET /api/v1/logs/fields`. */
|
|
218
|
+
async labels() {
|
|
219
|
+
return this.doGet('/api/v1/logs/fields', undefined, 'labels');
|
|
220
|
+
}
|
|
221
|
+
/** Lists the observed services via `GET /api/v1/services`. */
|
|
222
|
+
async streams() {
|
|
223
|
+
return this.doGet('/api/v1/services', undefined, 'streams');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
exports.SigNozStore = SigNozStore;
|
|
227
|
+
exports.default = SigNozStore;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SnsStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Amazon SNS (Simple Notification Service) store.
|
|
6
|
+
*
|
|
7
|
+
* SNS is a managed, push-based publish/subscribe fan-out service: publishers
|
|
8
|
+
* send to a topic and SNS pushes to every subscribed endpoint (SQS queue,
|
|
9
|
+
* Lambda, HTTP(S), email, SMS, ...). It has no query language and no SQL-shaped
|
|
10
|
+
* access pattern, so this store implements the minimal `NoSqlStore` marker
|
|
11
|
+
* interface (`src/nosql/store.ts`) and exposes SNS's real operations:
|
|
12
|
+
* publishing to a topic (`publish`), registering a subscription endpoint
|
|
13
|
+
* (`subscribe`), and topic administration (`createTopic`).
|
|
14
|
+
*
|
|
15
|
+
* Built on AWS SDK v3 (`@aws-sdk/client-sns`): an `SNSClient` speaks the wire
|
|
16
|
+
* protocol via the command pattern — you build a command object
|
|
17
|
+
* (`new PublishCommand(input)`) and hand it to `client.send(command)`. The SDK
|
|
18
|
+
* is loaded lazily inside `connect()` (via `require`) so importing this module
|
|
19
|
+
* never hard-requires the driver, and tests inject a mock `client` (with a
|
|
20
|
+
* `send(command)` method) so no real SDK or network is used.
|
|
21
|
+
*
|
|
22
|
+
* IMPORTANT: SNS delivery is *push*-based — there is no client-side receive
|
|
23
|
+
* loop. `subscribe()` therefore does NOT take a message handler; it registers
|
|
24
|
+
* an endpoint (an SQS queue ARN, Lambda ARN, HTTPS URL, email address, ...)
|
|
25
|
+
* that SNS will push messages to. Consuming those messages happens at that
|
|
26
|
+
* endpoint (e.g. via `SqsStore.subscribe` on a subscribed queue).
|
|
27
|
+
*
|
|
28
|
+
* Message encoding: `publish()` accepts a `string` (sent as-is), a `Buffer`
|
|
29
|
+
* (decoded to UTF-8), or any other JSON-serializable value (`JSON.stringify`d).
|
|
30
|
+
* The result becomes the notification `Message`.
|
|
31
|
+
*/
|
|
32
|
+
const errors_1 = require("../../errors");
|
|
33
|
+
/** Encode a message into the string SNS carries as the notification `Message`. */
|
|
34
|
+
function toMessage(message) {
|
|
35
|
+
if (typeof message === 'string')
|
|
36
|
+
return message;
|
|
37
|
+
if (Buffer.isBuffer(message))
|
|
38
|
+
return message.toString('utf8');
|
|
39
|
+
return JSON.stringify(message);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `SnsStore` wraps an AWS v3 `SNSClient` and exposes topic publishing,
|
|
43
|
+
* endpoint subscription registration, and topic administration.
|
|
44
|
+
*/
|
|
45
|
+
class SnsStore {
|
|
46
|
+
constructor(options = {}) {
|
|
47
|
+
this.name = 'sns';
|
|
48
|
+
this.library = '@aws-sdk/client-sns';
|
|
49
|
+
this.client = null;
|
|
50
|
+
this.aws = null;
|
|
51
|
+
this.connected = false;
|
|
52
|
+
this.options = options;
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------
|
|
55
|
+
// Lifecycle
|
|
56
|
+
// ---------------------------------------------------------------------
|
|
57
|
+
async connect() {
|
|
58
|
+
try {
|
|
59
|
+
if (this.options.client) {
|
|
60
|
+
this.client = this.options.client;
|
|
61
|
+
this.tryLoadSdk();
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const aws = require('@aws-sdk/client-sns');
|
|
65
|
+
this.aws = aws;
|
|
66
|
+
this.client = new aws.SNSClient({
|
|
67
|
+
region: this.options.region,
|
|
68
|
+
credentials: this.options.credentials,
|
|
69
|
+
endpoint: this.options.endpoint,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
this.connected = true;
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
this.connected = false;
|
|
76
|
+
this.client = null;
|
|
77
|
+
this.aws = null;
|
|
78
|
+
throw new errors_1.ConnectionError(`Failed to connect to SNS: ${err instanceof Error ? err.message : String(err)}`, { parent: err instanceof Error ? err : undefined, database: 'sns' });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
tryLoadSdk() {
|
|
82
|
+
if (this.aws)
|
|
83
|
+
return;
|
|
84
|
+
try {
|
|
85
|
+
this.aws = require('@aws-sdk/client-sns');
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
this.aws = null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async disconnect() {
|
|
92
|
+
try {
|
|
93
|
+
this.client?.destroy?.();
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
this.client = null;
|
|
97
|
+
this.aws = null;
|
|
98
|
+
this.connected = false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
isConnected() {
|
|
102
|
+
return this.connected && this.client !== null;
|
|
103
|
+
}
|
|
104
|
+
/** Returns the underlying `SNSClient` (loosely typed) for anything not wrapped here. */
|
|
105
|
+
getClient() {
|
|
106
|
+
return this.requireClient();
|
|
107
|
+
}
|
|
108
|
+
requireClient() {
|
|
109
|
+
if (!this.client || !this.connected) {
|
|
110
|
+
throw new errors_1.ConnectionError('SNS client is not connected. Call connect() first.', {
|
|
111
|
+
database: 'sns',
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return this.client;
|
|
115
|
+
}
|
|
116
|
+
command(name, input) {
|
|
117
|
+
if (!this.aws)
|
|
118
|
+
this.tryLoadSdk();
|
|
119
|
+
const Ctor = this.aws?.[name];
|
|
120
|
+
if (typeof Ctor !== 'function') {
|
|
121
|
+
throw new errors_1.ConnectionError(`SNS command '${name}' is unavailable: '@aws-sdk/client-sns' could not be loaded.`, { database: 'sns' });
|
|
122
|
+
}
|
|
123
|
+
return new Ctor(input);
|
|
124
|
+
}
|
|
125
|
+
wrapError(action, err) {
|
|
126
|
+
const parent = err instanceof Error ? err : new Error(String(err));
|
|
127
|
+
const name = parent.name ? ` (${parent.name})` : '';
|
|
128
|
+
return new errors_1.DatabaseError(`SNS ${action} failed${name}: ${parent.message}`, {
|
|
129
|
+
parent,
|
|
130
|
+
original: parent.message,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------
|
|
134
|
+
// Producing
|
|
135
|
+
// ---------------------------------------------------------------------
|
|
136
|
+
/**
|
|
137
|
+
* `Publish` — publish one `message` to the topic at `topicArn`. The message
|
|
138
|
+
* is encoded to a string (string as-is, Buffer → UTF-8, else JSON). Returns
|
|
139
|
+
* the message id (and FIFO sequence number, if any).
|
|
140
|
+
*/
|
|
141
|
+
async publish(topicArn, message, options = {}) {
|
|
142
|
+
const client = this.requireClient();
|
|
143
|
+
try {
|
|
144
|
+
const result = await client.send(this.command('PublishCommand', {
|
|
145
|
+
TopicArn: topicArn,
|
|
146
|
+
Message: toMessage(message),
|
|
147
|
+
Subject: options.subject,
|
|
148
|
+
MessageGroupId: options.messageGroupId,
|
|
149
|
+
MessageDeduplicationId: options.messageDeduplicationId,
|
|
150
|
+
MessageAttributes: options.messageAttributes,
|
|
151
|
+
MessageStructure: options.messageStructureJson ? 'json' : undefined,
|
|
152
|
+
}));
|
|
153
|
+
return { messageId: result?.MessageId, sequenceNumber: result?.SequenceNumber };
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
throw this.wrapError(`Publish to '${topicArn}'`, err);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// ---------------------------------------------------------------------
|
|
160
|
+
// Topic administration
|
|
161
|
+
// ---------------------------------------------------------------------
|
|
162
|
+
/** `CreateTopic` — create a topic by name. Returns its ARN. */
|
|
163
|
+
async createTopic(name, attributes) {
|
|
164
|
+
const client = this.requireClient();
|
|
165
|
+
try {
|
|
166
|
+
const result = await client.send(this.command('CreateTopicCommand', { Name: name, Attributes: attributes }));
|
|
167
|
+
return result?.TopicArn;
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
throw this.wrapError(`CreateTopic '${name}'`, err);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// ---------------------------------------------------------------------
|
|
174
|
+
// Subscribing (push-based)
|
|
175
|
+
// ---------------------------------------------------------------------
|
|
176
|
+
/**
|
|
177
|
+
* `Subscribe` — register a push `endpoint` on the topic at `topicArn`. Unlike
|
|
178
|
+
* poll-based engines, SNS pushes notifications to the endpoint, so this takes
|
|
179
|
+
* an endpoint (SQS/Lambda ARN, HTTPS URL, email, ...) and a protocol rather
|
|
180
|
+
* than a message handler. Returns the subscription ARN (or 'pending
|
|
181
|
+
* confirmation' for endpoints that require confirmation).
|
|
182
|
+
*/
|
|
183
|
+
async subscribe(topicArn, endpoint, options = {}) {
|
|
184
|
+
const client = this.requireClient();
|
|
185
|
+
try {
|
|
186
|
+
const result = await client.send(this.command('SubscribeCommand', {
|
|
187
|
+
TopicArn: topicArn,
|
|
188
|
+
Protocol: options.protocol ?? 'https',
|
|
189
|
+
Endpoint: endpoint,
|
|
190
|
+
ReturnSubscriptionArn: options.returnSubscriptionArn,
|
|
191
|
+
Attributes: options.attributes,
|
|
192
|
+
}));
|
|
193
|
+
return result?.SubscriptionArn;
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
throw this.wrapError(`Subscribe to '${topicArn}'`, err);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.SnsStore = SnsStore;
|
|
201
|
+
exports.default = SnsStore;
|