@heavybit/shared-lib 2.1.0 → 2.7.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/README.md +163 -2
- package/dist/cjs/access/index.js +9 -1
- package/dist/cjs/access/index.js.map +1 -1
- package/dist/cjs/approvals/index.js +137 -0
- package/dist/cjs/approvals/index.js.map +1 -0
- package/dist/cjs/audit/index.js +74 -0
- package/dist/cjs/audit/index.js.map +1 -0
- package/dist/cjs/cache/index.js +90 -16
- package/dist/cjs/cache/index.js.map +1 -1
- package/dist/cjs/cache/keyspace.js +101 -0
- package/dist/cjs/cache/keyspace.js.map +1 -0
- package/dist/cjs/common/circuit-breaker.js +74 -0
- package/dist/cjs/common/circuit-breaker.js.map +1 -0
- package/dist/cjs/common/index.js +4 -0
- package/dist/cjs/common/index.js.map +1 -1
- package/dist/cjs/common/internal-client.js +177 -0
- package/dist/cjs/common/internal-client.js.map +1 -0
- package/dist/cjs/common/internal-constants.js +12 -0
- package/dist/cjs/common/internal-constants.js.map +1 -0
- package/dist/cjs/common/internal-service-auth.js +160 -0
- package/dist/cjs/common/internal-service-auth.js.map +1 -0
- package/dist/cjs/common/money.js +215 -0
- package/dist/cjs/common/money.js.map +1 -0
- package/dist/cjs/common/phone.js +41 -22
- package/dist/cjs/common/phone.js.map +1 -1
- package/dist/cjs/common/time.js +28 -2
- package/dist/cjs/common/time.js.map +1 -1
- package/dist/cjs/config/index.js +139 -19
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/contracts/notification-dispatch.js +1 -1
- package/dist/cjs/database/db.js +37 -0
- package/dist/cjs/database/db.js.map +1 -0
- package/dist/cjs/database/index.js +22 -51
- package/dist/cjs/database/index.js.map +1 -1
- package/dist/cjs/database/pagination.js +88 -0
- package/dist/cjs/database/pagination.js.map +1 -0
- package/dist/cjs/database/pool.js +60 -0
- package/dist/cjs/database/pool.js.map +1 -0
- package/dist/cjs/database/scoped-repository.js +132 -0
- package/dist/cjs/database/scoped-repository.js.map +1 -0
- package/dist/cjs/database/scopes.js +166 -0
- package/dist/cjs/database/scopes.js.map +1 -0
- package/dist/cjs/database/table-names.js +14 -0
- package/dist/cjs/database/table-names.js.map +1 -0
- package/dist/cjs/database/tables.js +71 -0
- package/dist/cjs/database/tables.js.map +1 -0
- package/dist/cjs/express/auth.js +64 -50
- package/dist/cjs/express/auth.js.map +1 -1
- package/dist/cjs/express/index.js +2 -0
- package/dist/cjs/express/index.js.map +1 -1
- package/dist/cjs/express/internal-caller.js +52 -0
- package/dist/cjs/express/internal-caller.js.map +1 -0
- package/dist/cjs/express/step-up.js +41 -0
- package/dist/cjs/express/step-up.js.map +1 -0
- package/dist/cjs/http/index.js +3 -71
- package/dist/cjs/http/index.js.map +1 -1
- package/dist/cjs/identity/index.js +269 -67
- package/dist/cjs/identity/index.js.map +1 -1
- package/dist/cjs/identity/step-up.js +52 -0
- package/dist/cjs/identity/step-up.js.map +1 -0
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/knex/columns.js +36 -0
- package/dist/cjs/knex/columns.js.map +1 -0
- package/dist/cjs/knex/index.js +26 -43
- package/dist/cjs/knex/index.js.map +1 -1
- package/dist/cjs/knex/migration-helpers.js +57 -0
- package/dist/cjs/knex/migration-helpers.js.map +1 -0
- package/dist/cjs/logging/redact.js +6 -11
- package/dist/cjs/logging/redact.js.map +1 -1
- package/dist/cjs/messaging/base-consumer.js +36 -0
- package/dist/cjs/messaging/base-consumer.js.map +1 -0
- package/dist/cjs/messaging/consumer.js +142 -73
- package/dist/cjs/messaging/consumer.js.map +1 -1
- package/dist/cjs/messaging/envelope.js +53 -10
- package/dist/cjs/messaging/envelope.js.map +1 -1
- package/dist/cjs/messaging/idempotency.js +95 -8
- package/dist/cjs/messaging/idempotency.js.map +1 -1
- package/dist/cjs/messaging/index.js +2 -1
- package/dist/cjs/messaging/index.js.map +1 -1
- package/dist/cjs/messaging/outbox.js +97 -55
- package/dist/cjs/messaging/outbox.js.map +1 -1
- package/dist/cjs/messaging/publisher.js +86 -38
- package/dist/cjs/messaging/publisher.js.map +1 -1
- package/dist/cjs/messaging/staff-notifier.js +4 -4
- package/dist/cjs/messaging/staff-notifier.js.map +1 -1
- package/dist/cjs/messaging/topology.js +41 -5
- package/dist/cjs/messaging/topology.js.map +1 -1
- package/dist/cjs/rate-limit/index.js +57 -6
- package/dist/cjs/rate-limit/index.js.map +1 -1
- package/dist/cjs/rate-limit/keys.js +47 -0
- package/dist/cjs/rate-limit/keys.js.map +1 -0
- package/dist/cjs/socket/index.js +127 -16
- package/dist/cjs/socket/index.js.map +1 -1
- package/dist/cjs/socket/ticket.js +124 -0
- package/dist/cjs/socket/ticket.js.map +1 -0
- package/dist/cjs/testing/index.js +23 -14
- package/dist/cjs/testing/index.js.map +1 -1
- package/dist/esm/access/index.js +9 -1
- package/dist/esm/access/index.js.map +1 -1
- package/dist/esm/approvals/index.js +127 -0
- package/dist/esm/approvals/index.js.map +1 -0
- package/dist/esm/audit/index.js +70 -0
- package/dist/esm/audit/index.js.map +1 -0
- package/dist/esm/cache/index.js +70 -13
- package/dist/esm/cache/index.js.map +1 -1
- package/dist/esm/cache/keyspace.js +95 -0
- package/dist/esm/cache/keyspace.js.map +1 -0
- package/dist/esm/common/circuit-breaker.js +70 -0
- package/dist/esm/common/circuit-breaker.js.map +1 -0
- package/dist/esm/common/index.js +4 -0
- package/dist/esm/common/index.js.map +1 -1
- package/dist/esm/common/internal-client.js +173 -0
- package/dist/esm/common/internal-client.js.map +1 -0
- package/dist/esm/common/internal-constants.js +9 -0
- package/dist/esm/common/internal-constants.js.map +1 -0
- package/dist/esm/common/internal-service-auth.js +150 -0
- package/dist/esm/common/internal-service-auth.js.map +1 -0
- package/dist/esm/common/money.js +207 -0
- package/dist/esm/common/money.js.map +1 -0
- package/dist/esm/common/phone.js +41 -22
- package/dist/esm/common/phone.js.map +1 -1
- package/dist/esm/common/time.js +27 -2
- package/dist/esm/common/time.js.map +1 -1
- package/dist/esm/config/index.js +135 -18
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/contracts/notification-dispatch.js +1 -1
- package/dist/esm/database/db.js +32 -0
- package/dist/esm/database/db.js.map +1 -0
- package/dist/esm/database/index.js +9 -45
- package/dist/esm/database/index.js.map +1 -1
- package/dist/esm/database/pagination.js +81 -0
- package/dist/esm/database/pagination.js.map +1 -0
- package/dist/esm/database/pool.js +51 -0
- package/dist/esm/database/pool.js.map +1 -0
- package/dist/esm/database/scoped-repository.js +128 -0
- package/dist/esm/database/scoped-repository.js.map +1 -0
- package/dist/esm/database/scopes.js +157 -0
- package/dist/esm/database/scopes.js.map +1 -0
- package/dist/esm/database/table-names.js +11 -0
- package/dist/esm/database/table-names.js.map +1 -0
- package/dist/esm/database/tables.js +61 -0
- package/dist/esm/database/tables.js.map +1 -0
- package/dist/esm/express/auth.js +62 -48
- package/dist/esm/express/auth.js.map +1 -1
- package/dist/esm/express/index.js +2 -0
- package/dist/esm/express/index.js.map +1 -1
- package/dist/esm/express/internal-caller.js +49 -0
- package/dist/esm/express/internal-caller.js.map +1 -0
- package/dist/esm/express/step-up.js +38 -0
- package/dist/esm/express/step-up.js.map +1 -0
- package/dist/esm/http/index.js +3 -70
- package/dist/esm/http/index.js.map +1 -1
- package/dist/esm/identity/index.js +246 -64
- package/dist/esm/identity/index.js.map +1 -1
- package/dist/esm/identity/step-up.js +47 -0
- package/dist/esm/identity/step-up.js.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/knex/columns.js +28 -0
- package/dist/esm/knex/columns.js.map +1 -0
- package/dist/esm/knex/index.js +8 -34
- package/dist/esm/knex/index.js.map +1 -1
- package/dist/esm/knex/migration-helpers.js +51 -0
- package/dist/esm/knex/migration-helpers.js.map +1 -0
- package/dist/esm/logging/redact.js +3 -7
- package/dist/esm/logging/redact.js.map +1 -1
- package/dist/esm/messaging/base-consumer.js +32 -0
- package/dist/esm/messaging/base-consumer.js.map +1 -0
- package/dist/esm/messaging/consumer.js +139 -71
- package/dist/esm/messaging/consumer.js.map +1 -1
- package/dist/esm/messaging/envelope.js +50 -10
- package/dist/esm/messaging/envelope.js.map +1 -1
- package/dist/esm/messaging/idempotency.js +91 -7
- package/dist/esm/messaging/idempotency.js.map +1 -1
- package/dist/esm/messaging/index.js +2 -1
- package/dist/esm/messaging/index.js.map +1 -1
- package/dist/esm/messaging/outbox.js +97 -54
- package/dist/esm/messaging/outbox.js.map +1 -1
- package/dist/esm/messaging/publisher.js +86 -38
- package/dist/esm/messaging/publisher.js.map +1 -1
- package/dist/esm/messaging/staff-notifier.js +4 -4
- package/dist/esm/messaging/staff-notifier.js.map +1 -1
- package/dist/esm/messaging/topology.js +39 -4
- package/dist/esm/messaging/topology.js.map +1 -1
- package/dist/esm/rate-limit/index.js +41 -6
- package/dist/esm/rate-limit/index.js.map +1 -1
- package/dist/esm/rate-limit/keys.js +43 -0
- package/dist/esm/rate-limit/keys.js.map +1 -0
- package/dist/esm/socket/index.js +112 -17
- package/dist/esm/socket/index.js.map +1 -1
- package/dist/esm/socket/ticket.js +117 -0
- package/dist/esm/socket/ticket.js.map +1 -0
- package/dist/esm/testing/index.js +24 -15
- package/dist/esm/testing/index.js.map +1 -1
- package/dist/types/access/index.d.ts +9 -3
- package/dist/types/access/index.d.ts.map +1 -1
- package/dist/types/approvals/index.d.ts +99 -0
- package/dist/types/approvals/index.d.ts.map +1 -0
- package/dist/types/audit/index.d.ts +82 -0
- package/dist/types/audit/index.d.ts.map +1 -0
- package/dist/types/cache/index.d.ts +64 -14
- package/dist/types/cache/index.d.ts.map +1 -1
- package/dist/types/cache/keyspace.d.ts +84 -0
- package/dist/types/cache/keyspace.d.ts.map +1 -0
- package/dist/types/common/circuit-breaker.d.ts +51 -0
- package/dist/types/common/circuit-breaker.d.ts.map +1 -0
- package/dist/types/common/index.d.ts +4 -0
- package/dist/types/common/index.d.ts.map +1 -1
- package/dist/types/common/internal-client.d.ts +116 -0
- package/dist/types/common/internal-client.d.ts.map +1 -0
- package/dist/types/common/internal-constants.d.ts +9 -0
- package/dist/types/common/internal-constants.d.ts.map +1 -0
- package/dist/types/common/internal-service-auth.d.ts +102 -0
- package/dist/types/common/internal-service-auth.d.ts.map +1 -0
- package/dist/types/common/money.d.ts +104 -0
- package/dist/types/common/money.d.ts.map +1 -0
- package/dist/types/common/phone.d.ts +25 -15
- package/dist/types/common/phone.d.ts.map +1 -1
- package/dist/types/common/time.d.ts +20 -2
- package/dist/types/common/time.d.ts.map +1 -1
- package/dist/types/config/index.d.ts +251 -27
- package/dist/types/config/index.d.ts.map +1 -1
- package/dist/types/contracts/notification-dispatch.d.ts +13 -13
- package/dist/types/database/db.d.ts +46 -0
- package/dist/types/database/db.d.ts.map +1 -0
- package/dist/types/database/index.d.ts +9 -22
- package/dist/types/database/index.d.ts.map +1 -1
- package/dist/types/database/pagination.d.ts +68 -0
- package/dist/types/database/pagination.d.ts.map +1 -0
- package/dist/types/database/pool.d.ts +39 -0
- package/dist/types/database/pool.d.ts.map +1 -0
- package/dist/types/database/scoped-repository.d.ts +92 -0
- package/dist/types/database/scoped-repository.d.ts.map +1 -0
- package/dist/types/database/scopes.d.ts +159 -0
- package/dist/types/database/scopes.d.ts.map +1 -0
- package/dist/types/database/table-names.d.ts +13 -0
- package/dist/types/database/table-names.d.ts.map +1 -0
- package/dist/types/database/tables.d.ts +748 -0
- package/dist/types/database/tables.d.ts.map +1 -0
- package/dist/types/express/auth.d.ts +40 -24
- package/dist/types/express/auth.d.ts.map +1 -1
- package/dist/types/express/index.d.ts +2 -0
- package/dist/types/express/index.d.ts.map +1 -1
- package/dist/types/express/internal-caller.d.ts +53 -0
- package/dist/types/express/internal-caller.d.ts.map +1 -0
- package/dist/types/express/step-up.d.ts +38 -0
- package/dist/types/express/step-up.d.ts.map +1 -0
- package/dist/types/http/index.d.ts +3 -31
- package/dist/types/http/index.d.ts.map +1 -1
- package/dist/types/identity/index.d.ts +159 -21
- package/dist/types/identity/index.d.ts.map +1 -1
- package/dist/types/identity/step-up.d.ts +41 -0
- package/dist/types/identity/step-up.d.ts.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/knex/columns.d.ts +15 -0
- package/dist/types/knex/columns.d.ts.map +1 -0
- package/dist/types/knex/index.d.ts +3 -11
- package/dist/types/knex/index.d.ts.map +1 -1
- package/dist/types/knex/migration-helpers.d.ts +28 -0
- package/dist/types/knex/migration-helpers.d.ts.map +1 -0
- package/dist/types/logging/redact.d.ts +2 -2
- package/dist/types/logging/redact.d.ts.map +1 -1
- package/dist/types/messaging/base-consumer.d.ts +33 -0
- package/dist/types/messaging/base-consumer.d.ts.map +1 -0
- package/dist/types/messaging/consumer.d.ts +59 -21
- package/dist/types/messaging/consumer.d.ts.map +1 -1
- package/dist/types/messaging/envelope.d.ts +50 -11
- package/dist/types/messaging/envelope.d.ts.map +1 -1
- package/dist/types/messaging/idempotency.d.ts +60 -3
- package/dist/types/messaging/idempotency.d.ts.map +1 -1
- package/dist/types/messaging/index.d.ts +7 -0
- package/dist/types/messaging/index.d.ts.map +1 -1
- package/dist/types/messaging/outbox.d.ts +62 -22
- package/dist/types/messaging/outbox.d.ts.map +1 -1
- package/dist/types/messaging/publisher.d.ts +54 -21
- package/dist/types/messaging/publisher.d.ts.map +1 -1
- package/dist/types/messaging/staff-notifier.d.ts +9 -9
- package/dist/types/messaging/staff-notifier.d.ts.map +1 -1
- package/dist/types/messaging/staff-recipients.d.ts +1 -1
- package/dist/types/messaging/topology.d.ts +40 -8
- package/dist/types/messaging/topology.d.ts.map +1 -1
- package/dist/types/rate-limit/index.d.ts +40 -4
- package/dist/types/rate-limit/index.d.ts.map +1 -1
- package/dist/types/rate-limit/keys.d.ts +52 -0
- package/dist/types/rate-limit/keys.d.ts.map +1 -0
- package/dist/types/socket/index.d.ts +86 -2
- package/dist/types/socket/index.d.ts.map +1 -1
- package/dist/types/socket/ticket.d.ts +90 -0
- package/dist/types/socket/ticket.d.ts.map +1 -0
- package/dist/types/testing/index.d.ts +31 -10
- package/dist/types/testing/index.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +26 -14
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +3 -1
|
@@ -2,7 +2,7 @@ import { ServiceUnavailableError } from '../common/errors.js';
|
|
|
2
2
|
import type { EventEnvelope, Logger } from '../types/index.js';
|
|
3
3
|
import type { AmqpConnection } from './connection.js';
|
|
4
4
|
import { type EnvelopeMeta } from './envelope.js';
|
|
5
|
-
import type
|
|
5
|
+
import { type Topology } from './topology.js';
|
|
6
6
|
/**
|
|
7
7
|
* The broker accepted a `mandatory` message but no queue was bound to receive it (the consumer has never
|
|
8
8
|
* started, or its binding is wrong). Retryable: the message is not lost — the caller (or the outbox relay)
|
|
@@ -13,72 +13,105 @@ export declare class UnroutableMessageError extends ServiceUnavailableError {
|
|
|
13
13
|
readonly routingKey: string;
|
|
14
14
|
constructor(exchange: string, routingKey: string);
|
|
15
15
|
}
|
|
16
|
+
/** True when `error` is an {@link UnroutableMessageError} (retryable; the target queue is missing). */
|
|
16
17
|
export declare function isUnroutableError(error: unknown): error is UnroutableMessageError;
|
|
18
|
+
/** Transport options for sending a pre-built envelope. */
|
|
19
|
+
export interface SendOptions {
|
|
20
|
+
/** Sent as `x-correlation-id`; defaults to the active request context's. */
|
|
21
|
+
correlationId?: string;
|
|
22
|
+
}
|
|
17
23
|
/** Publishes domain events (fan-out to any interested consumer). */
|
|
18
24
|
export interface EventBus {
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
/** Builds the envelope (see `buildEnvelope`) and publishes it on the events exchange. */
|
|
26
|
+
publish<T extends object>(routingKey: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
27
|
+
/** Publishes a pre-built envelope (outbox relay). */
|
|
28
|
+
publishEnvelope(envelope: EventEnvelope, options?: SendOptions): Promise<void>;
|
|
21
29
|
}
|
|
22
|
-
/** Sends a command to the single service that owns it (e.g. `
|
|
30
|
+
/** Sends a command to the single service that owns it (e.g. `mail:send`). */
|
|
23
31
|
export interface CommandBus {
|
|
24
|
-
send<T>(command: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
25
|
-
/** Sends a pre-built command envelope (outbox relay). `envelope.
|
|
26
|
-
sendEnvelope(envelope: EventEnvelope): Promise<void>;
|
|
32
|
+
send<T extends object>(command: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
33
|
+
/** Sends a pre-built command envelope (outbox relay). `envelope.routingKey` is the command name. */
|
|
34
|
+
sendEnvelope(envelope: EventEnvelope, options?: SendOptions): Promise<void>;
|
|
27
35
|
}
|
|
28
|
-
|
|
36
|
+
/** Options for direct queue sends and delayed sends. */
|
|
37
|
+
export interface QueueSendOptions extends SendOptions {
|
|
29
38
|
/** Defaults to a new ULID. */
|
|
30
39
|
messageId?: string;
|
|
31
|
-
correlationId?: string;
|
|
32
40
|
}
|
|
33
41
|
/** Sends a plain JSON payload straight to a named queue, for a consumer outside the shared topology. */
|
|
34
42
|
export interface QueueSender {
|
|
35
43
|
sendToQueue(queue: string, payload: unknown, options?: QueueSendOptions): Promise<void>;
|
|
36
44
|
}
|
|
45
|
+
/** Delivers a payload to a queue after a delay (MSG-4). */
|
|
46
|
+
export interface DelayedSender {
|
|
47
|
+
/**
|
|
48
|
+
* @param queue Physical target queue (declared by its consumer).
|
|
49
|
+
* @param payload JSON body, delivered as-is.
|
|
50
|
+
* @param delayMs Delay in milliseconds (1 … {@link MAX_DELAY_MS}).
|
|
51
|
+
*/
|
|
52
|
+
scheduleDelayed(queue: string, payload: unknown, delayMs: number, options?: QueueSendOptions): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
/** Largest delay `scheduleDelayed` accepts (AMQP per-message TTL is a 32-bit value). */
|
|
55
|
+
export declare const MAX_DELAY_MS: number;
|
|
56
|
+
/** Dependencies for {@link MessagePublisher}. */
|
|
37
57
|
export interface PublisherOptions {
|
|
38
58
|
connection: AmqpConnection;
|
|
39
59
|
topology: Topology;
|
|
40
|
-
/** Service name
|
|
60
|
+
/** Service name, sent as the AMQP `appId`. */
|
|
41
61
|
source: string;
|
|
42
62
|
logger?: Logger;
|
|
43
63
|
}
|
|
44
64
|
/**
|
|
45
65
|
* Event and command publisher on a confirm channel: `publish()` resolves only once the broker
|
|
46
66
|
* has persisted the message, and rejects with 503 when the broker is unreachable so callers
|
|
47
|
-
* (or the outbox relay) can retry.
|
|
67
|
+
* (or the outbox relay) can retry. Every message is persistent JSON with `messageId` = event id and the
|
|
68
|
+
* correlation id in the `x-correlation-id` header.
|
|
48
69
|
*
|
|
49
70
|
* Commands and direct queue sends are `mandatory`: a command has exactly one owner, so one that no
|
|
50
71
|
* queue receives is a fault, not a no-op. The broker returns it (`basic.return`, always before its
|
|
51
72
|
* confirm), and the send rejects with `UnroutableMessageError` instead of resolving as if delivered.
|
|
52
73
|
* Events stay non-mandatory: a topic event with no subscriber yet is normal fan-out.
|
|
53
74
|
*/
|
|
54
|
-
export declare class MessagePublisher implements EventBus, CommandBus, QueueSender {
|
|
75
|
+
export declare class MessagePublisher implements EventBus, CommandBus, QueueSender, DelayedSender {
|
|
55
76
|
private readonly options;
|
|
56
77
|
private handle;
|
|
57
78
|
private readonly logger;
|
|
58
79
|
/** Message ids the broker returned as unroutable, awaiting their confirm. */
|
|
59
80
|
private readonly returned;
|
|
81
|
+
/** Delay queues already declared, per live channel (a reconnect gets a new channel). */
|
|
82
|
+
private readonly declaredDelayQueues;
|
|
60
83
|
constructor(options: PublisherOptions);
|
|
61
84
|
init(): Promise<void>;
|
|
62
|
-
publish<T>(
|
|
63
|
-
publishEnvelope(envelope: EventEnvelope): Promise<void>;
|
|
64
|
-
send<T>(command: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
65
|
-
sendEnvelope(envelope: EventEnvelope): Promise<void>;
|
|
85
|
+
publish<T extends object>(routingKey: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
86
|
+
publishEnvelope(envelope: EventEnvelope, options?: SendOptions): Promise<void>;
|
|
87
|
+
send<T extends object>(command: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
88
|
+
sendEnvelope(envelope: EventEnvelope, options?: SendOptions): Promise<void>;
|
|
66
89
|
/**
|
|
67
90
|
* Sends `payload` as-is (no envelope) to `queue` through the default exchange. The queue is the
|
|
68
91
|
* consumer's to declare, so it is not asserted here; a missing queue rejects as unroutable.
|
|
69
92
|
*/
|
|
70
93
|
sendToQueue(queue: string, payload: unknown, options?: QueueSendOptions): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Parks `payload` in a delay queue with a per-message TTL; when it expires the broker dead-letters it
|
|
96
|
+
* into `queue` (MSG-4). Delay queues are bucketed by power of two (see `delayQueueName`). The target
|
|
97
|
+
* queue must exist when the TTL fires, or the broker drops the message.
|
|
98
|
+
*
|
|
99
|
+
* @throws RangeError when `delayMs` is not an integer in 1 … {@link MAX_DELAY_MS}.
|
|
100
|
+
*/
|
|
101
|
+
scheduleDelayed(queue: string, payload: unknown, delayMs: number, options?: QueueSendOptions): Promise<void>;
|
|
102
|
+
private declareDelayQueue;
|
|
103
|
+
private channel;
|
|
71
104
|
private write;
|
|
72
105
|
}
|
|
73
106
|
/** Stand-in when messaging is disabled (local tooling, tests): logs and drops. */
|
|
74
|
-
export declare class NoopMessageBus implements EventBus, CommandBus, QueueSender {
|
|
75
|
-
private readonly source;
|
|
107
|
+
export declare class NoopMessageBus implements EventBus, CommandBus, QueueSender, DelayedSender {
|
|
76
108
|
private readonly logger;
|
|
77
|
-
constructor(
|
|
78
|
-
publish<T>(
|
|
109
|
+
constructor(logger?: Logger);
|
|
110
|
+
publish<T extends object>(routingKey: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
79
111
|
publishEnvelope(envelope: EventEnvelope): Promise<void>;
|
|
80
|
-
send<T>(command: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
112
|
+
send<T extends object>(command: string, data: T, meta?: EnvelopeMeta): Promise<EventEnvelope<T>>;
|
|
81
113
|
sendEnvelope(envelope: EventEnvelope): Promise<void>;
|
|
82
114
|
sendToQueue(queue: string): Promise<void>;
|
|
115
|
+
scheduleDelayed(queue: string, _payload: unknown, delayMs: number): Promise<void>;
|
|
83
116
|
}
|
|
84
117
|
//# sourceMappingURL=publisher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../../src/messaging/publisher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,iBAAiB,CAAC;AACrE,OAAO,
|
|
1
|
+
{"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../../src/messaging/publisher.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,20 +11,20 @@ import type { StaffRecipientResolver } from './staff-recipients.js';
|
|
|
11
11
|
* The slice of a service's outbox the notifier needs.
|
|
12
12
|
*
|
|
13
13
|
* @typeParam E The service's transaction/executor type.
|
|
14
|
-
* @example const outbox: CommandOutbox<
|
|
14
|
+
* @example const outbox: CommandOutbox<DbExecutor> = { command: (tx, name, data, meta) => enqueueOutbox(tx, name, data, { ...meta, exchange: 'commands' }).then(() => undefined) };
|
|
15
15
|
*/
|
|
16
16
|
export interface CommandOutbox<E> {
|
|
17
|
-
command<T>(executor: E, command: string, data: T, meta?: EnvelopeMeta): Promise<void>;
|
|
17
|
+
command<T extends object>(executor: E, command: string, data: T, meta?: EnvelopeMeta): Promise<void>;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* One operational alert to the staff who hold a permission.
|
|
21
21
|
*
|
|
22
|
-
* @example { template: '
|
|
22
|
+
* @example { template: 'job-failed', permission: 'jobs.manage', data: { reference: 'J-1' } }
|
|
23
23
|
*/
|
|
24
24
|
export interface StaffAlert<Ch extends string = string> {
|
|
25
25
|
/** Seeded notification template slug. */
|
|
26
26
|
template: string;
|
|
27
|
-
/** The permission its recipients hold (e.g. `
|
|
27
|
+
/** The permission its recipients hold (e.g. `reports.manage`). */
|
|
28
28
|
permission: string;
|
|
29
29
|
/** Template variables. */
|
|
30
30
|
data: Record<string, DispatchValue>;
|
|
@@ -34,9 +34,9 @@ export interface StaffAlert<Ch extends string = string> {
|
|
|
34
34
|
/**
|
|
35
35
|
* Tracing for the staged commands; the actor is always the system.
|
|
36
36
|
*
|
|
37
|
-
* @example { correlationId: correlationId(req)
|
|
37
|
+
* @example { correlationId: correlationId(req) }
|
|
38
38
|
*/
|
|
39
|
-
export type StaffAlertMeta = Pick<EnvelopeMeta, 'correlationId'
|
|
39
|
+
export type StaffAlertMeta = Pick<EnvelopeMeta, 'correlationId'>;
|
|
40
40
|
/**
|
|
41
41
|
* How the notifier stages commands. All app vocabulary is passed in; nothing is assumed.
|
|
42
42
|
*
|
|
@@ -62,9 +62,9 @@ export interface StaffNotifierOptions<C extends string, Ch extends string> {
|
|
|
62
62
|
* @typeParam C The app's dispatch categories.
|
|
63
63
|
* @typeParam Ch The app's dispatch channels.
|
|
64
64
|
* @example
|
|
65
|
-
* const notifier = new StaffNotifier(outbox, new ConfiguredStaffRecipients({ '
|
|
65
|
+
* const notifier = new StaffNotifier(outbox, new ConfiguredStaffRecipients({ 'jobs.manage': config.opsEmails }),
|
|
66
66
|
* { category: 'staff', defaultChannels: ['email'], logger });
|
|
67
|
-
* await notifier.alert(tx, { template: '
|
|
67
|
+
* await notifier.alert(tx, { template: 'job-failed', permission: 'jobs.manage', data: { reference } }, { correlationId });
|
|
68
68
|
*/
|
|
69
69
|
export declare class StaffNotifier<E, C extends string = string, Ch extends string = string> {
|
|
70
70
|
private readonly outbox;
|
|
@@ -79,7 +79,7 @@ export declare class StaffNotifier<E, C extends string = string, Ch extends stri
|
|
|
79
79
|
*
|
|
80
80
|
* @param executor The caller's open transaction; the commands commit or roll back with it.
|
|
81
81
|
* @param alert Template, permission, variables and optional channels.
|
|
82
|
-
* @param meta Correlation id
|
|
82
|
+
* @param meta Correlation id for tracing; the actor is always the system.
|
|
83
83
|
* @returns How many commands were staged (0 when nobody is configured).
|
|
84
84
|
*/
|
|
85
85
|
alert(executor: E, alert: StaffAlert<Ch>, meta?: StaffAlertMeta): Promise<number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staff-notifier.d.ts","sourceRoot":"","sources":["../../../src/messaging/staff-notifier.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,uCAAuC,CAAC;AAE/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"staff-notifier.d.ts","sourceRoot":"","sources":["../../../src/messaging/staff-notifier.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,uCAAuC,CAAC;AAE/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtG;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU,CAAC,EAAE,SAAS,MAAM,GAAG,MAAM;IACpD,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpC,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,SAAS,MAAM;IACvE,yEAAyE;IACzE,QAAQ,EAAE,CAAC,CAAC;IACZ,iHAAiH;IACjH,eAAe,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAAE,SAAS,MAAM,GAAG,MAAM;IAO/E,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAP7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAI;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,UAAU,EAAE,sBAAsB,EACnD,OAAO,EAAE,oBAAoB,CAAC,CAAC,EAAE,EAAE,CAAC;IAQtC;;;;;;;OAOG;IACG,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;CAoB5F"}
|
|
@@ -42,8 +42,8 @@ export declare class ConfiguredStaffRecipients implements StaffRecipientResolver
|
|
|
42
42
|
*/
|
|
43
43
|
export declare const staffEmailListSchema: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodString>, string[], string | undefined>, string[], string | undefined>, {
|
|
44
44
|
email: string;
|
|
45
|
-
userId?: string | null | undefined;
|
|
46
45
|
name?: string | undefined;
|
|
46
|
+
userId?: string | null | undefined;
|
|
47
47
|
locale?: string | null | undefined;
|
|
48
48
|
timezone?: string | null | undefined;
|
|
49
49
|
}[], string | undefined>;
|
|
@@ -1,23 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Naming for exchanges and queues
|
|
3
|
-
* environments that
|
|
2
|
+
* Naming for exchanges and queues, all derived from the app slug and the environment prefix
|
|
3
|
+
* (`QUEUE_PREFIX`), so two environments that share a broker or vhost never see each other's traffic.
|
|
4
4
|
*
|
|
5
|
-
* events exchange
|
|
6
|
-
* commands exchange
|
|
7
|
-
*
|
|
5
|
+
* events exchange {app}.{prefix}.events (topic) domain events, e.g. `thing.created`
|
|
6
|
+
* commands exchange {app}.{prefix}.commands (direct) work for one owner, e.g. `mail:send`
|
|
7
|
+
* dead-letter exch. {app}.{prefix}.{service}.dlx (direct) one per service
|
|
8
|
+
* service queues {prefix}.{service}.{purpose} e.g. `dev.billing.thing-events`
|
|
9
|
+
* dead-letter queue {queue}.dlq retry queues {queue}.retry.{ms} delay queues {queue}.delay.{ms}
|
|
8
10
|
*/
|
|
9
11
|
export interface Topology {
|
|
10
12
|
readonly app: string;
|
|
11
13
|
readonly prefix: string;
|
|
12
14
|
readonly eventsExchange: string;
|
|
13
15
|
readonly commandsExchange: string;
|
|
14
|
-
/** Physical queue name for a logical name. */
|
|
16
|
+
/** Physical queue name for a logical name (adds the environment prefix once). */
|
|
15
17
|
queue(name: string): string;
|
|
18
|
+
/** `{prefix}.{service}.{purpose}` — the name of a service's subscription queue. */
|
|
19
|
+
queueName(service: string, purpose: string): string;
|
|
20
|
+
/** `{app}.{prefix}.{service}.dlx` — the service's dead-letter exchange. */
|
|
21
|
+
deadLetterExchange(service: string): string;
|
|
16
22
|
}
|
|
17
|
-
|
|
23
|
+
/** Options for {@link createTopology}; values come from config, never literals in shared code. */
|
|
24
|
+
export interface TopologyOptions {
|
|
25
|
+
/** App slug (lower-case letters, digits, `-`, `_`). */
|
|
18
26
|
app: string;
|
|
27
|
+
/** Environment prefix, i.e. `QUEUE_PREFIX` (lower-case letters, digits, `-`, `_`). */
|
|
19
28
|
prefix: string;
|
|
20
|
-
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Builds the naming scheme for one app and environment.
|
|
32
|
+
*
|
|
33
|
+
* @param options App slug and environment prefix.
|
|
34
|
+
* @returns The {@link Topology}.
|
|
35
|
+
* @throws Error when a segment is empty or has other characters.
|
|
36
|
+
* @example const topology = createTopology({ app: config.APP_SLUG, prefix: config.QUEUE_PREFIX });
|
|
37
|
+
*/
|
|
38
|
+
export declare function createTopology(options: TopologyOptions): Topology;
|
|
39
|
+
/** Retry queue for one delay: a fixed TTL, dead-lettering back into `queue`. */
|
|
21
40
|
export declare const retryQueueName: (queue: string, delayMs: number) => string;
|
|
41
|
+
/** Dead-letter queue of `queue`. */
|
|
22
42
|
export declare const deadLetterQueueName: (queue: string) => string;
|
|
43
|
+
/** Smallest delay bucket for {@link delayQueueName}. */
|
|
44
|
+
export declare const MIN_DELAY_BUCKET_MS = 1000;
|
|
45
|
+
/**
|
|
46
|
+
* Delay queue for `scheduleDelayed`: one per power-of-two bucket (1s, 2s, 4s …) at or above `delayMs`.
|
|
47
|
+
* Per-message TTLs only expire at the head of a queue, so bucketing bounds how long a short delay can
|
|
48
|
+
* wait behind a longer one (at most its own bucket size).
|
|
49
|
+
*
|
|
50
|
+
* @param queue Target queue (physical name).
|
|
51
|
+
* @param delayMs Requested delay in milliseconds.
|
|
52
|
+
* @returns `{queue}.delay.{bucketMs}`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function delayQueueName(queue: string, delayMs: number): string;
|
|
23
55
|
//# sourceMappingURL=topology.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../../../src/messaging/topology.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../../../src/messaging/topology.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,iFAAiF;IACjF,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,mFAAmF;IACnF,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACpD,2EAA2E;IAC3E,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7C;AAED,kGAAkG;AAClG,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;CAChB;AAWD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ,CAYjE;AAED,gFAAgF;AAChF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,EAAE,SAAS,MAAM,WAAgC,CAAC;AAC9F,oCAAoC;AACpC,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,WAAmB,CAAC;AAErE,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIrE"}
|
|
@@ -2,27 +2,63 @@ import type { NextFunction, Request, Response } from 'express';
|
|
|
2
2
|
import type { Redis } from 'ioredis';
|
|
3
3
|
import { type RateLimiterAbstract } from 'rate-limiter-flexible';
|
|
4
4
|
import type { Logger } from '../types/index.js';
|
|
5
|
+
import { type RedisKeyspace } from '../cache/keyspace.js';
|
|
6
|
+
export * from './keys.js';
|
|
7
|
+
/** Inputs to {@link createLimiter}. */
|
|
5
8
|
export interface RateLimitOptions {
|
|
6
9
|
points: number;
|
|
7
10
|
durationSec: number;
|
|
8
|
-
/**
|
|
9
|
-
|
|
11
|
+
/** The service keyspace; limiter keys read `{prefix}rl:{scope}:{key}`. */
|
|
12
|
+
keyspace: RedisKeyspace;
|
|
13
|
+
/** Limit name, unique per limiter (lower-case kebab-case), e.g. `sign-in-ip`. */
|
|
14
|
+
scope: string;
|
|
10
15
|
redis?: Redis | null;
|
|
11
16
|
/** Lock the key for this long once exhausted (default: none). */
|
|
12
17
|
blockDurationSec?: number;
|
|
13
18
|
logger?: Logger;
|
|
14
19
|
}
|
|
15
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Redis limiter with an in-memory insurance limiter so a Redis outage never blocks traffic. Its
|
|
22
|
+
* keys come from the keyspace; pass already-encoded keys (see {@link limiterKey}) to `consume`.
|
|
23
|
+
*
|
|
24
|
+
* @param options Points, window, keyspace and scope.
|
|
25
|
+
* @returns The limiter.
|
|
26
|
+
* @example const limiter = createLimiter({ keyspace: ks, scope: 'sign-in-ip', points: 10, durationSec: 60, redis });
|
|
27
|
+
*/
|
|
16
28
|
export declare function createLimiter(options: RateLimitOptions): RateLimiterAbstract;
|
|
29
|
+
/**
|
|
30
|
+
* Encodes a raw limiter key (user id, IP …) so it cannot add segments to the limiter's Redis key.
|
|
31
|
+
*
|
|
32
|
+
* @param raw Raw identifier.
|
|
33
|
+
* @returns The encoded key part.
|
|
34
|
+
* @example limiter.consume(limiterKey(req.ip))
|
|
35
|
+
*/
|
|
36
|
+
export declare const limiterKey: (raw: string) => string;
|
|
17
37
|
/**
|
|
18
38
|
* Consumes one point for `key`; throws TooManyRequestsError (429) when exhausted.
|
|
19
|
-
* For in-service checks such as per-identifier
|
|
39
|
+
* For in-service checks such as per-identifier sign-in throttling.
|
|
40
|
+
*
|
|
41
|
+
* @param limiter Limiter from {@link createLimiter}.
|
|
42
|
+
* @param key Encoded key (see {@link limiterKey}).
|
|
43
|
+
* @param message Optional public message for the 429.
|
|
44
|
+
* @throws TooManyRequestsError when the limit is exhausted; rethrows limiter failures.
|
|
45
|
+
* @example await consumeOrThrow(limiter, limiterKey(userId));
|
|
20
46
|
*/
|
|
21
47
|
export declare function consumeOrThrow(limiter: RateLimiterAbstract, key: string, message?: string): Promise<void>;
|
|
48
|
+
/** Inputs to {@link rateLimitMiddleware}: limiter options plus the request → key function. */
|
|
22
49
|
export interface RateLimitMiddlewareOptions extends RateLimitOptions {
|
|
23
50
|
/** Default: authenticated user ID, else client IP. */
|
|
24
51
|
keyOf?: (req: Request) => string;
|
|
25
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Express middleware that consumes one point per request. Sets `X-RateLimit-Limit` and
|
|
55
|
+
* `X-RateLimit-Remaining`; when exhausted answers 429 `RATE_LIMITED` with `Retry-After` (seconds).
|
|
56
|
+
* Fails open: a limiter error (not a rejection) is logged and the request continues.
|
|
57
|
+
*
|
|
58
|
+
* @param options Limiter options and `keyOf` (default user id, else client IP).
|
|
59
|
+
* @returns The middleware.
|
|
60
|
+
* @example router.post('/sessions', rateLimitMiddleware({ keyspace: ks, scope: 'sign-in-ip', points: 10, durationSec: 60, redis }), handler);
|
|
61
|
+
*/
|
|
26
62
|
export declare function rateLimitMiddleware(options: RateLimitMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
27
63
|
export type { RateLimiterAbstract };
|
|
28
64
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAuC,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAuC,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGzE,cAAc,WAAW,CAAC;AAE1B,uCAAuC;AACvC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,QAAQ,EAAE,aAAa,CAAC;IACxB,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,mBAAmB,CAY5E;AAED;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,MAA4B,CAAC;AAEtE;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/G;AAED,8FAA8F;AAC9F,MAAM,WAAW,0BAA2B,SAAQ,gBAAgB;IAClE,sDAAsD;IACtD,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,IAMvD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAiB9E;AAED,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type RedisKey, type RedisKeyspace } from '../cache/keyspace.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rate-limit key builder and the sliding-window limiter contract. Dependency-free (exported from the
|
|
4
|
+
* package root as well as `/rate-limit`); the consuming service implements the sliding window.
|
|
5
|
+
*/
|
|
6
|
+
/** Purpose segment for every rate-limit key: `{prefix}rl:{scope}:…`. */
|
|
7
|
+
export declare const RATE_LIMIT_PURPOSE = "rl";
|
|
8
|
+
/** What a limit counts against. At least one dimension is required; they combine in a fixed order. */
|
|
9
|
+
export interface RateLimitKeyInput {
|
|
10
|
+
/** Limit name, e.g. `sign-in` (lower-case kebab-case). */
|
|
11
|
+
scope: string;
|
|
12
|
+
ip?: string;
|
|
13
|
+
userId?: string;
|
|
14
|
+
/** Normalised (trimmed, lower-cased) and always hashed — never stored in clear. */
|
|
15
|
+
email?: string;
|
|
16
|
+
/** Request host, lower-cased. */
|
|
17
|
+
host?: string;
|
|
18
|
+
/** Route template, e.g. `/sessions` (encoded, so slashes cannot add segments). */
|
|
19
|
+
route?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Builds `{prefix}rl:{scope}[:ip:{ip}][:user:{id}][:email:{hash}][:host:{host}][:route:{route}]`.
|
|
23
|
+
*
|
|
24
|
+
* @param keyspace The service keyspace.
|
|
25
|
+
* @param input Scope plus at least one dimension.
|
|
26
|
+
* @returns The rate-limit key.
|
|
27
|
+
* @throws ConfigError when no dimension is given or the scope is invalid.
|
|
28
|
+
* @example rateLimitKey(ks, { scope: 'sign-in', ip: req.ip, email: body.email })
|
|
29
|
+
*/
|
|
30
|
+
export declare function rateLimitKey(keyspace: RedisKeyspace, input: RateLimitKeyInput): RedisKey;
|
|
31
|
+
/** Input to one sliding-window check. */
|
|
32
|
+
export interface SlidingWindowCheck {
|
|
33
|
+
/** Key from {@link rateLimitKey}. */
|
|
34
|
+
key: RedisKey;
|
|
35
|
+
/** Requests allowed per window. */
|
|
36
|
+
limit: number;
|
|
37
|
+
/** Window length in milliseconds. */
|
|
38
|
+
windowMs: number;
|
|
39
|
+
/** Clock override for tests (epoch ms). */
|
|
40
|
+
now?: number;
|
|
41
|
+
}
|
|
42
|
+
/** Outcome of one sliding-window check. */
|
|
43
|
+
export interface SlidingWindowResult {
|
|
44
|
+
allowed: boolean;
|
|
45
|
+
/** Requests left in the current window (0 when refused). */
|
|
46
|
+
remaining: number;
|
|
47
|
+
/** Milliseconds until the next request would be allowed (0 when allowed). */
|
|
48
|
+
retryAfterMs: number;
|
|
49
|
+
}
|
|
50
|
+
/** Sliding-window limiter contract; implemented by the consuming service (e.g. over Redis sorted sets). */
|
|
51
|
+
export type SlidingWindowLimiter = (check: SlidingWindowCheck) => Promise<SlidingWindowResult>;
|
|
52
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/keys.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,QAAQ,EAAqB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3G;;;GAGG;AAEH,wEAAwE;AACxE,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,sGAAsG;AACtG,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAeD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,iBAAiB,GAAG,QAAQ,CAUxF;AAED,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,GAAG,EAAE,QAAQ,CAAC;IACd,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,2GAA2G;AAC3G,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { Server as HttpServer } from 'node:http';
|
|
2
|
+
import type { Redis } from 'ioredis';
|
|
2
3
|
import { Server, type ServerOptions, type Socket } from 'socket.io';
|
|
4
|
+
import type { RedisKeyspace } from '../cache/keyspace.js';
|
|
5
|
+
import { type IdentityProtocol } from '../identity/index.js';
|
|
3
6
|
import type { AuthUser, Logger } from '../types/index.js';
|
|
7
|
+
import { type SocketTicketClaims, type SocketTicketKeyOptions, type SocketTicketRejection } from './ticket.js';
|
|
8
|
+
export * from './ticket.js';
|
|
4
9
|
export interface SocketServerOptions {
|
|
5
10
|
/** Socket.IO path, e.g. `/ws/notifications` (the gateway proxies the same path). */
|
|
6
11
|
path: string;
|
|
@@ -23,8 +28,87 @@ export interface SocketEmitter {
|
|
|
23
28
|
emitToRoom(room: string, event: string, payload: unknown): void;
|
|
24
29
|
close(): Promise<void>;
|
|
25
30
|
}
|
|
31
|
+
/** Name of the private room every connection of `userId` joins. */
|
|
26
32
|
export declare const userRoom: (userId: string) => string;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a Socket.IO server that authenticates every connection and joins it only to server-derived rooms.
|
|
35
|
+
* The verified user is in `socket.data.identity`.
|
|
36
|
+
*
|
|
37
|
+
* @example const sockets = createSocketServer(httpServer, { path: '/ws', authenticate: gatewaySocketAuth({ secret, protocol }) });
|
|
38
|
+
*/
|
|
27
39
|
export declare function createSocketServer(httpServer: HttpServer, options: SocketServerOptions): SocketEmitter;
|
|
28
|
-
/**
|
|
29
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Trusts the gateway-signed (v2) identity headers forwarded on the WebSocket upgrade request. The gateway
|
|
42
|
+
* signs the upgrade as `GET <handshake path>` (query ignored).
|
|
43
|
+
*
|
|
44
|
+
* @param options The shared secret (at least 32 characters) and the app's identity protocol.
|
|
45
|
+
* @returns An `authenticate` function for {@link createSocketServer}.
|
|
46
|
+
* @example createSocketServer(server, { path: '/ws', authenticate: gatewaySocketAuth({ secret, protocol }) });
|
|
47
|
+
*/
|
|
48
|
+
export declare function gatewaySocketAuth(options: {
|
|
49
|
+
secret: string;
|
|
50
|
+
protocol: IdentityProtocol;
|
|
51
|
+
}): (socket: Socket) => AuthUser | null;
|
|
52
|
+
/** Why a ticket handshake was refused: a ticket problem, an origin problem or a replayed ticket. */
|
|
53
|
+
export type SocketRejectionReason = SocketTicketRejection | 'origin_not_allowed' | 'replayed';
|
|
54
|
+
/** Passed to `onRejected` so the service can log it and publish its security event. */
|
|
55
|
+
export interface SocketRejection {
|
|
56
|
+
reason: SocketRejectionReason;
|
|
57
|
+
/** Known once the ticket verified (origin and replay rejections). */
|
|
58
|
+
userId: string | null;
|
|
59
|
+
/** The Socket.IO path that was refused. */
|
|
60
|
+
path: string;
|
|
61
|
+
origin: string | null;
|
|
62
|
+
}
|
|
63
|
+
/** Settings for {@link createTicketHandshake}. */
|
|
64
|
+
export interface TicketHandshakeOptions extends SocketTicketKeyOptions {
|
|
65
|
+
/** Ticket audience(s) this server accepts. */
|
|
66
|
+
audience: string | readonly string[];
|
|
67
|
+
/** Browser origins allowed for this ticket holder (e.g. the app's origins, or a tenant's own domain). */
|
|
68
|
+
allowedOrigins: (claims: SocketTicketClaims) => readonly string[] | Promise<readonly string[]>;
|
|
69
|
+
/** Accept handshakes without an `Origin` header (non-browser clients). Default false. */
|
|
70
|
+
allowMissingOrigin?: boolean;
|
|
71
|
+
/** Returns false when the ticket id was already used (makes tickets single-use). */
|
|
72
|
+
isFirstUse?: (claims: SocketTicketClaims) => Promise<boolean>;
|
|
73
|
+
/** Called for every refused handshake. Must not throw. */
|
|
74
|
+
onRejected?: (rejection: SocketRejection) => void;
|
|
75
|
+
/** Socket.IO path, reported in rejections. */
|
|
76
|
+
path: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The handshake check on its own (testable without a server): verifies the ticket from
|
|
80
|
+
* `socket.handshake.auth.ticket`, then the browser origin against `allowedOrigins(claims)`, then
|
|
81
|
+
* single use.
|
|
82
|
+
*
|
|
83
|
+
* @param options Ticket keys, audience, origin rule, replay check and rejection hook.
|
|
84
|
+
* @returns `authenticate(socket)` resolving to the claims, or null when refused.
|
|
85
|
+
*/
|
|
86
|
+
export declare function createTicketHandshake(options: TicketHandshakeOptions): (socket: Pick<Socket, 'handshake'>) => Promise<SocketTicketClaims | null>;
|
|
87
|
+
/** Settings for {@link createTicketSocketServer}. */
|
|
88
|
+
export interface TicketSocketServerOptions extends Omit<TicketHandshakeOptions, 'isFirstUse'> {
|
|
89
|
+
httpServer: HttpServer;
|
|
90
|
+
/**
|
|
91
|
+
* Shared Redis: enables the `@socket.io/redis-adapter` fan-out across replicas (channel prefix from
|
|
92
|
+
* `keyspace`) and makes tickets single-use (`{keyspace}socket-ticket:{jti}`, TTL = ticket lifetime).
|
|
93
|
+
* Omit only for a single in-process instance (tests, local tools).
|
|
94
|
+
*/
|
|
95
|
+
redis?: Redis;
|
|
96
|
+
/** The service's keyspace; required with `redis`. */
|
|
97
|
+
keyspace?: RedisKeyspace;
|
|
98
|
+
/** Extra rooms to join on connect, derived from the verified claims. `user:{userId}` is always joined. */
|
|
99
|
+
rooms?: (claims: SocketTicketClaims) => string[];
|
|
100
|
+
serverOptions?: Partial<ServerOptions>;
|
|
101
|
+
logger?: Logger;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Creates a Socket.IO server whose clients authenticate with a short-lived ticket
|
|
105
|
+
* (`io(url, { path, auth: (cb) => getTicket().then((ticket) => cb({ ticket })) })`). Each connection
|
|
106
|
+
* auto-joins `user:{userId}`; the verified claims are in `socket.data.identity` for later room checks
|
|
107
|
+
* with `canJoinScopeRoom`.
|
|
108
|
+
*
|
|
109
|
+
* @param options HTTP server, path, ticket keys, origin rule, Redis + keyspace, rejection hook.
|
|
110
|
+
* @returns The emitter.
|
|
111
|
+
* @example createTicketSocketServer({ httpServer, path: '/ws', secret, domain, audience: 'admin-app', redis, keyspace, allowedOrigins: () => origins, onRejected })
|
|
112
|
+
*/
|
|
113
|
+
export declare function createTicketSocketServer(options: TicketSocketServerOptions): SocketEmitter;
|
|
30
114
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/socket/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/socket/index.ts"],"names":[],"mappings":"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"}
|