@flusys/nestjs-shared 7.1.0 → 8.0.0-beta.1
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/classes/api-controller.class.d.ts +4 -4
- package/classes/api-service.class.d.ts +7 -7
- package/classes/disabled-event-bus.class.d.ts +1 -1
- package/classes/domain-event.publisher.d.ts +1 -1
- package/classes/event-bus.registry.d.ts +1 -1
- package/classes/event-transports/event-transport.registry.d.ts +1 -1
- package/classes/event-transports/index.d.ts +2 -2
- package/classes/event-transports/kafka-transport.optional.d.ts +1 -1
- package/classes/event-transports/memory-transport.d.ts +1 -1
- package/classes/event-transports/rabbitmq-transport.optional.d.ts +1 -1
- package/classes/hybrid-event-bus.class.d.ts +1 -1
- package/classes/index.d.ts +11 -11
- package/constants/index.d.ts +2 -2
- package/decorators/api-response.decorator.d.ts +1 -1
- package/decorators/current-user.decorator.d.ts +1 -1
- package/decorators/index.d.ts +6 -6
- package/decorators/require-permission.decorator.d.ts +1 -1
- package/dtos/filter-and-pagination.dto.d.ts +1 -1
- package/dtos/index.d.ts +6 -6
- package/entities/index.d.ts +3 -3
- package/enums/index.d.ts +3 -3
- package/exceptions/index.d.ts +2 -2
- package/fesm/470.js +2713 -0
- package/fesm/509.js +793 -0
- package/fesm/667.js +606 -0
- package/fesm/67.js +808 -0
- package/fesm/720.js +914 -0
- package/{cjs/classes/event-transports/rabbitmq-transport.optional.js → fesm/chunks/123.js} +78 -55
- package/fesm/{classes/event-transports/kafka-transport.optional.js → chunks/37.js} +74 -41
- package/fesm/classes/index.js +62 -12
- package/fesm/constants/index.js +445 -17
- package/fesm/decorators/index.js +341 -6
- package/fesm/dtos/index.js +23 -6
- package/fesm/entities/index.js +336 -3
- package/fesm/enums/index.js +57 -3
- package/fesm/exceptions/index.js +280 -2
- package/fesm/guards/index.js +1003 -3
- package/fesm/index.js +1524 -14
- package/fesm/interceptors/index.js +924 -5
- package/fesm/interfaces/index.js +57 -11
- package/fesm/middlewares/index.js +33 -1
- package/fesm/modules/index.js +432 -9
- package/fesm/runtime.js +134 -0
- package/fesm/utils/index.js +1045 -8
- package/filters/global-exception.filter.d.ts +1 -1
- package/filters/index.d.ts +1 -1
- package/guards/index.d.ts +3 -3
- package/guards/jwt-auth.guard.d.ts +1 -1
- package/guards/optional-jwt-auth.guard.d.ts +1 -1
- package/guards/permission.guard.d.ts +2 -2
- package/index.d.ts +14 -14
- package/interceptors/delete-empty-id-from-body.interceptor.d.ts +1 -1
- package/interceptors/idempotency.interceptor.d.ts +2 -2
- package/interceptors/index.d.ts +5 -5
- package/interceptors/response-meta.interceptor.d.ts +1 -1
- package/interceptors/set-user-field-on-body.interceptor.d.ts +1 -1
- package/interceptors/slug.interceptor.d.ts +2 -2
- package/interfaces/ai-assistant-adapter.interface.d.ts +1 -1
- package/interfaces/api.interface.d.ts +2 -2
- package/interfaces/datasource.interface.d.ts +1 -1
- package/interfaces/event-manager-adapter.interface.d.ts +2 -2
- package/interfaces/index.d.ts +11 -11
- package/interfaces/module-config.interface.d.ts +1 -1
- package/interfaces/notification-adapter.interface.d.ts +1 -1
- package/middlewares/index.d.ts +1 -1
- package/middlewares/logger.middleware.d.ts +2 -2
- package/modules/cache/cache.module.d.ts +1 -1
- package/modules/datasource/index.d.ts +1 -1
- package/modules/datasource/multi-tenant-datasource.service.d.ts +4 -4
- package/modules/event-bus/event-bus.explorer.d.ts +2 -2
- package/modules/event-bus/event-bus.module.d.ts +2 -2
- package/modules/event-bus/module-events.provider.d.ts +1 -1
- package/modules/index.d.ts +9 -9
- package/modules/shared-permission-cache/shared-permission-cache.service.d.ts +3 -3
- package/modules/utils/utils.service.d.ts +1 -1
- package/package.json +30 -44
- package/utils/index.d.ts +8 -8
- package/utils/permission-cache-key.util.d.ts +1 -1
- package/utils/query-helpers.util.d.ts +2 -2
- package/utils/request.util.d.ts +1 -1
- package/cjs/classes/api-controller.class.js +0 -728
- package/cjs/classes/api-controller.class.spec.js +0 -684
- package/cjs/classes/api-service.class.js +0 -631
- package/cjs/classes/api-service.class.spec.js +0 -1137
- package/cjs/classes/disabled-event-bus.class.js +0 -15
- package/cjs/classes/disabled-event-bus.class.spec.js +0 -40
- package/cjs/classes/domain-event.publisher.js +0 -76
- package/cjs/classes/domain-event.publisher.spec.js +0 -234
- package/cjs/classes/event-bus.registry.js +0 -68
- package/cjs/classes/event-bus.registry.spec.js +0 -141
- package/cjs/classes/event-transports/event-transport.registry.js +0 -41
- package/cjs/classes/event-transports/event-transport.registry.spec.js +0 -31
- package/cjs/classes/event-transports/index.js +0 -23
- package/cjs/classes/event-transports/kafka-transport.optional.js +0 -151
- package/cjs/classes/event-transports/kafka-transport.optional.spec.js +0 -198
- package/cjs/classes/event-transports/memory-transport.js +0 -53
- package/cjs/classes/event-transports/memory-transport.spec.js +0 -57
- package/cjs/classes/event-transports/rabbitmq-transport.optional.spec.js +0 -255
- package/cjs/classes/handle-custome-db.js +0 -37
- package/cjs/classes/handle-custome-db.spec.js +0 -82
- package/cjs/classes/hybrid-cache.class.js +0 -96
- package/cjs/classes/hybrid-cache.class.spec.js +0 -168
- package/cjs/classes/hybrid-event-bus.class.js +0 -281
- package/cjs/classes/hybrid-event-bus.class.spec.js +0 -218
- package/cjs/classes/index.js +0 -28
- package/cjs/classes/winston.logger.class.js +0 -274
- package/cjs/classes/winston.logger.class.spec.js +0 -330
- package/cjs/constants/index.js +0 -88
- package/cjs/constants/message-keys.js +0 -68
- package/cjs/constants/permissions.js +0 -307
- package/cjs/decorators/api-response.decorator.js +0 -52
- package/cjs/decorators/api-response.decorator.spec.js +0 -126
- package/cjs/decorators/current-user.decorator.js +0 -16
- package/cjs/decorators/current-user.decorator.spec.js +0 -74
- package/cjs/decorators/index.js +0 -23
- package/cjs/decorators/log-action.decorator.js +0 -149
- package/cjs/decorators/log-action.decorator.spec.js +0 -353
- package/cjs/decorators/on-domain-event.decorator.js +0 -13
- package/cjs/decorators/on-domain-event.decorator.spec.js +0 -50
- package/cjs/decorators/public.decorator.js +0 -13
- package/cjs/decorators/public.decorator.spec.js +0 -50
- package/cjs/decorators/require-permission.decorator.js +0 -32
- package/cjs/decorators/require-permission.decorator.spec.js +0 -147
- package/cjs/dtos/delete.dto.js +0 -92
- package/cjs/dtos/filter-and-pagination.dto.js +0 -164
- package/cjs/dtos/get-by-ids.dto.js +0 -65
- package/cjs/dtos/identity-response.dto.js +0 -108
- package/cjs/dtos/index.js +0 -23
- package/cjs/dtos/pagination.dto.js +0 -67
- package/cjs/dtos/response-payload.dto.js +0 -369
- package/cjs/entities/identity.js +0 -100
- package/cjs/entities/index.js +0 -20
- package/cjs/entities/raw-type.js +0 -4
- package/cjs/entities/user-root.js +0 -189
- package/cjs/enums/index.js +0 -20
- package/cjs/enums/notification-type.enum.js +0 -17
- package/cjs/enums/participant-status.enum.js +0 -17
- package/cjs/enums/recurrence-type.enum.js +0 -18
- package/cjs/exceptions/base-app.exception.js +0 -151
- package/cjs/exceptions/base-app.exception.spec.js +0 -157
- package/cjs/exceptions/index.js +0 -19
- package/cjs/exceptions/permission.exception.js +0 -56
- package/cjs/exceptions/permission.exception.spec.js +0 -82
- package/cjs/filters/global-exception.filter.js +0 -279
- package/cjs/filters/global-exception.filter.spec.js +0 -440
- package/cjs/filters/index.js +0 -18
- package/cjs/guards/index.js +0 -20
- package/cjs/guards/jwt-auth.guard.js +0 -75
- package/cjs/guards/jwt-auth.guard.spec.js +0 -75
- package/cjs/guards/optional-jwt-auth.guard.js +0 -67
- package/cjs/guards/optional-jwt-auth.guard.spec.js +0 -55
- package/cjs/guards/permission.guard.js +0 -179
- package/cjs/guards/permission.guard.spec.js +0 -373
- package/cjs/index.js +0 -31
- package/cjs/interceptors/delete-empty-id-from-body.interceptor.js +0 -40
- package/cjs/interceptors/delete-empty-id-from-body.interceptor.spec.js +0 -107
- package/cjs/interceptors/idempotency.interceptor.js +0 -96
- package/cjs/interceptors/idempotency.interceptor.spec.js +0 -116
- package/cjs/interceptors/index.js +0 -22
- package/cjs/interceptors/response-meta.interceptor.js +0 -47
- package/cjs/interceptors/response-meta.interceptor.spec.js +0 -89
- package/cjs/interceptors/set-user-field-on-body.interceptor.js +0 -60
- package/cjs/interceptors/set-user-field-on-body.interceptor.spec.js +0 -128
- package/cjs/interceptors/slug.interceptor.js +0 -75
- package/cjs/interceptors/slug.interceptor.spec.js +0 -110
- package/cjs/interfaces/ai-assistant-adapter.interface.js +0 -24
- package/cjs/interfaces/api.interface.js +0 -4
- package/cjs/interfaces/datasource.interface.js +0 -4
- package/cjs/interfaces/event-bus.interface.js +0 -4
- package/cjs/interfaces/event-manager-adapter.interface.js +0 -11
- package/cjs/interfaces/identity.interface.js +0 -4
- package/cjs/interfaces/index.js +0 -28
- package/cjs/interfaces/logged-user-info.interface.js +0 -6
- package/cjs/interfaces/module-config.interface.js +0 -4
- package/cjs/interfaces/notification-adapter.interface.js +0 -11
- package/cjs/interfaces/permission-sync-adapter.interface.js +0 -11
- package/cjs/interfaces/permission.interface.js +0 -4
- package/cjs/middlewares/index.js +0 -18
- package/cjs/middlewares/logger.middleware.js +0 -264
- package/cjs/middlewares/logger.middleware.spec.js +0 -462
- package/cjs/modules/cache/cache.module.js +0 -39
- package/cjs/modules/cache/cache.module.spec.js +0 -48
- package/cjs/modules/datasource/index.js +0 -18
- package/cjs/modules/datasource/multi-tenant-datasource.service.js +0 -222
- package/cjs/modules/datasource/multi-tenant-datasource.service.spec.js +0 -381
- package/cjs/modules/event-bus/event-bus.explorer.js +0 -124
- package/cjs/modules/event-bus/event-bus.explorer.spec.js +0 -189
- package/cjs/modules/event-bus/event-bus.integration.spec.js +0 -253
- package/cjs/modules/event-bus/event-bus.module.js +0 -94
- package/cjs/modules/event-bus/event-bus.module.spec.js +0 -149
- package/cjs/modules/event-bus/module-events.provider.js +0 -39
- package/cjs/modules/event-bus/module-events.provider.spec.js +0 -56
- package/cjs/modules/index.js +0 -26
- package/cjs/modules/shared-permission-cache/shared-permission-cache.module.js +0 -32
- package/cjs/modules/shared-permission-cache/shared-permission-cache.service.js +0 -101
- package/cjs/modules/shared-permission-cache/shared-permission-cache.service.spec.js +0 -165
- package/cjs/modules/utils/utils.module.js +0 -32
- package/cjs/modules/utils/utils.service.js +0 -76
- package/cjs/modules/utils/utils.service.spec.js +0 -169
- package/cjs/utils/date-time.util.js +0 -94
- package/cjs/utils/date-time.util.spec.js +0 -84
- package/cjs/utils/event-pattern.util.js +0 -103
- package/cjs/utils/event-pattern.util.spec.js +0 -251
- package/cjs/utils/html-sanitizer.util.js +0 -64
- package/cjs/utils/html-sanitizer.util.spec.js +0 -76
- package/cjs/utils/index.js +0 -25
- package/cjs/utils/optional-module.util.js +0 -35
- package/cjs/utils/optional-module.util.spec.js +0 -14
- package/cjs/utils/permission-cache-key.util.js +0 -31
- package/cjs/utils/permission-cache-key.util.spec.js +0 -88
- package/cjs/utils/query-helpers.util.js +0 -60
- package/cjs/utils/query-helpers.util.spec.js +0 -209
- package/cjs/utils/request.util.js +0 -96
- package/cjs/utils/request.util.spec.js +0 -249
- package/cjs/utils/string.util.js +0 -63
- package/cjs/utils/string.util.spec.js +0 -63
- package/fesm/classes/api-controller.class.js +0 -718
- package/fesm/classes/api-controller.class.spec.js +0 -680
- package/fesm/classes/api-service.class.js +0 -621
- package/fesm/classes/api-service.class.spec.js +0 -1133
- package/fesm/classes/disabled-event-bus.class.js +0 -11
- package/fesm/classes/disabled-event-bus.class.spec.js +0 -36
- package/fesm/classes/domain-event.publisher.js +0 -63
- package/fesm/classes/domain-event.publisher.spec.js +0 -230
- package/fesm/classes/event-bus.registry.js +0 -64
- package/fesm/classes/event-bus.registry.spec.js +0 -137
- package/fesm/classes/event-transports/event-transport.registry.js +0 -35
- package/fesm/classes/event-transports/event-transport.registry.spec.js +0 -27
- package/fesm/classes/event-transports/index.js +0 -6
- package/fesm/classes/event-transports/kafka-transport.optional.spec.js +0 -194
- package/fesm/classes/event-transports/memory-transport.js +0 -49
- package/fesm/classes/event-transports/memory-transport.spec.js +0 -53
- package/fesm/classes/event-transports/rabbitmq-transport.optional.js +0 -174
- package/fesm/classes/event-transports/rabbitmq-transport.optional.spec.js +0 -251
- package/fesm/classes/handle-custome-db.js +0 -19
- package/fesm/classes/handle-custome-db.spec.js +0 -78
- package/fesm/classes/hybrid-cache.class.js +0 -81
- package/fesm/classes/hybrid-cache.class.spec.js +0 -164
- package/fesm/classes/hybrid-event-bus.class.js +0 -237
- package/fesm/classes/hybrid-event-bus.class.spec.js +0 -214
- package/fesm/classes/winston.logger.class.js +0 -228
- package/fesm/classes/winston.logger.class.spec.js +0 -327
- package/fesm/constants/message-keys.js +0 -49
- package/fesm/constants/permissions.js +0 -215
- package/fesm/decorators/api-response.decorator.js +0 -42
- package/fesm/decorators/api-response.decorator.spec.js +0 -122
- package/fesm/decorators/current-user.decorator.js +0 -18
- package/fesm/decorators/current-user.decorator.spec.js +0 -73
- package/fesm/decorators/log-action.decorator.js +0 -139
- package/fesm/decorators/log-action.decorator.spec.js +0 -349
- package/fesm/decorators/on-domain-event.decorator.js +0 -10
- package/fesm/decorators/on-domain-event.decorator.spec.js +0 -46
- package/fesm/decorators/public.decorator.js +0 -20
- package/fesm/decorators/public.decorator.spec.js +0 -46
- package/fesm/decorators/require-permission.decorator.js +0 -27
- package/fesm/decorators/require-permission.decorator.spec.js +0 -143
- package/fesm/dtos/delete.dto.js +0 -82
- package/fesm/dtos/filter-and-pagination.dto.js +0 -148
- package/fesm/dtos/get-by-ids.dto.js +0 -55
- package/fesm/dtos/identity-response.dto.js +0 -98
- package/fesm/dtos/pagination.dto.js +0 -57
- package/fesm/dtos/response-payload.dto.js +0 -336
- package/fesm/entities/identity.js +0 -90
- package/fesm/entities/raw-type.js +0 -1
- package/fesm/entities/user-root.js +0 -179
- package/fesm/enums/notification-type.enum.js +0 -7
- package/fesm/enums/participant-status.enum.js +0 -7
- package/fesm/enums/recurrence-type.enum.js +0 -8
- package/fesm/exceptions/base-app.exception.js +0 -115
- package/fesm/exceptions/base-app.exception.spec.js +0 -153
- package/fesm/exceptions/permission.exception.js +0 -35
- package/fesm/exceptions/permission.exception.spec.js +0 -78
- package/fesm/filters/global-exception.filter.js +0 -269
- package/fesm/filters/global-exception.filter.spec.js +0 -436
- package/fesm/filters/index.js +0 -1
- package/fesm/guards/jwt-auth.guard.js +0 -65
- package/fesm/guards/jwt-auth.guard.spec.js +0 -71
- package/fesm/guards/optional-jwt-auth.guard.js +0 -57
- package/fesm/guards/optional-jwt-auth.guard.spec.js +0 -51
- package/fesm/guards/permission.guard.js +0 -169
- package/fesm/guards/permission.guard.spec.js +0 -369
- package/fesm/interceptors/delete-empty-id-from-body.interceptor.js +0 -30
- package/fesm/interceptors/delete-empty-id-from-body.interceptor.spec.js +0 -103
- package/fesm/interceptors/idempotency.interceptor.js +0 -86
- package/fesm/interceptors/idempotency.interceptor.spec.js +0 -112
- package/fesm/interceptors/response-meta.interceptor.js +0 -37
- package/fesm/interceptors/response-meta.interceptor.spec.js +0 -85
- package/fesm/interceptors/set-user-field-on-body.interceptor.js +0 -39
- package/fesm/interceptors/set-user-field-on-body.interceptor.spec.js +0 -124
- package/fesm/interceptors/slug.interceptor.js +0 -65
- package/fesm/interceptors/slug.interceptor.spec.js +0 -106
- package/fesm/interfaces/ai-assistant-adapter.interface.js +0 -3
- package/fesm/interfaces/api.interface.js +0 -1
- package/fesm/interfaces/datasource.interface.js +0 -1
- package/fesm/interfaces/event-bus.interface.js +0 -1
- package/fesm/interfaces/event-manager-adapter.interface.js +0 -1
- package/fesm/interfaces/identity.interface.js +0 -1
- package/fesm/interfaces/logged-user-info.interface.js +0 -3
- package/fesm/interfaces/module-config.interface.js +0 -5
- package/fesm/interfaces/notification-adapter.interface.js +0 -1
- package/fesm/interfaces/permission-sync-adapter.interface.js +0 -1
- package/fesm/interfaces/permission.interface.js +0 -1
- package/fesm/middlewares/logger.middleware.js +0 -235
- package/fesm/middlewares/logger.middleware.spec.js +0 -459
- package/fesm/modules/cache/cache.module.js +0 -29
- package/fesm/modules/cache/cache.module.spec.js +0 -44
- package/fesm/modules/datasource/index.js +0 -1
- package/fesm/modules/datasource/multi-tenant-datasource.service.js +0 -212
- package/fesm/modules/datasource/multi-tenant-datasource.service.spec.js +0 -377
- package/fesm/modules/event-bus/event-bus.explorer.js +0 -114
- package/fesm/modules/event-bus/event-bus.explorer.spec.js +0 -185
- package/fesm/modules/event-bus/event-bus.integration.spec.js +0 -249
- package/fesm/modules/event-bus/event-bus.module.js +0 -84
- package/fesm/modules/event-bus/event-bus.module.spec.js +0 -145
- package/fesm/modules/event-bus/module-events.provider.js +0 -26
- package/fesm/modules/event-bus/module-events.provider.spec.js +0 -52
- package/fesm/modules/shared-permission-cache/shared-permission-cache.module.js +0 -22
- package/fesm/modules/shared-permission-cache/shared-permission-cache.service.js +0 -91
- package/fesm/modules/shared-permission-cache/shared-permission-cache.service.spec.js +0 -161
- package/fesm/modules/utils/utils.module.js +0 -22
- package/fesm/modules/utils/utils.service.js +0 -66
- package/fesm/modules/utils/utils.service.spec.js +0 -165
- package/fesm/utils/date-time.util.js +0 -70
- package/fesm/utils/date-time.util.spec.js +0 -80
- package/fesm/utils/event-pattern.util.js +0 -91
- package/fesm/utils/event-pattern.util.spec.js +0 -247
- package/fesm/utils/html-sanitizer.util.js +0 -69
- package/fesm/utils/html-sanitizer.util.spec.js +0 -72
- package/fesm/utils/optional-module.util.js +0 -25
- package/fesm/utils/optional-module.util.spec.js +0 -10
- package/fesm/utils/permission-cache-key.util.js +0 -10
- package/fesm/utils/permission-cache-key.util.spec.js +0 -84
- package/fesm/utils/query-helpers.util.js +0 -85
- package/fesm/utils/query-helpers.util.spec.js +0 -205
- package/fesm/utils/request.util.js +0 -81
- package/fesm/utils/request.util.spec.js +0 -245
- package/fesm/utils/string.util.js +0 -71
- package/fesm/utils/string.util.spec.js +0 -59
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "UtilsService", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return UtilsService;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _common = require("@nestjs/common");
|
|
12
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
13
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
15
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
16
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
17
|
-
}
|
|
18
|
-
let UtilsService = class UtilsService {
|
|
19
|
-
// ---------------- CACHE HELPERS ----------------
|
|
20
|
-
/**
|
|
21
|
-
* Generate cache key with optional tenant prefix for multi-tenant isolation
|
|
22
|
-
*/ getCacheKey(entityName, params, entityId, tenantId) {
|
|
23
|
-
const prefix = this.buildTenantPrefix(tenantId);
|
|
24
|
-
if (entityId) {
|
|
25
|
-
return `${prefix}entity_${entityName}_id_${entityId}${params ? '_select_' + JSON.stringify(params) : ''}`;
|
|
26
|
-
}
|
|
27
|
-
return `${prefix}entity_${entityName}_all_${JSON.stringify(params)}`;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Track cache key for later invalidation with optional tenant prefix
|
|
31
|
-
*/ async trackCacheKey(cacheKey, entityName, cacheManager, entityId, tenantId) {
|
|
32
|
-
try {
|
|
33
|
-
const trackingKey = this.buildTrackingKey(entityName, entityId, tenantId);
|
|
34
|
-
const keys = await cacheManager.get(trackingKey) || [];
|
|
35
|
-
if (!keys.includes(cacheKey)) keys.push(cacheKey);
|
|
36
|
-
await cacheManager.set(trackingKey, keys);
|
|
37
|
-
} catch {
|
|
38
|
-
// Silent failure - cache tracking is non-critical
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Clear cache for entity with optional tenant prefix
|
|
43
|
-
*/ async clearCache(entityName, cacheManager, entityId, tenantId) {
|
|
44
|
-
try {
|
|
45
|
-
const trackingKey = this.buildTrackingKey(entityName, entityId, tenantId);
|
|
46
|
-
const keys = await cacheManager.get(trackingKey) || [];
|
|
47
|
-
await Promise.allSettled(keys.map((key)=>cacheManager.del(key)));
|
|
48
|
-
await cacheManager.del(trackingKey);
|
|
49
|
-
} catch {
|
|
50
|
-
// Silent failure - cache invalidation is non-critical
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// ---------------- STRING HELPERS ----------------
|
|
54
|
-
/**
|
|
55
|
-
* Transform string to URL-friendly slug
|
|
56
|
-
*/ transformToSlug(value, salt) {
|
|
57
|
-
const slug = value?.trim().replace(/[^A-Z0-9]+/gi, '-').toLowerCase();
|
|
58
|
-
return salt ? `${slug}-${this.getRandomInt(1, 100)}` : slug;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Generate random integer between min and max (inclusive)
|
|
62
|
-
*/ getRandomInt(min, max) {
|
|
63
|
-
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
64
|
-
}
|
|
65
|
-
// ---------------- PRIVATE HELPERS ----------------
|
|
66
|
-
buildTenantPrefix(tenantId) {
|
|
67
|
-
return tenantId ? `tenant_${tenantId}_` : '';
|
|
68
|
-
}
|
|
69
|
-
buildTrackingKey(entityName, entityId, tenantId) {
|
|
70
|
-
const prefix = this.buildTenantPrefix(tenantId);
|
|
71
|
-
return entityId ? `${prefix}entity_${entityName}_id_${entityId}_keys` : `${prefix}entity_${entityName}_keys`;
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
UtilsService = _ts_decorate([
|
|
75
|
-
(0, _common.Injectable)()
|
|
76
|
-
], UtilsService);
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
const _utilsservice = require("./utils.service");
|
|
6
|
-
describe('UtilsService', ()=>{
|
|
7
|
-
let service;
|
|
8
|
-
let mockCache;
|
|
9
|
-
beforeEach(()=>{
|
|
10
|
-
service = new _utilsservice.UtilsService();
|
|
11
|
-
mockCache = {
|
|
12
|
-
get: jest.fn(),
|
|
13
|
-
set: jest.fn(),
|
|
14
|
-
del: jest.fn()
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
describe('getCacheKey', ()=>{
|
|
18
|
-
it('should build an "all" key from the entity name and params when no id is given', ()=>{
|
|
19
|
-
const key = service.getCacheKey('product', {
|
|
20
|
-
page: 1
|
|
21
|
-
});
|
|
22
|
-
expect(key).toBe('entity_product_all_{"page":1}');
|
|
23
|
-
});
|
|
24
|
-
it('should build a per-id key with a select suffix when params are given', ()=>{
|
|
25
|
-
const key = service.getCacheKey('product', {
|
|
26
|
-
fields: [
|
|
27
|
-
'name'
|
|
28
|
-
]
|
|
29
|
-
}, 'prod-1');
|
|
30
|
-
expect(key).toBe('entity_product_id_prod-1_select_{"fields":["name"]}');
|
|
31
|
-
});
|
|
32
|
-
it('should build a per-id key without a select suffix when params are falsy', ()=>{
|
|
33
|
-
const key = service.getCacheKey('product', null, 'prod-1');
|
|
34
|
-
expect(key).toBe('entity_product_id_prod-1');
|
|
35
|
-
});
|
|
36
|
-
it('should prefix the key with the tenant id when provided', ()=>{
|
|
37
|
-
const key = service.getCacheKey('product', {
|
|
38
|
-
page: 1
|
|
39
|
-
}, undefined, 'tenant-a');
|
|
40
|
-
expect(key).toBe('tenant_tenant-a_entity_product_all_{"page":1}');
|
|
41
|
-
});
|
|
42
|
-
it('should prefix a per-id key with the tenant id too', ()=>{
|
|
43
|
-
const key = service.getCacheKey('product', undefined, 'prod-1', 'tenant-a');
|
|
44
|
-
expect(key).toBe('tenant_tenant-a_entity_product_id_prod-1');
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
describe('trackCacheKey', ()=>{
|
|
48
|
-
it('should create a new tracking list when none exists yet', async ()=>{
|
|
49
|
-
mockCache.get.mockResolvedValue(undefined);
|
|
50
|
-
await service.trackCacheKey('cache-key-1', 'product', mockCache);
|
|
51
|
-
expect(mockCache.set).toHaveBeenCalledWith('entity_product_keys', [
|
|
52
|
-
'cache-key-1'
|
|
53
|
-
]);
|
|
54
|
-
});
|
|
55
|
-
it('should append to an existing tracking list without duplicating entries', async ()=>{
|
|
56
|
-
mockCache.get.mockResolvedValue([
|
|
57
|
-
'cache-key-1'
|
|
58
|
-
]);
|
|
59
|
-
await service.trackCacheKey('cache-key-1', 'product', mockCache);
|
|
60
|
-
expect(mockCache.set).toHaveBeenCalledWith('entity_product_keys', [
|
|
61
|
-
'cache-key-1'
|
|
62
|
-
]);
|
|
63
|
-
});
|
|
64
|
-
it('should append a new key alongside existing ones', async ()=>{
|
|
65
|
-
mockCache.get.mockResolvedValue([
|
|
66
|
-
'cache-key-1'
|
|
67
|
-
]);
|
|
68
|
-
await service.trackCacheKey('cache-key-2', 'product', mockCache);
|
|
69
|
-
expect(mockCache.set).toHaveBeenCalledWith('entity_product_keys', [
|
|
70
|
-
'cache-key-1',
|
|
71
|
-
'cache-key-2'
|
|
72
|
-
]);
|
|
73
|
-
});
|
|
74
|
-
it('should scope the tracking key by entity id and tenant', async ()=>{
|
|
75
|
-
mockCache.get.mockResolvedValue(undefined);
|
|
76
|
-
await service.trackCacheKey('cache-key-1', 'product', mockCache, 'prod-1', 'tenant-a');
|
|
77
|
-
expect(mockCache.get).toHaveBeenCalledWith('tenant_tenant-a_entity_product_id_prod-1_keys');
|
|
78
|
-
expect(mockCache.set).toHaveBeenCalledWith('tenant_tenant-a_entity_product_id_prod-1_keys', [
|
|
79
|
-
'cache-key-1'
|
|
80
|
-
]);
|
|
81
|
-
});
|
|
82
|
-
it('should swallow cache read errors without throwing', async ()=>{
|
|
83
|
-
mockCache.get.mockRejectedValue(new Error('cache down'));
|
|
84
|
-
await expect(service.trackCacheKey('k', 'product', mockCache)).resolves.toBeUndefined();
|
|
85
|
-
expect(mockCache.set).not.toHaveBeenCalled();
|
|
86
|
-
});
|
|
87
|
-
it('should swallow cache write errors without throwing', async ()=>{
|
|
88
|
-
mockCache.get.mockResolvedValue([]);
|
|
89
|
-
mockCache.set.mockRejectedValue(new Error('cache down'));
|
|
90
|
-
await expect(service.trackCacheKey('k', 'product', mockCache)).resolves.toBeUndefined();
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
describe('clearCache', ()=>{
|
|
94
|
-
it('should delete every tracked key plus the tracking key itself', async ()=>{
|
|
95
|
-
mockCache.get.mockResolvedValue([
|
|
96
|
-
'k1',
|
|
97
|
-
'k2'
|
|
98
|
-
]);
|
|
99
|
-
await service.clearCache('product', mockCache);
|
|
100
|
-
expect(mockCache.del).toHaveBeenCalledWith('k1');
|
|
101
|
-
expect(mockCache.del).toHaveBeenCalledWith('k2');
|
|
102
|
-
expect(mockCache.del).toHaveBeenCalledWith('entity_product_keys');
|
|
103
|
-
expect(mockCache.del).toHaveBeenCalledTimes(3);
|
|
104
|
-
});
|
|
105
|
-
it('should only delete the tracking key when no keys were tracked', async ()=>{
|
|
106
|
-
mockCache.get.mockResolvedValue(undefined);
|
|
107
|
-
await service.clearCache('product', mockCache);
|
|
108
|
-
expect(mockCache.del).toHaveBeenCalledTimes(1);
|
|
109
|
-
expect(mockCache.del).toHaveBeenCalledWith('entity_product_keys');
|
|
110
|
-
});
|
|
111
|
-
it('should continue deleting remaining keys even if one deletion rejects', async ()=>{
|
|
112
|
-
mockCache.get.mockResolvedValue([
|
|
113
|
-
'k1',
|
|
114
|
-
'k2'
|
|
115
|
-
]);
|
|
116
|
-
mockCache.del.mockImplementation((key)=>key === 'k1' ? Promise.reject(new Error('fail')) : Promise.resolve());
|
|
117
|
-
await service.clearCache('product', mockCache);
|
|
118
|
-
expect(mockCache.del).toHaveBeenCalledWith('k2');
|
|
119
|
-
expect(mockCache.del).toHaveBeenCalledWith('entity_product_keys');
|
|
120
|
-
});
|
|
121
|
-
it('should scope deletion by entity id and tenant', async ()=>{
|
|
122
|
-
mockCache.get.mockResolvedValue([
|
|
123
|
-
'k1'
|
|
124
|
-
]);
|
|
125
|
-
await service.clearCache('product', mockCache, 'prod-1', 'tenant-a');
|
|
126
|
-
expect(mockCache.get).toHaveBeenCalledWith('tenant_tenant-a_entity_product_id_prod-1_keys');
|
|
127
|
-
});
|
|
128
|
-
it('should swallow errors from the initial cache read', async ()=>{
|
|
129
|
-
mockCache.get.mockRejectedValue(new Error('cache down'));
|
|
130
|
-
await expect(service.clearCache('product', mockCache)).resolves.toBeUndefined();
|
|
131
|
-
expect(mockCache.del).not.toHaveBeenCalled();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
describe('transformToSlug', ()=>{
|
|
135
|
-
it('should lowercase and dash-separate a normal string', ()=>{
|
|
136
|
-
expect(service.transformToSlug('Hello World')).toBe('hello-world');
|
|
137
|
-
});
|
|
138
|
-
it('should collapse runs of non-alphanumeric characters into a single dash', ()=>{
|
|
139
|
-
expect(service.transformToSlug('Hello World!!!')).toBe('hello-world-');
|
|
140
|
-
});
|
|
141
|
-
it('should trim leading/trailing whitespace before slugging', ()=>{
|
|
142
|
-
expect(service.transformToSlug(' Hello World ')).toBe('hello-world');
|
|
143
|
-
});
|
|
144
|
-
it('should append a random numeric salt when requested', ()=>{
|
|
145
|
-
const randomSpy = jest.spyOn(service, 'getRandomInt').mockReturnValue(42);
|
|
146
|
-
expect(service.transformToSlug('Hello World', true)).toBe('hello-world-42');
|
|
147
|
-
randomSpy.mockRestore();
|
|
148
|
-
});
|
|
149
|
-
it('should handle an empty string', ()=>{
|
|
150
|
-
expect(service.transformToSlug('')).toBe('');
|
|
151
|
-
});
|
|
152
|
-
it('should handle strings that are entirely non-alphanumeric', ()=>{
|
|
153
|
-
expect(service.transformToSlug('!!!')).toBe('-');
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
describe('getRandomInt', ()=>{
|
|
157
|
-
it('should return the exact bound when min equals max', ()=>{
|
|
158
|
-
expect(service.getRandomInt(5, 5)).toBe(5);
|
|
159
|
-
});
|
|
160
|
-
it('should stay within an inclusive [min, max] range across many samples', ()=>{
|
|
161
|
-
for(let i = 0; i < 200; i++){
|
|
162
|
-
const value = service.getRandomInt(1, 10);
|
|
163
|
-
expect(value).toBeGreaterThanOrEqual(1);
|
|
164
|
-
expect(value).toBeLessThanOrEqual(10);
|
|
165
|
-
expect(Number.isInteger(value)).toBe(true);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
});
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get formatInTimezone () {
|
|
13
|
-
return formatInTimezone;
|
|
14
|
-
},
|
|
15
|
-
get getTodayInTimezone () {
|
|
16
|
-
return getTodayInTimezone;
|
|
17
|
-
},
|
|
18
|
-
get localToUtc () {
|
|
19
|
-
return localToUtc;
|
|
20
|
-
},
|
|
21
|
-
get utcToLocal () {
|
|
22
|
-
return utcToLocal;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
function getOffsetMinutes(utcDate, timezone) {
|
|
26
|
-
const extract = (tz)=>{
|
|
27
|
-
const parts = new Intl.DateTimeFormat('en-US', {
|
|
28
|
-
timeZone: tz,
|
|
29
|
-
year: 'numeric',
|
|
30
|
-
month: '2-digit',
|
|
31
|
-
day: '2-digit',
|
|
32
|
-
hour: '2-digit',
|
|
33
|
-
minute: '2-digit',
|
|
34
|
-
second: '2-digit',
|
|
35
|
-
hour12: false
|
|
36
|
-
}).formatToParts(utcDate);
|
|
37
|
-
const p = Object.fromEntries(parts.filter((x)=>x.type !== 'literal').map((x)=>[
|
|
38
|
-
x.type,
|
|
39
|
-
parseInt(x.value)
|
|
40
|
-
]));
|
|
41
|
-
return Date.UTC(p['year'], p['month'] - 1, p['day'], p['hour'], p['minute'], p['second']);
|
|
42
|
-
};
|
|
43
|
-
return (extract(timezone) - extract('UTC')) / 60_000;
|
|
44
|
-
}
|
|
45
|
-
function localToUtc(dateStr, timeStr, timezone) {
|
|
46
|
-
const [year, month, day] = dateStr.split('-').map(Number);
|
|
47
|
-
const [hours, minutes] = timeStr.split(':').map(Number);
|
|
48
|
-
const approx = new Date(Date.UTC(year, month - 1, day, hours, minutes, 0));
|
|
49
|
-
const offset = getOffsetMinutes(approx, timezone);
|
|
50
|
-
const utcDate = new Date(approx.getTime() - offset * 60_000);
|
|
51
|
-
// DST boundary guard: re-check offset after adjustment
|
|
52
|
-
const finalOffset = getOffsetMinutes(utcDate, timezone);
|
|
53
|
-
return finalOffset !== offset ? new Date(approx.getTime() - finalOffset * 60_000) : utcDate;
|
|
54
|
-
}
|
|
55
|
-
function utcToLocal(utcDate, timezone) {
|
|
56
|
-
const d = typeof utcDate === 'string' ? new Date(utcDate) : utcDate;
|
|
57
|
-
const parts = new Intl.DateTimeFormat('en-CA', {
|
|
58
|
-
timeZone: timezone,
|
|
59
|
-
year: 'numeric',
|
|
60
|
-
month: '2-digit',
|
|
61
|
-
day: '2-digit',
|
|
62
|
-
hour: '2-digit',
|
|
63
|
-
minute: '2-digit',
|
|
64
|
-
hour12: false
|
|
65
|
-
}).formatToParts(d);
|
|
66
|
-
const p = Object.fromEntries(parts.filter((x)=>x.type !== 'literal').map((x)=>[
|
|
67
|
-
x.type,
|
|
68
|
-
x.value
|
|
69
|
-
]));
|
|
70
|
-
// en-CA formats midnight hour as '24' — normalize to '00'
|
|
71
|
-
const hour = p['hour'] === '24' ? '00' : p['hour'];
|
|
72
|
-
return {
|
|
73
|
-
date: `${p['year']}-${p['month']}-${p['day']}`,
|
|
74
|
-
time: `${hour}:${p['minute']}`,
|
|
75
|
-
display: new Intl.DateTimeFormat('en-US', {
|
|
76
|
-
timeZone: timezone,
|
|
77
|
-
dateStyle: 'medium',
|
|
78
|
-
timeStyle: 'short'
|
|
79
|
-
}).format(d)
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
function formatInTimezone(utcDate, timezone, options = {
|
|
83
|
-
dateStyle: 'medium',
|
|
84
|
-
timeStyle: 'short'
|
|
85
|
-
}) {
|
|
86
|
-
const d = typeof utcDate === 'string' ? new Date(utcDate) : utcDate;
|
|
87
|
-
return new Intl.DateTimeFormat('en-US', {
|
|
88
|
-
...options,
|
|
89
|
-
timeZone: timezone
|
|
90
|
-
}).format(d);
|
|
91
|
-
}
|
|
92
|
-
function getTodayInTimezone(timezone) {
|
|
93
|
-
return utcToLocal(new Date(), timezone).date;
|
|
94
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
const _datetimeutil = require("./date-time.util");
|
|
6
|
-
describe('date-time.util', ()=>{
|
|
7
|
-
describe('localToUtc', ()=>{
|
|
8
|
-
it('should convert a local date/time in a fixed-offset timezone to UTC', ()=>{
|
|
9
|
-
// Asia/Dhaka is UTC+6, no DST
|
|
10
|
-
const result = (0, _datetimeutil.localToUtc)('2026-01-15', '10:00', 'Asia/Dhaka');
|
|
11
|
-
expect(result.toISOString()).toBe('2026-01-15T04:00:00.000Z');
|
|
12
|
-
});
|
|
13
|
-
it('should convert local time in UTC timezone unchanged', ()=>{
|
|
14
|
-
const result = (0, _datetimeutil.localToUtc)('2026-06-01', '12:30', 'UTC');
|
|
15
|
-
expect(result.toISOString()).toBe('2026-06-01T12:30:00.000Z');
|
|
16
|
-
});
|
|
17
|
-
it('should handle a negative UTC offset timezone (America/New_York in winter, no DST)', ()=>{
|
|
18
|
-
// America/New_York is UTC-5 in January (standard time, no DST)
|
|
19
|
-
const result = (0, _datetimeutil.localToUtc)('2026-01-15', '09:00', 'America/New_York');
|
|
20
|
-
expect(result.toISOString()).toBe('2026-01-15T14:00:00.000Z');
|
|
21
|
-
});
|
|
22
|
-
it('should account for DST when converting a summer date in America/New_York (UTC-4)', ()=>{
|
|
23
|
-
const result = (0, _datetimeutil.localToUtc)('2026-07-15', '09:00', 'America/New_York');
|
|
24
|
-
expect(result.toISOString()).toBe('2026-07-15T13:00:00.000Z');
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
describe('utcToLocal', ()=>{
|
|
28
|
-
it('should convert a UTC Date to local date/time/display parts', ()=>{
|
|
29
|
-
const result = (0, _datetimeutil.utcToLocal)(new Date('2026-01-15T04:00:00.000Z'), 'Asia/Dhaka');
|
|
30
|
-
expect(result.date).toBe('2026-01-15');
|
|
31
|
-
expect(result.time).toBe('10:00');
|
|
32
|
-
expect(result.display).toEqual(expect.any(String));
|
|
33
|
-
});
|
|
34
|
-
it('should accept a UTC date string as input', ()=>{
|
|
35
|
-
const result = (0, _datetimeutil.utcToLocal)('2026-01-15T04:00:00.000Z', 'Asia/Dhaka');
|
|
36
|
-
expect(result.date).toBe('2026-01-15');
|
|
37
|
-
expect(result.time).toBe('10:00');
|
|
38
|
-
});
|
|
39
|
-
it('should normalize midnight (en-CA "24") to "00"', ()=>{
|
|
40
|
-
// 00:00 Dhaka time == 18:00 UTC the previous day
|
|
41
|
-
const result = (0, _datetimeutil.utcToLocal)('2026-01-14T18:00:00.000Z', 'Asia/Dhaka');
|
|
42
|
-
expect(result.date).toBe('2026-01-15');
|
|
43
|
-
expect(result.time).toBe('00:00');
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe('formatInTimezone', ()=>{
|
|
47
|
-
it('should format a date in the given timezone with default options', ()=>{
|
|
48
|
-
const result = (0, _datetimeutil.formatInTimezone)('2026-01-15T04:00:00.000Z', 'Asia/Dhaka');
|
|
49
|
-
expect(typeof result).toBe('string');
|
|
50
|
-
expect(result.length).toBeGreaterThan(0);
|
|
51
|
-
});
|
|
52
|
-
it('should respect custom Intl.DateTimeFormatOptions', ()=>{
|
|
53
|
-
const result = (0, _datetimeutil.formatInTimezone)('2026-01-15T04:00:00.000Z', 'UTC', {
|
|
54
|
-
year: 'numeric'
|
|
55
|
-
});
|
|
56
|
-
expect(result).toBe('2026');
|
|
57
|
-
});
|
|
58
|
-
it('should accept a Date object as input', ()=>{
|
|
59
|
-
const result = (0, _datetimeutil.formatInTimezone)(new Date('2026-01-15T04:00:00.000Z'), 'UTC', {
|
|
60
|
-
year: 'numeric'
|
|
61
|
-
});
|
|
62
|
-
expect(result).toBe('2026');
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
describe('getTodayInTimezone', ()=>{
|
|
66
|
-
it('should return a date string in YYYY-MM-DD format', ()=>{
|
|
67
|
-
const result = (0, _datetimeutil.getTodayInTimezone)('UTC');
|
|
68
|
-
expect(result).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
69
|
-
});
|
|
70
|
-
it('should match utcToLocal(now, timezone).date', ()=>{
|
|
71
|
-
const now = new Date();
|
|
72
|
-
const expected = (0, _datetimeutil.utcToLocal)(now, 'Asia/Dhaka').date;
|
|
73
|
-
expect((0, _datetimeutil.getTodayInTimezone)('Asia/Dhaka')).toBe(expected);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
describe('round-trip', ()=>{
|
|
77
|
-
it('should round-trip localToUtc -> utcToLocal for a fixed-offset zone', ()=>{
|
|
78
|
-
const utc = (0, _datetimeutil.localToUtc)('2026-03-10', '08:15', 'Asia/Dhaka');
|
|
79
|
-
const back = (0, _datetimeutil.utcToLocal)(utc, 'Asia/Dhaka');
|
|
80
|
-
expect(back.date).toBe('2026-03-10');
|
|
81
|
-
expect(back.time).toBe('08:15');
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get isMultiWildcard () {
|
|
13
|
-
return isMultiWildcard;
|
|
14
|
-
},
|
|
15
|
-
get matchEventPattern () {
|
|
16
|
-
return matchEventPattern;
|
|
17
|
-
},
|
|
18
|
-
get sanitizeEventPayload () {
|
|
19
|
-
return sanitizeEventPayload;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
const SENSITIVE_KEYS = [
|
|
23
|
-
'password',
|
|
24
|
-
'secret',
|
|
25
|
-
'token',
|
|
26
|
-
'apikey',
|
|
27
|
-
'authorization',
|
|
28
|
-
'salt',
|
|
29
|
-
'hash',
|
|
30
|
-
'credential',
|
|
31
|
-
'accesskey',
|
|
32
|
-
'accountkey',
|
|
33
|
-
'privatekey',
|
|
34
|
-
'connectionstring',
|
|
35
|
-
'passphrase'
|
|
36
|
-
];
|
|
37
|
-
/**
|
|
38
|
-
* Matched whole, not as a substring - `pass` must be redacted without also
|
|
39
|
-
* redacting `bypassCache`, and a storage row's `key` is a path, not a secret.
|
|
40
|
-
*
|
|
41
|
-
* `config` is the provider settings blob on the storage and email config rows:
|
|
42
|
-
* S3, Azure, SFTP and SMTP credentials live in it, so it never leaves the
|
|
43
|
-
* process, even though the row itself still publishes.
|
|
44
|
-
*/ const SENSITIVE_EXACT_KEYS = [
|
|
45
|
-
'pass',
|
|
46
|
-
'pwd',
|
|
47
|
-
'config'
|
|
48
|
-
];
|
|
49
|
-
const REDACTED = '[REDACTED]';
|
|
50
|
-
const CIRCULAR = '[CIRCULAR]';
|
|
51
|
-
const TRUNCATED = '[TRUNCATED]';
|
|
52
|
-
const BINARY = '[BINARY]';
|
|
53
|
-
const MAX_DEPTH = 8;
|
|
54
|
-
function matchEventPattern(pattern, eventName) {
|
|
55
|
-
if (pattern === eventName) return true;
|
|
56
|
-
const patternSegments = pattern.split('.');
|
|
57
|
-
const nameSegments = eventName.split('.');
|
|
58
|
-
return matchSegments(patternSegments, 0, nameSegments, 0);
|
|
59
|
-
}
|
|
60
|
-
function isMultiWildcard(segment) {
|
|
61
|
-
return segment === '#' || segment === '**';
|
|
62
|
-
}
|
|
63
|
-
function matchSegments(pattern, patternIndex, name, nameIndex) {
|
|
64
|
-
if (patternIndex === pattern.length) return nameIndex === name.length;
|
|
65
|
-
const segment = pattern[patternIndex];
|
|
66
|
-
if (isMultiWildcard(segment)) {
|
|
67
|
-
for(let skip = nameIndex; skip <= name.length; skip++){
|
|
68
|
-
if (matchSegments(pattern, patternIndex + 1, name, skip)) return true;
|
|
69
|
-
}
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
if (nameIndex === name.length) return false;
|
|
73
|
-
if (segment !== '*' && segment !== name[nameIndex]) return false;
|
|
74
|
-
return matchSegments(pattern, patternIndex + 1, name, nameIndex + 1);
|
|
75
|
-
}
|
|
76
|
-
function sanitizeEventPayload(value) {
|
|
77
|
-
return sanitizeValue(value, new WeakSet(), 0);
|
|
78
|
-
}
|
|
79
|
-
function sanitizeValue(value, ancestors, depth) {
|
|
80
|
-
if (value === null || typeof value !== 'object') return value;
|
|
81
|
-
if (value instanceof Date) return value;
|
|
82
|
-
if (Buffer.isBuffer(value)) return BINARY;
|
|
83
|
-
if (ancestors.has(value)) return CIRCULAR;
|
|
84
|
-
if (depth >= MAX_DEPTH) return TRUNCATED;
|
|
85
|
-
ancestors.add(value);
|
|
86
|
-
try {
|
|
87
|
-
if (Array.isArray(value)) {
|
|
88
|
-
return value.map((item)=>sanitizeValue(item, ancestors, depth + 1));
|
|
89
|
-
}
|
|
90
|
-
const sanitized = {};
|
|
91
|
-
for (const [key, entry] of Object.entries(value)){
|
|
92
|
-
sanitized[key] = isSensitiveKey(key) ? REDACTED : sanitizeValue(entry, ancestors, depth + 1);
|
|
93
|
-
}
|
|
94
|
-
return sanitized;
|
|
95
|
-
} finally{
|
|
96
|
-
ancestors.delete(value);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function isSensitiveKey(key) {
|
|
100
|
-
const lowered = key.toLowerCase();
|
|
101
|
-
if (SENSITIVE_EXACT_KEYS.includes(lowered)) return true;
|
|
102
|
-
return SENSITIVE_KEYS.some((sensitive)=>lowered.includes(sensitive));
|
|
103
|
-
}
|