@heavybit/shared-lib 1.3.2 → 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 +261 -0
- 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/errors.js +44 -5
- package/dist/cjs/common/errors.js.map +1 -1
- 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 +63 -11
- package/dist/cjs/common/phone.js.map +1 -1
- package/dist/cjs/common/response.js +78 -5
- package/dist/cjs/common/response.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 +140 -20
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/context/index.js +49 -0
- package/dist/cjs/context/index.js.map +1 -0
- package/dist/cjs/contracts/index.js +0 -2
- package/dist/cjs/contracts/index.js.map +1 -1
- package/dist/cjs/contracts/notification-dispatch.js +87 -63
- package/dist/cjs/contracts/notification-dispatch.js.map +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 +88 -41
- package/dist/cjs/express/auth.js.map +1 -1
- package/dist/cjs/express/index.js +3 -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/middleware.js +154 -34
- package/dist/cjs/express/middleware.js.map +1 -1
- package/dist/cjs/express/respond.js +47 -0
- package/dist/cjs/express/respond.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 +7 -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/index.js +76 -40
- package/dist/cjs/logging/index.js.map +1 -1
- package/dist/cjs/logging/redact.js +112 -0
- package/dist/cjs/logging/redact.js.map +1 -0
- 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 +3 -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 +36 -44
- package/dist/cjs/messaging/staff-notifier.js.map +1 -1
- package/dist/cjs/messaging/staff-recipients.js +57 -0
- package/dist/cjs/messaging/staff-recipients.js.map +1 -0
- 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/cjs/validation/index.js +27 -3
- package/dist/cjs/validation/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/errors.js +42 -4
- package/dist/esm/common/errors.js.map +1 -1
- 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 +63 -11
- package/dist/esm/common/phone.js.map +1 -1
- package/dist/esm/common/response.js +75 -5
- package/dist/esm/common/response.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 +136 -19
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/context/index.js +44 -0
- package/dist/esm/context/index.js.map +1 -0
- package/dist/esm/contracts/index.js +0 -2
- package/dist/esm/contracts/index.js.map +1 -1
- package/dist/esm/contracts/notification-dispatch.js +85 -62
- package/dist/esm/contracts/notification-dispatch.js.map +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 +87 -40
- package/dist/esm/express/auth.js.map +1 -1
- package/dist/esm/express/index.js +3 -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/middleware.js +146 -27
- package/dist/esm/express/middleware.js.map +1 -1
- package/dist/esm/express/respond.js +42 -0
- package/dist/esm/express/respond.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 +7 -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/index.js +68 -39
- package/dist/esm/logging/index.js.map +1 -1
- package/dist/esm/logging/redact.js +106 -0
- package/dist/esm/logging/redact.js.map +1 -0
- 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 +3 -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 +36 -43
- package/dist/esm/messaging/staff-notifier.js.map +1 -1
- package/dist/esm/messaging/staff-recipients.js +53 -0
- package/dist/esm/messaging/staff-recipients.js.map +1 -0
- 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/esm/validation/index.js +27 -2
- package/dist/esm/validation/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/alerting/index.d.ts +1 -1
- package/dist/types/alerting/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/errors.d.ts +48 -7
- package/dist/types/common/errors.d.ts.map +1 -1
- 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 +45 -6
- package/dist/types/common/phone.d.ts.map +1 -1
- package/dist/types/common/response.d.ts +66 -5
- package/dist/types/common/response.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 +252 -28
- package/dist/types/config/index.d.ts.map +1 -1
- package/dist/types/context/index.d.ts +39 -0
- package/dist/types/context/index.d.ts.map +1 -0
- package/dist/types/contracts/index.d.ts +0 -2
- package/dist/types/contracts/index.d.ts.map +1 -1
- package/dist/types/contracts/notification-dispatch.d.ts +204 -86
- package/dist/types/contracts/notification-dispatch.d.ts.map +1 -1
- 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 +63 -11
- package/dist/types/express/auth.d.ts.map +1 -1
- package/dist/types/express/index.d.ts +3 -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/middleware.d.ts +86 -7
- package/dist/types/express/middleware.d.ts.map +1 -1
- package/dist/types/express/respond.d.ts +41 -0
- package/dist/types/express/respond.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 +7 -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/index.d.ts +30 -4
- package/dist/types/logging/index.d.ts.map +1 -1
- package/dist/types/logging/redact.d.ts +54 -0
- package/dist/types/logging/redact.d.ts.map +1 -0
- 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 +8 -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 +69 -38
- package/dist/types/messaging/staff-notifier.d.ts.map +1 -1
- package/dist/types/messaging/staff-recipients.d.ts +50 -0
- package/dist/types/messaging/staff-recipients.d.ts.map +1 -0
- 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 +62 -15
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/validation/index.d.ts +33 -2
- package/dist/types/validation/index.d.ts.map +1 -1
- package/package.json +3 -1
- package/dist/cjs/contracts/editorial-draft.js +0 -120
- package/dist/cjs/contracts/editorial-draft.js.map +0 -1
- package/dist/cjs/contracts/upload-import.js +0 -54
- package/dist/cjs/contracts/upload-import.js.map +0 -1
- package/dist/esm/contracts/editorial-draft.js +0 -117
- package/dist/esm/contracts/editorial-draft.js.map +0 -1
- package/dist/esm/contracts/upload-import.js +0 -51
- package/dist/esm/contracts/upload-import.js.map +0 -1
- package/dist/types/contracts/editorial-draft.d.ts +0 -610
- package/dist/types/contracts/editorial-draft.d.ts.map +0 -1
- package/dist/types/contracts/upload-import.d.ts +0 -96
- package/dist/types/contracts/upload-import.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.js","sourceRoot":"","sources":["../../../src/socket/ticket.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,24 +19,26 @@ exports.RecordingLogger = RecordingLogger;
|
|
|
19
19
|
function makeAuthUser(overrides = {}) {
|
|
20
20
|
return { id: (0, id_js_1.newId)(), email: 'user@example.com', roles: [], permissions: [], scopes: {}, attrs: {}, ...overrides };
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Gateway-signed (v2) identity headers for route tests (use with supertest `.set()`). The method and path
|
|
24
|
+
* must match the request the test sends.
|
|
25
|
+
*
|
|
26
|
+
* @example request(app).get('/v1/items').set(identityHeaders({ user, secret, protocol, method: 'GET', path: '/v1/items' }));
|
|
27
|
+
*/
|
|
28
|
+
function identityHeaders(input) {
|
|
29
|
+
return (0, index_js_1.signedIdentityHeaders)(input);
|
|
25
30
|
}
|
|
26
|
-
/** Records everything published/sent so tests can assert on events, commands and
|
|
31
|
+
/** Records everything published/sent so tests can assert on events, commands, queue sends and delayed sends. */
|
|
27
32
|
class RecordingBus {
|
|
28
|
-
source;
|
|
29
33
|
events = [];
|
|
30
34
|
commands = [];
|
|
31
35
|
queued = [];
|
|
36
|
+
delayed = [];
|
|
32
37
|
failWith = null;
|
|
33
|
-
|
|
34
|
-
this.source = source;
|
|
35
|
-
}
|
|
36
|
-
async publish(type, data, meta) {
|
|
38
|
+
async publish(routingKey, data, meta) {
|
|
37
39
|
if (this.failWith)
|
|
38
40
|
throw this.failWith;
|
|
39
|
-
const envelope = (0, envelope_js_1.buildEnvelope)(
|
|
41
|
+
const envelope = (0, envelope_js_1.buildEnvelope)(routingKey, data, meta);
|
|
40
42
|
this.events.push(envelope);
|
|
41
43
|
return envelope;
|
|
42
44
|
}
|
|
@@ -48,7 +50,7 @@ class RecordingBus {
|
|
|
48
50
|
async send(command, data, meta) {
|
|
49
51
|
if (this.failWith)
|
|
50
52
|
throw this.failWith;
|
|
51
|
-
const envelope = (0, envelope_js_1.buildEnvelope)(command, data,
|
|
53
|
+
const envelope = (0, envelope_js_1.buildEnvelope)(command, data, meta);
|
|
52
54
|
this.commands.push(envelope);
|
|
53
55
|
return envelope;
|
|
54
56
|
}
|
|
@@ -62,11 +64,18 @@ class RecordingBus {
|
|
|
62
64
|
throw this.failWith;
|
|
63
65
|
this.queued.push({ queue, payload, options });
|
|
64
66
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
async scheduleDelayed(queue, payload, delayMs, options = {}) {
|
|
68
|
+
if (this.failWith)
|
|
69
|
+
throw this.failWith;
|
|
70
|
+
this.delayed.push({ queue, payload, delayMs, options });
|
|
71
|
+
}
|
|
72
|
+
/** Published events with this routing key. */
|
|
73
|
+
eventsOfType(routingKey) {
|
|
74
|
+
return this.events.filter((e) => e.routingKey === routingKey);
|
|
67
75
|
}
|
|
76
|
+
/** Sent commands with this name. */
|
|
68
77
|
commandsOfType(command) {
|
|
69
|
-
return this.commands.filter((e) => e.
|
|
78
|
+
return this.commands.filter((e) => e.routingKey === command);
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
81
|
exports.RecordingBus = RecordingBus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.z = exports.csvList = exports.booleanish = exports.passwordSchema = exports.slugSchema = exports.emailSchema = exports.sortOrderSchema = exports.paginationSchema = exports.idParamSchema = exports.idSchema = void 0;
|
|
3
|
+
exports.z = exports.csvList = exports.booleanish = exports.passwordSchema = exports.slugSchema = exports.emailSchema = exports.sortOrderSchema = exports.paginationSchema = exports.idParam = exports.idParamSchema = exports.idSchema = void 0;
|
|
4
4
|
exports.zodIssuesToErrors = zodIssuesToErrors;
|
|
5
5
|
exports.parseOrThrow = parseOrThrow;
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
Object.defineProperty(exports, "z", { enumerable: true, get: function () { return zod_1.z; } });
|
|
8
8
|
const id_js_1 = require("../common/id.js");
|
|
9
9
|
const errors_js_1 = require("../common/errors.js");
|
|
10
|
+
/** A ULID in canonical form (26 upper-case Crockford base32 chars), as `newId()` makes and `CHAR(26)` stores. */
|
|
10
11
|
exports.idSchema = zod_1.z.string().regex(id_js_1.ID_PATTERN, 'Invalid id');
|
|
12
|
+
/** Route params `{ id }` where `id` is a canonical ULID. Use with `validate({ params: idParamSchema })`. */
|
|
11
13
|
exports.idParamSchema = zod_1.z.object({ id: exports.idSchema });
|
|
14
|
+
/**
|
|
15
|
+
* Alias of {@link idParamSchema} for `validate({ params: idParam })`. Stricter than `z.string().ulid()`:
|
|
16
|
+
* lower-case ULIDs are rejected, so a lookup never misses a stored upper-case id.
|
|
17
|
+
*/
|
|
18
|
+
exports.idParam = exports.idParamSchema;
|
|
19
|
+
/** Offset pagination query: `page` ≥ 1 (default 1), `limit` 1–100 (default 20). Prefer cursor pagination (D6). */
|
|
12
20
|
exports.paginationSchema = zod_1.z.object({
|
|
13
21
|
page: zod_1.z.coerce.number().int().min(1).default(1),
|
|
14
22
|
limit: zod_1.z.coerce.number().int().min(1).max(100).default(20),
|
|
15
23
|
});
|
|
24
|
+
/** `asc` or `desc`, default `desc`. */
|
|
16
25
|
exports.sortOrderSchema = zod_1.z.enum(['asc', 'desc']).default('desc');
|
|
26
|
+
/** Trimmed, lower-cased email address, max 191 chars. */
|
|
17
27
|
exports.emailSchema = zod_1.z.string().trim().toLowerCase().email('Invalid email address').max(191);
|
|
28
|
+
/** Lower-case kebab-case slug, 1–120 chars. */
|
|
18
29
|
exports.slugSchema = zod_1.z.string().trim().min(1).max(120).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'Invalid slug');
|
|
19
30
|
/** Length-first password rule (NIST 800-63B): 8–128 chars, no composition rules. Tighten per app if needed. */
|
|
20
31
|
exports.passwordSchema = zod_1.z.string().min(8, 'Password must be at least 8 characters').max(128, 'Password is too long');
|
|
@@ -22,7 +33,13 @@ exports.passwordSchema = zod_1.z.string().min(8, 'Password must be at least 8 ch
|
|
|
22
33
|
exports.booleanish = zod_1.z.union([zod_1.z.boolean(), zod_1.z.enum(['true', 'false', '1', '0', 'yes', 'no'])]).transform((v) => v === true || v === 'true' || v === '1' || v === 'yes');
|
|
23
34
|
/** Comma list or repeated query param → string[]. */
|
|
24
35
|
exports.csvList = zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]).transform((v) => (Array.isArray(v) ? v : v.split(',')).map((s) => s.trim()).filter(Boolean));
|
|
25
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Converts Zod issues into the `{ field: [messages] }` shape used by the error envelope.
|
|
38
|
+
*
|
|
39
|
+
* @param error A Zod error.
|
|
40
|
+
* @returns Messages keyed by dotted field path (`_` for the root).
|
|
41
|
+
* @example zodIssuesToErrors(result.error) // { 'items.0': ['Expected string'] }
|
|
42
|
+
*/
|
|
26
43
|
function zodIssuesToErrors(error) {
|
|
27
44
|
const errors = {};
|
|
28
45
|
for (const issue of error.issues) {
|
|
@@ -31,7 +48,14 @@ function zodIssuesToErrors(error) {
|
|
|
31
48
|
}
|
|
32
49
|
return errors;
|
|
33
50
|
}
|
|
34
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Parses `input` or throws a ValidationError (422).
|
|
53
|
+
*
|
|
54
|
+
* @param schema Zod schema.
|
|
55
|
+
* @param input Untrusted value.
|
|
56
|
+
* @returns The parsed value.
|
|
57
|
+
* @example const dto = parseOrThrow(createSchema, payload);
|
|
58
|
+
*/
|
|
35
59
|
function parseOrThrow(schema, input) {
|
|
36
60
|
const result = schema.safeParse(input);
|
|
37
61
|
if (!result.success)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/validation/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/validation/index.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/access/index.js
CHANGED
|
@@ -12,25 +12,33 @@ function grants(granted, required) {
|
|
|
12
12
|
return true;
|
|
13
13
|
return granted.endsWith('.*') && required.startsWith(granted.slice(0, -1));
|
|
14
14
|
}
|
|
15
|
-
/** True when the user holds at least one of `required`. */
|
|
15
|
+
/** True when the user holds at least one of `required`. A super admin holds every permission. */
|
|
16
16
|
export function hasPermission(user, ...required) {
|
|
17
17
|
if (!user)
|
|
18
18
|
return false;
|
|
19
|
+
if (user.isSuperAdmin)
|
|
20
|
+
return true;
|
|
19
21
|
return required.some((perm) => user.permissions.some((g) => grants(g, perm)));
|
|
20
22
|
}
|
|
23
|
+
/** True when the user holds every one of `required`. A super admin holds every permission. */
|
|
21
24
|
export function hasAllPermissions(user, ...required) {
|
|
22
25
|
if (!user)
|
|
23
26
|
return false;
|
|
27
|
+
if (user.isSuperAdmin)
|
|
28
|
+
return true;
|
|
24
29
|
return required.every((perm) => user.permissions.some((g) => grants(g, perm)));
|
|
25
30
|
}
|
|
31
|
+
/** True when the user has at least one of `roles`. Prefer permission checks; roles are coarse. */
|
|
26
32
|
export function hasRole(user, ...roles) {
|
|
27
33
|
return !!user && roles.some((role) => user.roles.includes(role));
|
|
28
34
|
}
|
|
35
|
+
/** Returns the user, or throws UnauthorizedError (401) when there is none. */
|
|
29
36
|
export function requireUser(user) {
|
|
30
37
|
if (!user)
|
|
31
38
|
throw new UnauthorizedError();
|
|
32
39
|
return user;
|
|
33
40
|
}
|
|
41
|
+
/** Returns the user when they hold any of `required` (super admin always does); throws 401/403 otherwise. */
|
|
34
42
|
export function assertPermission(user, ...required) {
|
|
35
43
|
const u = requireUser(user);
|
|
36
44
|
if (!hasPermission(u, ...required))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/access/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,SAAS,MAAM,CAAC,OAAe,EAAE,QAAgB;IAC/C,IAAI,OAAO,KAAK,mBAAmB,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzE,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/access/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { hasAllPermissions } from '../access/index.js';
|
|
2
|
+
import { ConflictError, ForbiddenError } from '../common/errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Two-person approval state machine. A requester asks for a sensitive operation; a different person who
|
|
5
|
+
* holds both the operation's permission and the app's "decide" permission approves or rejects it; the
|
|
6
|
+
* approved operation is then executed once (or fails). Pending requests expire after a TTL.
|
|
7
|
+
*
|
|
8
|
+
* ```
|
|
9
|
+
* pending ──► approved ──► executed
|
|
10
|
+
* │ └──────► failed
|
|
11
|
+
* ├──► rejected
|
|
12
|
+
* ├──► cancelled
|
|
13
|
+
* └──► expired
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* App values (the decide permission and the TTL) are passed in through {@link createApprovalPolicy}.
|
|
17
|
+
*/
|
|
18
|
+
/** Every approval state. */
|
|
19
|
+
export const APPROVAL_STATES = ['pending', 'approved', 'rejected', 'cancelled', 'expired', 'executed', 'failed'];
|
|
20
|
+
const TRANSITIONS = Object.freeze({
|
|
21
|
+
pending: ['approved', 'rejected', 'cancelled', 'expired'],
|
|
22
|
+
approved: ['executed', 'failed'],
|
|
23
|
+
rejected: [],
|
|
24
|
+
cancelled: [],
|
|
25
|
+
expired: [],
|
|
26
|
+
executed: [],
|
|
27
|
+
failed: [],
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* True when `from → to` is an allowed move.
|
|
31
|
+
*
|
|
32
|
+
* @example canTransition('pending', 'approved') // true
|
|
33
|
+
*/
|
|
34
|
+
export function canTransition(from, to) {
|
|
35
|
+
return TRANSITIONS[from]?.includes(to) ?? false;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Throws unless `from → to` is allowed.
|
|
39
|
+
*
|
|
40
|
+
* @throws ConflictError (`APPROVAL_INVALID_TRANSITION`).
|
|
41
|
+
*/
|
|
42
|
+
export function assertTransition(from, to) {
|
|
43
|
+
if (!canTransition(from, to)) {
|
|
44
|
+
throw new ConflictError(`This request can no longer move from ${from} to ${to}`, { code: 'APPROVAL_INVALID_TRANSITION' });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** True when the state allows no further moves. */
|
|
48
|
+
export function isTerminalApprovalState(state) {
|
|
49
|
+
return TRANSITIONS[state].length === 0;
|
|
50
|
+
}
|
|
51
|
+
function assertPending(approval, now) {
|
|
52
|
+
if (approval.state !== 'pending') {
|
|
53
|
+
throw new ConflictError('This request has already been decided', { code: 'APPROVAL_NOT_PENDING' });
|
|
54
|
+
}
|
|
55
|
+
if (approval.expiresAt && new Date(approval.expiresAt).getTime() <= now.getTime()) {
|
|
56
|
+
throw new ConflictError('This request has expired', { code: 'APPROVAL_EXPIRED' });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Throws unless `approver` may approve or reject `approval`: it is pending and not expired, the approver
|
|
61
|
+
* is not the requester (even a super admin cannot approve their own request), and holds both the
|
|
62
|
+
* operation permission and `decidePermission`.
|
|
63
|
+
*
|
|
64
|
+
* @param approval The request.
|
|
65
|
+
* @param approver The deciding user.
|
|
66
|
+
* @param decidePermission The app's "may decide approvals" permission.
|
|
67
|
+
* @param now Clock (tests).
|
|
68
|
+
* @throws ConflictError (`APPROVAL_NOT_PENDING`, `APPROVAL_EXPIRED`) or ForbiddenError
|
|
69
|
+
* (`APPROVAL_SELF_DECISION`, `APPROVAL_FORBIDDEN`).
|
|
70
|
+
*/
|
|
71
|
+
export function assertCanDecide(approval, approver, decidePermission, now = new Date()) {
|
|
72
|
+
assertPending(approval, now);
|
|
73
|
+
if (approver.id === approval.requesterUserId) {
|
|
74
|
+
throw new ForbiddenError('You cannot decide your own request', { code: 'APPROVAL_SELF_DECISION' });
|
|
75
|
+
}
|
|
76
|
+
if (!hasAllPermissions(approver, approval.operationPermission, decidePermission)) {
|
|
77
|
+
throw new ForbiddenError('You do not have permission to decide this request', { code: 'APPROVAL_FORBIDDEN' });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Throws unless `user` may cancel `approval`: only the requester, and only while it is pending.
|
|
82
|
+
*
|
|
83
|
+
* @throws ConflictError (`APPROVAL_NOT_PENDING`) or ForbiddenError (`APPROVAL_NOT_REQUESTER`).
|
|
84
|
+
*/
|
|
85
|
+
export function assertCanCancel(approval, user) {
|
|
86
|
+
if (user.id !== approval.requesterUserId) {
|
|
87
|
+
throw new ForbiddenError('Only the person who made this request can cancel it', { code: 'APPROVAL_NOT_REQUESTER' });
|
|
88
|
+
}
|
|
89
|
+
if (approval.state !== 'pending') {
|
|
90
|
+
throw new ConflictError('This request has already been decided', { code: 'APPROVAL_NOT_PENDING' });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* When a request made at `from` expires.
|
|
95
|
+
*
|
|
96
|
+
* @param ttlSeconds Positive lifetime in seconds.
|
|
97
|
+
* @param from Creation time (default now).
|
|
98
|
+
* @returns The expiry instant.
|
|
99
|
+
* @example approvalExpiresAt(3600, new Date('2026-01-01T00:00:00Z')) // 2026-01-01T01:00:00Z
|
|
100
|
+
*/
|
|
101
|
+
export function approvalExpiresAt(ttlSeconds, from = new Date()) {
|
|
102
|
+
if (!Number.isFinite(ttlSeconds) || ttlSeconds <= 0)
|
|
103
|
+
throw new RangeError('Approval TTL must be a positive number of seconds');
|
|
104
|
+
return new Date(from.getTime() + ttlSeconds * 1000);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Binds the approval rules to an app's decide permission and TTL.
|
|
108
|
+
*
|
|
109
|
+
* @param options Decide permission and TTL.
|
|
110
|
+
* @returns The bound policy.
|
|
111
|
+
* @example const approvals = createApprovalPolicy({ decidePermission: 'requests.decide', ttlSeconds: 86_400 });
|
|
112
|
+
*/
|
|
113
|
+
export function createApprovalPolicy(options) {
|
|
114
|
+
if (!options.decidePermission)
|
|
115
|
+
throw new RangeError('An approval policy needs a decide permission');
|
|
116
|
+
approvalExpiresAt(options.ttlSeconds); // validates the TTL up front
|
|
117
|
+
return Object.freeze({
|
|
118
|
+
decidePermission: options.decidePermission,
|
|
119
|
+
ttlSeconds: options.ttlSeconds,
|
|
120
|
+
canTransition,
|
|
121
|
+
assertTransition,
|
|
122
|
+
assertCanDecide: (approval, approver, now) => assertCanDecide(approval, approver, options.decidePermission, now),
|
|
123
|
+
assertCanCancel,
|
|
124
|
+
expiresAt: (from) => approvalExpiresAt(options.ttlSeconds, from),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/approvals/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { maskPhone } from '../common/phone.js';
|
|
2
|
+
import { toUtcIso } from '../common/time.js';
|
|
3
|
+
import { createKeyClassifier, redactValue } from '../logging/redact.js';
|
|
4
|
+
/** User-agent strings are cut to this length. */
|
|
5
|
+
export const MAX_USER_AGENT_LENGTH = 255;
|
|
6
|
+
/** Stable JSON form for deep comparison (object keys sorted; Dates as ISO strings). */
|
|
7
|
+
function canonical(value) {
|
|
8
|
+
return JSON.stringify(value ?? null, (_key, v) => {
|
|
9
|
+
if (v && typeof v === 'object' && !Array.isArray(v) && !(v instanceof Date)) {
|
|
10
|
+
return Object.fromEntries(Object.entries(v).sort(([a], [b]) => a.localeCompare(b)));
|
|
11
|
+
}
|
|
12
|
+
return v;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function diff(before, after, classifier) {
|
|
16
|
+
const changes = {};
|
|
17
|
+
const redactedFields = [];
|
|
18
|
+
const keys = [...new Set([...Object.keys(before), ...Object.keys(after)])].sort();
|
|
19
|
+
for (const key of keys) {
|
|
20
|
+
const was = before[key] ?? null;
|
|
21
|
+
const now = after[key] ?? null;
|
|
22
|
+
if (canonical(was) === canonical(now))
|
|
23
|
+
continue;
|
|
24
|
+
if (classifier.isSecret(key)) {
|
|
25
|
+
redactedFields.push(key);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const clean = (value) => classifier.isPhone(key) && (typeof value === 'string' || typeof value === 'number') ? maskPhone(String(value)) : redactValue(value, classifier);
|
|
29
|
+
changes[key] = { before: clean(was), after: clean(now) };
|
|
30
|
+
}
|
|
31
|
+
return { changes, redactedFields };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates an audit-event builder with the app's extra redaction words.
|
|
35
|
+
*
|
|
36
|
+
* @param options Extra redaction words.
|
|
37
|
+
* @returns `buildAuditEvent` bound to that list.
|
|
38
|
+
* @example const buildAudit = createAuditEventBuilder({ redactKeys: ['nationalId'] });
|
|
39
|
+
*/
|
|
40
|
+
export function createAuditEventBuilder(options = {}) {
|
|
41
|
+
const classifier = createKeyClassifier(options.redactKeys ?? []);
|
|
42
|
+
return (input) => {
|
|
43
|
+
if (!input.action || !input.entityType)
|
|
44
|
+
throw new RangeError('Audit events need an action and an entity type');
|
|
45
|
+
const { changes, redactedFields } = diff(input.before ?? {}, input.after ?? {}, classifier);
|
|
46
|
+
return {
|
|
47
|
+
action: input.action,
|
|
48
|
+
entityType: input.entityType,
|
|
49
|
+
entityId: input.entityId,
|
|
50
|
+
scope: input.scope ? { key: input.scope.key, id: input.scope.id } : null,
|
|
51
|
+
actorUserId: input.actor?.id ?? null,
|
|
52
|
+
outcome: input.outcome ?? 'success',
|
|
53
|
+
occurredAt: toUtcIso(input.occurredAt ?? new Date()),
|
|
54
|
+
changes,
|
|
55
|
+
redactedFields,
|
|
56
|
+
ip: input.ip ?? null,
|
|
57
|
+
userAgent: input.userAgent ? input.userAgent.slice(0, MAX_USER_AGENT_LENGTH) : null,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Builds an audit event with the default redaction list: the diff holds only changed fields; secret
|
|
63
|
+
* fields are dropped (named in `redactedFields`); phone fields are masked to their last 4 digits.
|
|
64
|
+
*
|
|
65
|
+
* @param input Action, entity, scope, actor, before/after state and request facts.
|
|
66
|
+
* @returns The event.
|
|
67
|
+
* @example buildAuditEvent({ action: 'widget.updated', entityType: 'widget', entityId, scope: { key: 'tenant', id: tenantId }, actor: req.user ?? null, before, after, ip: req.ip, userAgent: req.get('user-agent') })
|
|
68
|
+
*/
|
|
69
|
+
export const buildAuditEvent = createAuditEventBuilder();
|
|
70
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/audit/index.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/cache/index.js
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import { Redis } from 'ioredis';
|
|
2
|
+
import { ConfigError } from '../config/index.js';
|
|
2
3
|
import { silentLogger } from '../logging/index.js';
|
|
4
|
+
export * from './keyspace.js';
|
|
5
|
+
/** Purpose segment for tag index sets: `{prefix}cache-tag:{tag}`. */
|
|
6
|
+
export const CACHE_TAG_PURPOSE = 'cache-tag';
|
|
7
|
+
/** Lower bound for a tag set's own TTL, so it outlives the keys it lists. */
|
|
8
|
+
const MIN_TAG_TTL_SEC = 86_400;
|
|
9
|
+
/**
|
|
10
|
+
* Throws unless `ttlSec` is a positive whole number of seconds.
|
|
11
|
+
*
|
|
12
|
+
* @param ttlSec Proposed TTL.
|
|
13
|
+
* @throws ConfigError for ttl ≤ 0, fractions, NaN or Infinity.
|
|
14
|
+
* @example assertTtl(60)
|
|
15
|
+
*/
|
|
16
|
+
export function assertTtl(ttlSec) {
|
|
17
|
+
if (!Number.isInteger(ttlSec) || ttlSec <= 0)
|
|
18
|
+
throw new ConfigError(`Redis TTL must be a positive whole number of seconds (got ${String(ttlSec)})`);
|
|
19
|
+
}
|
|
20
|
+
function assertOwned(keyspace, key) {
|
|
21
|
+
if (!keyspace.owns(key))
|
|
22
|
+
throw new ConfigError(`Cache key is outside the keyspace ${keyspace.prefix}`);
|
|
23
|
+
}
|
|
3
24
|
const NULL_SENTINEL = '__null__';
|
|
4
25
|
class MemoryStore {
|
|
5
26
|
max;
|
|
@@ -33,14 +54,23 @@ class MemoryStore {
|
|
|
33
54
|
* Redis-backed cache with tag invalidation. If Redis errors, reads fall through to the loader
|
|
34
55
|
* and writes go to a bounded in-memory store, so a cache outage degrades latency rather than
|
|
35
56
|
* availability.
|
|
57
|
+
*
|
|
58
|
+
* @param options Redis client (or null for memory only), the service keyspace, memory bound, logger.
|
|
59
|
+
* @returns The {@link Cache}.
|
|
60
|
+
* @example
|
|
61
|
+
* const cache = createCache({ redis, keyspace: ks, logger });
|
|
62
|
+
* const widget = await cache.wrap(ks.key('widget', id), () => repo.find(id), { ttlSec: 300 });
|
|
36
63
|
*/
|
|
37
64
|
export function createCache(options) {
|
|
38
65
|
const logger = options.logger ?? silentLogger;
|
|
39
|
-
const
|
|
66
|
+
const { keyspace } = options;
|
|
40
67
|
const memory = new MemoryStore(options.memoryMaxEntries ?? 5000);
|
|
41
68
|
const inflight = new Map();
|
|
42
|
-
const k = (key) =>
|
|
43
|
-
|
|
69
|
+
const k = (key) => {
|
|
70
|
+
assertOwned(keyspace, key);
|
|
71
|
+
return key;
|
|
72
|
+
};
|
|
73
|
+
const tagKey = (tag) => keyspace.key(CACHE_TAG_PURPOSE, tag);
|
|
44
74
|
let warned = false;
|
|
45
75
|
const redisFailed = (error) => {
|
|
46
76
|
if (!warned)
|
|
@@ -60,13 +90,14 @@ export function createCache(options) {
|
|
|
60
90
|
}
|
|
61
91
|
return memory.get(k(key));
|
|
62
92
|
};
|
|
63
|
-
const writeRaw = async (key, raw, opts
|
|
64
|
-
|
|
93
|
+
const writeRaw = async (key, raw, opts) => {
|
|
94
|
+
assertTtl(opts.ttlSec);
|
|
95
|
+
const ttl = opts.ttlSec;
|
|
65
96
|
if (options.redis) {
|
|
66
97
|
try {
|
|
67
98
|
const pipeline = options.redis.multi().set(k(key), raw, 'EX', ttl);
|
|
68
99
|
for (const tag of opts.tags ?? [])
|
|
69
|
-
pipeline.sadd(tagKey(tag), k(key)).expire(tagKey(tag), Math.max(ttl,
|
|
100
|
+
pipeline.sadd(tagKey(tag), k(key)).expire(tagKey(tag), Math.max(ttl, MIN_TAG_TTL_SEC));
|
|
70
101
|
await pipeline.exec();
|
|
71
102
|
return;
|
|
72
103
|
}
|
|
@@ -92,7 +123,8 @@ export function createCache(options) {
|
|
|
92
123
|
if (options.redis && keys.length)
|
|
93
124
|
await options.redis.del(...keys.map(k)).catch(redisFailed);
|
|
94
125
|
},
|
|
95
|
-
async wrap(key, loader, opts
|
|
126
|
+
async wrap(key, loader, opts) {
|
|
127
|
+
assertTtl(opts.ttlSec);
|
|
96
128
|
const raw = await readRaw(key);
|
|
97
129
|
if (raw !== undefined) {
|
|
98
130
|
if (raw === NULL_SENTINEL)
|
|
@@ -108,7 +140,7 @@ export function createCache(options) {
|
|
|
108
140
|
if (value !== null && value !== undefined)
|
|
109
141
|
await writeRaw(key, JSON.stringify(value), opts);
|
|
110
142
|
else if (opts.cacheNull)
|
|
111
|
-
await writeRaw(key, NULL_SENTINEL, { ...opts, ttlSec: Math.min(opts.ttlSec
|
|
143
|
+
await writeRaw(key, NULL_SENTINEL, { ...opts, ttlSec: Math.min(opts.ttlSec, 30) });
|
|
112
144
|
return value;
|
|
113
145
|
}
|
|
114
146
|
finally {
|
|
@@ -138,19 +170,30 @@ export function createCache(options) {
|
|
|
138
170
|
};
|
|
139
171
|
return cache;
|
|
140
172
|
}
|
|
141
|
-
/**
|
|
142
|
-
|
|
173
|
+
/**
|
|
174
|
+
* ioredis client that never crashes the process on connection errors and retries forever.
|
|
175
|
+
* It sets no `keyPrefix`: keys carry their full `{app}:{env}:{service}:` prefix from the keyspace.
|
|
176
|
+
*
|
|
177
|
+
* @param env Connection env (`REDIS_URL`, or host/port/password, and `REDIS_DB`).
|
|
178
|
+
* @param opts Logger and extra ioredis options.
|
|
179
|
+
* @returns The client.
|
|
180
|
+
* @example const redis = createRedisClient(config, { logger });
|
|
181
|
+
*/
|
|
182
|
+
export function createRedisClient(env, opts = {}) {
|
|
143
183
|
const logger = opts.logger ?? silentLogger;
|
|
144
184
|
const base = {
|
|
145
|
-
|
|
146
|
-
|
|
185
|
+
host: env.REDIS_HOST,
|
|
186
|
+
port: env.REDIS_PORT,
|
|
187
|
+
password: env.REDIS_PASSWORD || undefined,
|
|
188
|
+
db: env.REDIS_DB ?? 0,
|
|
147
189
|
lazyConnect: false,
|
|
148
190
|
enableOfflineQueue: false,
|
|
149
191
|
maxRetriesPerRequest: 1,
|
|
150
192
|
retryStrategy: (times) => Math.min(times * 500, 10_000),
|
|
151
193
|
...opts.options,
|
|
194
|
+
keyPrefix: undefined,
|
|
152
195
|
};
|
|
153
|
-
const client =
|
|
196
|
+
const client = env.REDIS_URL ? new Redis(env.REDIS_URL, base) : new Redis(base);
|
|
154
197
|
let lastError = '';
|
|
155
198
|
client.on('error', (error) => {
|
|
156
199
|
if (error.message !== lastError)
|
|
@@ -160,4 +203,18 @@ export function createRedisClient(opts) {
|
|
|
160
203
|
client.on('ready', () => { lastError = ''; logger.info('Redis connected', { db: base.db }); });
|
|
161
204
|
return client;
|
|
162
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* `SET key value EX ttlSec` for a keyspace key; refuses a TTL ≤ 0 so no key lives forever.
|
|
208
|
+
*
|
|
209
|
+
* @param redis Client (or anything with a compatible `set`).
|
|
210
|
+
* @param key Key from the service keyspace.
|
|
211
|
+
* @param value String value.
|
|
212
|
+
* @param ttlSec TTL in whole seconds (> 0).
|
|
213
|
+
* @throws ConfigError for an invalid TTL.
|
|
214
|
+
* @example await setWithTtl(redis, ks.key('session', id), payload, 900);
|
|
215
|
+
*/
|
|
216
|
+
export async function setWithTtl(redis, key, value, ttlSec) {
|
|
217
|
+
assertTtl(ttlSec);
|
|
218
|
+
await redis.set(key, value, 'EX', ttlSec);
|
|
219
|
+
}
|
|
163
220
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"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"}
|