SnsStore — Amazon SNS (Simple Notification Service)
Read this page in the documentation
SnsStore — Amazon SNS (Simple Notification Service) Overview Amazon SNS (Simple Notification Service) is a managed, push-based publish/subscribe fan-out service: publishers send to a topic and SNS pushes to every subscribed endpoint (SQS queue, Lambda, HTTP(S), email, SMS, ...). There is no query language and no SQL-shaped access pattern. Because none of that fits the SQL-shaped Dialect interface, SnsStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — and exposes SNS's own operations (publish, subscribe an endpoint, administer) directly rather than forcing them into a query(sql) shape. Identity: Property | Value | --------- | ----------------------- | name | 'sns' | library | '@aws-sdk/client-sns' | The store is built on AWS SDK v3 (@aws-sdk/client-sns), which speaks the SNS wire protocol via the command pattern: you construct a command object (new PublishCommand(input)) and hand it to client.send(command). Push-based subscribe — no receive loop, no handler SNS delivery is push-based — there is no client-side receive loop. Unlike poll-based engines (SQS, Kinesis), subscribe() does not take a message handler. It registers an endpoint (an SQS queue ARN, Lambda ARN, HTTPS URL, email address, ...) that SNS will push messages to. Consuming those messages happens at that endpoint — e.g. via SqsStore.subscribe on a subscribed queue. Lazy loading — not a hard dependency @aws-sdk/client-sns is not a hard dependency of this package. The SDK is loaded lazily via require() inside connect() (and on demand when a command is first built), rather than a top-level import. Importing this module therefore does not require the SDK to be installed — it is only needed when an SNS store is actually connected and driving real commands. Injected client SnsStoreOptions accepts a pre-built client (any object exposing a compatible send(command) method, typed as SnsClientLike). When provided, connect() uses it directly (and best-effort-loads the SDK only for its command constructors). This is how the test suite injects a mock client (no SDK, no network). Message encoding publish() accepts a string (sent as-is), a Buffer (decoded to UTF-8), or any other JSON-serializable value (JSON.stringifyd). The result becomes the notification Message. Connection Build a store from connection options and call connect(): All connection options are optional: Option | Type | Purpose | ------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------- | region | string | AWS region, e.g. 'us-east-1'. | credentials | { accessKeyId; secretAccessKey; sessionToken? } | Static credentials. Omit to fall back to the default AWS credential provider chain. | endpoint | string | Override the service endpoint, e.g. 'http://localhost:4566' for LocalStack. | client | SnsClientLike | A pre-built client to use directly (mock or custom config). When set, the SDK is not required to build a client. | Injected-client form Methods Internally, every operation follows the AWS v3 command pattern: the store resolves a command constructor by name from the lazily loaded SDK, builds new XxxCommand(input), and calls client.send(command). SDK failures are wrapped in a DatabaseError (preserving the original error); using any method before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise lazy-requires @aws-sdk/client-sns and builds an SNSClient from the options. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void>| Calls the client's optional destroy() and clears connection state. (SNS has no client-side loops to stop.) | isConnected | isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): SnsClientLike | Returns the underlying client for operations not wrapped here. Throws ConnectionError if not connected. | Producing Method | Signature | AWS command | Behavior | --------- | ---------------------------------------------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------- | publish | publish(topicArn: string, message: SnsMessage, options?: SnsPublishOptions): Promise<SnsPublishResult> | PublishCommand | Encodes message to a string and publishes it to the topic at topicArn. Returns { messageId?, sequenceNumber? }. | Topic administration Method | Signature | AWS command | Behavior | ------------- | ---------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------- | createTopic | createTopic(name: string, attributes?: Record<string, string>): Promise<string \| undefined> | CreateTopicCommand | Creates a topic by name. Returns its ARN. | Subscribing (push-based) Method | Signature | AWS command | Behavior | ----------- | ---------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | subscribe | subscribe(topicArn: string, endpoint: string, options?: SnsSubscribeOptions): Promise<string \| undefined> | SubscribeCommand | Registers a push endpoint on the topic at topicArn. Takes an endpoint and protocol, not a message handler. Returns the subscription ARN (or 'pending confirmation' for endpoints that require confirmation). | Example Verification status Unit / mock-verified only. The tests in tests/nosql/sns.test.ts are fully mock-driven: a fake client whose send(command) records the command and returns canned output is injected via SnsStoreOptions.client. The real @aws-sdk/client-sns package is not installed, and there is no live SNS access and no network in the test run — the command constructors are stubbed on the store's aws handle so command-type assertions are deterministic. What this proves: Each method builds and sends the correct command type (PublishCommand, CreateTopicCommand, SubscribeCommand) with the expected .input. Message encoding: strings pass through as the Message; objects are JSON-encoded. createTopic sends CreateTopicCommand and returns the ARN. subscribe sends SubscribeCommand with the endpoint and protocol, and defaults the protocol to 'https'. Lifecycle behavior: connecting via an injected client, disconnect() destroying the client, and ConnectionError before connect(). Error handling: Publish and Subscribe failures wrapped in DatabaseError. What this does not prove: live execution against real Amazon SNS (or LocalStack), and — because subscribe is push-based — no actual end-to-end fan-out delivery to a subscribed endpoint. The command/response shape is verified against the SDK's documented contract, but end-to-end execution over the wire has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories