rl-core-api 0.7.0 → 0.8.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.
Files changed (59) hide show
  1. package/README.md +54 -0
  2. package/dist/core/config/env.schema.d.ts +3 -0
  3. package/dist/core/config/env.schema.js +3 -0
  4. package/dist/core/core.module.js +3 -1
  5. package/dist/core/events/appEvent.enum.d.ts +6 -0
  6. package/dist/core/events/appEvent.enum.js +1 -0
  7. package/dist/core/health/health.controller.d.ts +4 -1
  8. package/dist/core/health/health.controller.js +9 -3
  9. package/dist/core/queue/bullConnection.module.d.ts +2 -0
  10. package/dist/core/queue/bullConnection.module.js +27 -0
  11. package/dist/core/queue/job.interface.d.ts +70 -0
  12. package/dist/core/queue/job.interface.js +2 -0
  13. package/dist/core/queue/job.producer.d.ts +15 -0
  14. package/dist/core/queue/job.producer.js +124 -0
  15. package/dist/core/queue/jobEvents.interface.d.ts +4 -0
  16. package/dist/core/queue/jobEvents.interface.js +4 -0
  17. package/dist/core/queue/jobEvents.service.d.ts +12 -0
  18. package/dist/core/queue/jobEvents.service.js +53 -0
  19. package/dist/core/queue/jobStatus.controller.d.ts +8 -0
  20. package/dist/core/queue/jobStatus.controller.js +44 -0
  21. package/dist/core/queue/jobStatus.response.d.ts +20 -0
  22. package/dist/core/queue/jobStatus.response.js +84 -0
  23. package/dist/core/queue/jobWorkerHost.d.ts +17 -0
  24. package/dist/core/queue/jobWorkerHost.js +72 -0
  25. package/dist/core/queue/queue.constants.d.ts +11 -0
  26. package/dist/core/queue/queue.constants.js +18 -0
  27. package/dist/core/queue/queue.module.d.ts +2 -0
  28. package/dist/core/queue/queue.module.js +38 -0
  29. package/dist/core/queue/queueAdmin.controller.d.ts +11 -0
  30. package/dist/core/queue/queueAdmin.controller.js +93 -0
  31. package/dist/core/queue/queueAdmin.response.d.ts +23 -0
  32. package/dist/core/queue/queueAdmin.response.js +87 -0
  33. package/dist/core/queue/queueAdmin.service.d.ts +15 -0
  34. package/dist/core/queue/queueAdmin.service.js +85 -0
  35. package/dist/core/queue/redisConnection.d.ts +2 -0
  36. package/dist/core/queue/redisConnection.js +11 -0
  37. package/dist/core/websocket/baseGateway.d.ts +1 -0
  38. package/dist/core/websocket/baseGateway.js +3 -0
  39. package/dist/features/audit/audit.module.js +1 -0
  40. package/dist/features/audit/presentation/index.d.ts +1 -0
  41. package/dist/features/audit/presentation/index.js +1 -0
  42. package/dist/features/audit/presentation/userPermissionsChanged.listener.d.ts +7 -0
  43. package/dist/features/audit/presentation/userPermissionsChanged.listener.js +43 -0
  44. package/dist/features/notifications/notifications.module.js +1 -1
  45. package/dist/features/notifications/presentation/domainEvents.listener.d.ts +2 -1
  46. package/dist/features/notifications/presentation/domainEvents.listener.js +19 -0
  47. package/dist/features/rbac/domain/rbac.catalog.js +15 -0
  48. package/dist/features/rbac/domain/rbac.service.d.ts +11 -1
  49. package/dist/features/rbac/domain/rbac.service.js +72 -2
  50. package/dist/features/rbac/presentation/commands/setUserPermissions.command.d.ts +3 -0
  51. package/dist/features/rbac/presentation/commands/setUserPermissions.command.js +24 -0
  52. package/dist/features/rbac/presentation/index.d.ts +1 -0
  53. package/dist/features/rbac/presentation/index.js +1 -0
  54. package/dist/features/rbac/presentation/rbac.controller.d.ts +5 -0
  55. package/dist/features/rbac/presentation/rbac.controller.js +57 -0
  56. package/dist/index.d.ts +11 -1
  57. package/dist/index.js +33 -2
  58. package/dist/rlCore.module.js +8 -0
  59. package/package.json +4 -1
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.JobStatusResponse = exports.JobErrorResponse = exports.JobProgressResponse = void 0;
13
+ const swagger_1 = require("@nestjs/swagger");
14
+ class JobProgressResponse {
15
+ }
16
+ exports.JobProgressResponse = JobProgressResponse;
17
+ __decorate([
18
+ (0, swagger_1.ApiProperty)({ example: 120 }),
19
+ __metadata("design:type", Number)
20
+ ], JobProgressResponse.prototype, "processed", void 0);
21
+ __decorate([
22
+ (0, swagger_1.ApiProperty)({ example: 175 }),
23
+ __metadata("design:type", Number)
24
+ ], JobProgressResponse.prototype, "total", void 0);
25
+ __decorate([
26
+ (0, swagger_1.ApiProperty)({ example: 69, description: "Inteiro de 0 a 100" }),
27
+ __metadata("design:type", Number)
28
+ ], JobProgressResponse.prototype, "percent", void 0);
29
+ __decorate([
30
+ (0, swagger_1.ApiProperty)({ required: false, example: "Lendo a planilha" }),
31
+ __metadata("design:type", String)
32
+ ], JobProgressResponse.prototype, "message", void 0);
33
+ class JobErrorResponse {
34
+ }
35
+ exports.JobErrorResponse = JobErrorResponse;
36
+ __decorate([
37
+ (0, swagger_1.ApiProperty)({ type: String, nullable: true, example: "INVALID_FILTER" }),
38
+ __metadata("design:type", Object)
39
+ ], JobErrorResponse.prototype, "code", void 0);
40
+ __decorate([
41
+ (0, swagger_1.ApiProperty)({ example: "Falha ao processar. Tente novamente" }),
42
+ __metadata("design:type", String)
43
+ ], JobErrorResponse.prototype, "message", void 0);
44
+ class JobStatusResponse {
45
+ }
46
+ exports.JobStatusResponse = JobStatusResponse;
47
+ __decorate([
48
+ (0, swagger_1.ApiProperty)({ example: "42" }),
49
+ __metadata("design:type", String)
50
+ ], JobStatusResponse.prototype, "id", void 0);
51
+ __decorate([
52
+ (0, swagger_1.ApiProperty)({ example: "funkos:import" }),
53
+ __metadata("design:type", String)
54
+ ], JobStatusResponse.prototype, "name", void 0);
55
+ __decorate([
56
+ (0, swagger_1.ApiProperty)({
57
+ example: "active",
58
+ enum: ["waiting", "active", "completed", "failed", "delayed", "unknown"],
59
+ }),
60
+ __metadata("design:type", String)
61
+ ], JobStatusResponse.prototype, "state", void 0);
62
+ __decorate([
63
+ (0, swagger_1.ApiProperty)({ type: JobProgressResponse, nullable: true }),
64
+ __metadata("design:type", Object)
65
+ ], JobStatusResponse.prototype, "progress", void 0);
66
+ __decorate([
67
+ (0, swagger_1.ApiProperty)({
68
+ nullable: true,
69
+ description: "Relatório que o processador devolveu, no formato da feature",
70
+ }),
71
+ __metadata("design:type", Object)
72
+ ], JobStatusResponse.prototype, "summary", void 0);
73
+ __decorate([
74
+ (0, swagger_1.ApiProperty)({ type: JobErrorResponse, nullable: true }),
75
+ __metadata("design:type", Object)
76
+ ], JobStatusResponse.prototype, "error", void 0);
77
+ __decorate([
78
+ (0, swagger_1.ApiProperty)({ format: "date-time" }),
79
+ __metadata("design:type", String)
80
+ ], JobStatusResponse.prototype, "createdAt", void 0);
81
+ __decorate([
82
+ (0, swagger_1.ApiProperty)({ type: String, format: "date-time", nullable: true }),
83
+ __metadata("design:type", Object)
84
+ ], JobStatusResponse.prototype, "finishedAt", void 0);
@@ -0,0 +1,17 @@
1
+ import { WorkerHost } from "@nestjs/bullmq";
2
+ import { Logger, OnApplicationBootstrap } from "@nestjs/common";
3
+ import { Job } from "bullmq";
4
+ import { JobContext, JobEnvelope } from "./job.interface";
5
+ import { JobEventsService } from "./jobEvents.service";
6
+ export declare abstract class JobWorkerHost<TPayload = unknown, TSummary = unknown> extends WorkerHost implements OnApplicationBootstrap {
7
+ protected readonly jobEvents: JobEventsService;
8
+ protected readonly logger: Logger;
9
+ constructor(jobEvents: JobEventsService);
10
+ onApplicationBootstrap(): void;
11
+ abstract handle(job: JobContext<TPayload>): Promise<TSummary>;
12
+ process(job: Job<JobEnvelope<TPayload>>): Promise<TSummary>;
13
+ }
14
+ export declare const toSafeError: (err: Error) => {
15
+ errorCode: string | null;
16
+ message: string;
17
+ };
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toSafeError = exports.JobWorkerHost = void 0;
4
+ const bullmq_1 = require("@nestjs/bullmq");
5
+ const common_1 = require("@nestjs/common");
6
+ class JobWorkerHost extends bullmq_1.WorkerHost {
7
+ constructor(jobEvents) {
8
+ super();
9
+ this.jobEvents = jobEvents;
10
+ this.logger = new common_1.Logger(this.constructor.name);
11
+ }
12
+ onApplicationBootstrap() {
13
+ if (!this.worker.isRunning()) {
14
+ void this.worker.run();
15
+ }
16
+ }
17
+ async process(job) {
18
+ const jobId = String(job.id);
19
+ const { ownerId, payload } = job.data;
20
+ try {
21
+ const summary = await this.handle({
22
+ jobId,
23
+ ownerId,
24
+ payload,
25
+ report: async (processed, total, message) => {
26
+ const percent = total > 0 ? Math.min(100, Math.round((processed / total) * 100)) : 0;
27
+ await job.updateProgress({ processed, total, percent, message });
28
+ this.jobEvents.progress(ownerId, {
29
+ jobId,
30
+ name: job.name,
31
+ processed,
32
+ total,
33
+ percent,
34
+ message,
35
+ });
36
+ },
37
+ });
38
+ this.jobEvents.completed(ownerId, {
39
+ jobId,
40
+ name: job.name,
41
+ summary,
42
+ });
43
+ return summary;
44
+ }
45
+ catch (err) {
46
+ this.logger.error(`Job ${job.name} #${jobId} falhou: ${err.message}`, err.stack);
47
+ if (job.attemptsMade + 1 >= (job.opts.attempts ?? 1)) {
48
+ this.jobEvents.failed(ownerId, {
49
+ jobId,
50
+ name: job.name,
51
+ ...(0, exports.toSafeError)(err),
52
+ });
53
+ }
54
+ throw err;
55
+ }
56
+ }
57
+ }
58
+ exports.JobWorkerHost = JobWorkerHost;
59
+ const toSafeError = (err) => {
60
+ if (err instanceof common_1.HttpException) {
61
+ const response = err.getResponse();
62
+ const code = typeof response === "object" && response !== null
63
+ ? (response.errorCode ?? null)
64
+ : null;
65
+ return { errorCode: code, message: err.message };
66
+ }
67
+ return {
68
+ errorCode: null,
69
+ message: "Falha ao processar. Tente novamente ou avise o suporte",
70
+ };
71
+ };
72
+ exports.toSafeError = toSafeError;
@@ -0,0 +1,11 @@
1
+ export declare const JOBS_QUEUE = "jobs";
2
+ export declare const JOB_PROGRESS_EVENT = "job:progress";
3
+ export declare const JOB_COMPLETED_EVENT = "job:completed";
4
+ export declare const JOB_FAILED_EVENT = "job:failed";
5
+ export declare const JOB_CONCURRENCY = 5;
6
+ export declare const JOB_ATTEMPTS = 3;
7
+ export declare const JOB_BACKOFF_DELAY_MS = 30000;
8
+ export declare const COMPLETED_RETENTION_SECONDS = 86400;
9
+ export declare const FAILED_RETENTION_SECONDS = 14400;
10
+ export declare const isRedisConfigured: () => boolean;
11
+ export declare const queuePrefix: () => string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queuePrefix = exports.isRedisConfigured = exports.FAILED_RETENTION_SECONDS = exports.COMPLETED_RETENTION_SECONDS = exports.JOB_BACKOFF_DELAY_MS = exports.JOB_ATTEMPTS = exports.JOB_CONCURRENCY = exports.JOB_FAILED_EVENT = exports.JOB_COMPLETED_EVENT = exports.JOB_PROGRESS_EVENT = exports.JOBS_QUEUE = void 0;
4
+ const dotenv_1 = require("dotenv");
5
+ (0, dotenv_1.config)();
6
+ exports.JOBS_QUEUE = "jobs";
7
+ exports.JOB_PROGRESS_EVENT = "job:progress";
8
+ exports.JOB_COMPLETED_EVENT = "job:completed";
9
+ exports.JOB_FAILED_EVENT = "job:failed";
10
+ exports.JOB_CONCURRENCY = 5;
11
+ exports.JOB_ATTEMPTS = 3;
12
+ exports.JOB_BACKOFF_DELAY_MS = 30_000;
13
+ exports.COMPLETED_RETENTION_SECONDS = 86_400;
14
+ exports.FAILED_RETENTION_SECONDS = 14_400;
15
+ const isRedisConfigured = () => Boolean(process.env.REDIS_HOST);
16
+ exports.isRedisConfigured = isRedisConfigured;
17
+ const queuePrefix = () => process.env.REDIS_PREFIX ?? "core";
18
+ exports.queuePrefix = queuePrefix;
@@ -0,0 +1,2 @@
1
+ export declare class QueueModule {
2
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.QueueModule = void 0;
10
+ const bullmq_1 = require("@nestjs/bullmq");
11
+ const common_1 = require("@nestjs/common");
12
+ const bullConnection_module_1 = require("./bullConnection.module");
13
+ const job_producer_1 = require("./job.producer");
14
+ const jobEvents_service_1 = require("./jobEvents.service");
15
+ const jobStatus_controller_1 = require("./jobStatus.controller");
16
+ const queue_constants_1 = require("./queue.constants");
17
+ const queueAdmin_controller_1 = require("./queueAdmin.controller");
18
+ const queueAdmin_service_1 = require("./queueAdmin.service");
19
+ const logger = new common_1.Logger("QueueModule");
20
+ const buildImports = () => {
21
+ if (!(0, queue_constants_1.isRedisConfigured)()) {
22
+ logger.warn("REDIS_HOST não configurado — a fila não será registrada e o enfileiramento fica indisponível");
23
+ return [];
24
+ }
25
+ return [bullConnection_module_1.BullConnectionModule, bullmq_1.BullModule.registerQueue({ name: queue_constants_1.JOBS_QUEUE })];
26
+ };
27
+ let QueueModule = class QueueModule {
28
+ };
29
+ exports.QueueModule = QueueModule;
30
+ exports.QueueModule = QueueModule = __decorate([
31
+ (0, common_1.Global)(),
32
+ (0, common_1.Module)({
33
+ imports: buildImports(),
34
+ controllers: [jobStatus_controller_1.JobStatusController, queueAdmin_controller_1.QueueAdminController],
35
+ providers: [job_producer_1.JobProducer, jobEvents_service_1.JobEventsService, queueAdmin_service_1.QueueAdminService],
36
+ exports: [job_producer_1.JobProducer, jobEvents_service_1.JobEventsService],
37
+ })
38
+ ], QueueModule);
@@ -0,0 +1,11 @@
1
+ import { QueueCounts, QueueJobSummary } from "./job.interface";
2
+ import { QueueAdminService } from "./queueAdmin.service";
3
+ import { Paginated } from "../utils/pagination.util";
4
+ export declare class QueueAdminController {
5
+ private readonly queues;
6
+ constructor(queues: QueueAdminService);
7
+ counts(): Promise<QueueCounts>;
8
+ jobs(state: string, page?: string, limit?: string): Promise<Paginated<QueueJobSummary>>;
9
+ retry(id: string): Promise<void>;
10
+ remove(id: string): Promise<void>;
11
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.QueueAdminController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const swagger_1 = require("@nestjs/swagger");
18
+ const requirePermission_decorator_1 = require("../auth/decorators/requirePermission.decorator");
19
+ const permissions_guard_1 = require("../auth/guards/permissions.guard");
20
+ const queueAdmin_response_1 = require("./queueAdmin.response");
21
+ const queueAdmin_service_1 = require("./queueAdmin.service");
22
+ const DEFAULT_LIMIT = 20;
23
+ const MAX_LIMIT = 100;
24
+ let QueueAdminController = class QueueAdminController {
25
+ constructor(queues) {
26
+ this.queues = queues;
27
+ }
28
+ counts() {
29
+ return this.queues.counts();
30
+ }
31
+ jobs(state, page, limit) {
32
+ return this.queues.list(toState(state), toPositive(page, 1), Math.min(toPositive(limit, DEFAULT_LIMIT), MAX_LIMIT));
33
+ }
34
+ retry(id) {
35
+ return this.queues.retry(id);
36
+ }
37
+ remove(id) {
38
+ return this.queues.remove(id);
39
+ }
40
+ };
41
+ exports.QueueAdminController = QueueAdminController;
42
+ __decorate([
43
+ (0, common_1.Get)("counts"),
44
+ (0, requirePermission_decorator_1.RequirePermission)("queues:read:any"),
45
+ (0, swagger_1.ApiOkResponse)({ type: queueAdmin_response_1.QueueCountsResponse }),
46
+ __metadata("design:type", Function),
47
+ __metadata("design:paramtypes", []),
48
+ __metadata("design:returntype", Promise)
49
+ ], QueueAdminController.prototype, "counts", null);
50
+ __decorate([
51
+ (0, common_1.Get)("jobs"),
52
+ (0, requirePermission_decorator_1.RequirePermission)("queues:read:any"),
53
+ (0, swagger_1.ApiQuery)({ name: "state", enum: queueAdmin_service_1.LISTABLE_STATES }),
54
+ (0, swagger_1.ApiOkResponse)({ type: queueAdmin_response_1.PaginatedQueueJobsResponse }),
55
+ __param(0, (0, common_1.Query)("state")),
56
+ __param(1, (0, common_1.Query)("page")),
57
+ __param(2, (0, common_1.Query)("limit")),
58
+ __metadata("design:type", Function),
59
+ __metadata("design:paramtypes", [String, String, String]),
60
+ __metadata("design:returntype", Promise)
61
+ ], QueueAdminController.prototype, "jobs", null);
62
+ __decorate([
63
+ (0, common_1.Post)("jobs/:id/retry"),
64
+ (0, common_1.HttpCode)(204),
65
+ (0, requirePermission_decorator_1.RequirePermission)("queues:manage:any"),
66
+ __param(0, (0, common_1.Param)("id")),
67
+ __metadata("design:type", Function),
68
+ __metadata("design:paramtypes", [String]),
69
+ __metadata("design:returntype", Promise)
70
+ ], QueueAdminController.prototype, "retry", null);
71
+ __decorate([
72
+ (0, common_1.Delete)("jobs/:id"),
73
+ (0, common_1.HttpCode)(204),
74
+ (0, requirePermission_decorator_1.RequirePermission)("queues:manage:any"),
75
+ __param(0, (0, common_1.Param)("id")),
76
+ __metadata("design:type", Function),
77
+ __metadata("design:paramtypes", [String]),
78
+ __metadata("design:returntype", Promise)
79
+ ], QueueAdminController.prototype, "remove", null);
80
+ exports.QueueAdminController = QueueAdminController = __decorate([
81
+ (0, swagger_1.ApiTags)("Queues"),
82
+ (0, swagger_1.ApiBearerAuth)(),
83
+ (0, common_1.UseGuards)(permissions_guard_1.PermissionsGuard),
84
+ (0, common_1.Controller)({ path: "queues", version: "1" }),
85
+ __metadata("design:paramtypes", [queueAdmin_service_1.QueueAdminService])
86
+ ], QueueAdminController);
87
+ const toState = (value) => queueAdmin_service_1.LISTABLE_STATES.includes(value)
88
+ ? value
89
+ : "failed";
90
+ const toPositive = (value, fallback) => {
91
+ const parsed = Number(value);
92
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
93
+ };
@@ -0,0 +1,23 @@
1
+ import { PaginationMetaResponse } from "../utils/paginationMeta.response";
2
+ export declare class QueueCountsResponse {
3
+ waiting: number;
4
+ active: number;
5
+ completed: number;
6
+ failed: number;
7
+ delayed: number;
8
+ }
9
+ export declare class QueueJobResponse {
10
+ id: string;
11
+ name: string;
12
+ state: string;
13
+ ownerId: string | null;
14
+ attemptsMade: number;
15
+ percent: number | null;
16
+ failedReason: string | null;
17
+ createdAt: string;
18
+ finishedAt: string | null;
19
+ }
20
+ export declare class PaginatedQueueJobsResponse {
21
+ items: QueueJobResponse[];
22
+ meta: PaginationMetaResponse;
23
+ }
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PaginatedQueueJobsResponse = exports.QueueJobResponse = exports.QueueCountsResponse = void 0;
13
+ const swagger_1 = require("@nestjs/swagger");
14
+ const paginationMeta_response_1 = require("../utils/paginationMeta.response");
15
+ class QueueCountsResponse {
16
+ }
17
+ exports.QueueCountsResponse = QueueCountsResponse;
18
+ __decorate([
19
+ (0, swagger_1.ApiProperty)({ example: 3 }),
20
+ __metadata("design:type", Number)
21
+ ], QueueCountsResponse.prototype, "waiting", void 0);
22
+ __decorate([
23
+ (0, swagger_1.ApiProperty)({ example: 1 }),
24
+ __metadata("design:type", Number)
25
+ ], QueueCountsResponse.prototype, "active", void 0);
26
+ __decorate([
27
+ (0, swagger_1.ApiProperty)({ example: 128 }),
28
+ __metadata("design:type", Number)
29
+ ], QueueCountsResponse.prototype, "completed", void 0);
30
+ __decorate([
31
+ (0, swagger_1.ApiProperty)({ example: 2 }),
32
+ __metadata("design:type", Number)
33
+ ], QueueCountsResponse.prototype, "failed", void 0);
34
+ __decorate([
35
+ (0, swagger_1.ApiProperty)({ example: 0 }),
36
+ __metadata("design:type", Number)
37
+ ], QueueCountsResponse.prototype, "delayed", void 0);
38
+ class QueueJobResponse {
39
+ }
40
+ exports.QueueJobResponse = QueueJobResponse;
41
+ __decorate([
42
+ (0, swagger_1.ApiProperty)({ example: "42" }),
43
+ __metadata("design:type", String)
44
+ ], QueueJobResponse.prototype, "id", void 0);
45
+ __decorate([
46
+ (0, swagger_1.ApiProperty)({ example: "funkos:import" }),
47
+ __metadata("design:type", String)
48
+ ], QueueJobResponse.prototype, "name", void 0);
49
+ __decorate([
50
+ (0, swagger_1.ApiProperty)({ example: "failed" }),
51
+ __metadata("design:type", String)
52
+ ], QueueJobResponse.prototype, "state", void 0);
53
+ __decorate([
54
+ (0, swagger_1.ApiProperty)({ type: String, format: "uuid", nullable: true }),
55
+ __metadata("design:type", Object)
56
+ ], QueueJobResponse.prototype, "ownerId", void 0);
57
+ __decorate([
58
+ (0, swagger_1.ApiProperty)({ example: 2 }),
59
+ __metadata("design:type", Number)
60
+ ], QueueJobResponse.prototype, "attemptsMade", void 0);
61
+ __decorate([
62
+ (0, swagger_1.ApiProperty)({ type: Number, nullable: true, example: 69 }),
63
+ __metadata("design:type", Object)
64
+ ], QueueJobResponse.prototype, "percent", void 0);
65
+ __decorate([
66
+ (0, swagger_1.ApiProperty)({ type: String, nullable: true }),
67
+ __metadata("design:type", Object)
68
+ ], QueueJobResponse.prototype, "failedReason", void 0);
69
+ __decorate([
70
+ (0, swagger_1.ApiProperty)({ format: "date-time" }),
71
+ __metadata("design:type", String)
72
+ ], QueueJobResponse.prototype, "createdAt", void 0);
73
+ __decorate([
74
+ (0, swagger_1.ApiProperty)({ type: String, format: "date-time", nullable: true }),
75
+ __metadata("design:type", Object)
76
+ ], QueueJobResponse.prototype, "finishedAt", void 0);
77
+ class PaginatedQueueJobsResponse {
78
+ }
79
+ exports.PaginatedQueueJobsResponse = PaginatedQueueJobsResponse;
80
+ __decorate([
81
+ (0, swagger_1.ApiProperty)({ type: QueueJobResponse, isArray: true }),
82
+ __metadata("design:type", Array)
83
+ ], PaginatedQueueJobsResponse.prototype, "items", void 0);
84
+ __decorate([
85
+ (0, swagger_1.ApiProperty)({ type: paginationMeta_response_1.PaginationMetaResponse }),
86
+ __metadata("design:type", paginationMeta_response_1.PaginationMetaResponse)
87
+ ], PaginatedQueueJobsResponse.prototype, "meta", void 0);
@@ -0,0 +1,15 @@
1
+ import { QueueCounts, QueueJobSummary } from "./job.interface";
2
+ import { JobProducer } from "./job.producer";
3
+ import { Paginated } from "../utils/pagination.util";
4
+ export declare const LISTABLE_STATES: readonly ["waiting", "active", "completed", "failed", "delayed"];
5
+ export type ListableState = (typeof LISTABLE_STATES)[number];
6
+ export declare class QueueAdminService {
7
+ private readonly producer;
8
+ constructor(producer: JobProducer);
9
+ counts(): Promise<QueueCounts>;
10
+ list(state: ListableState, page: number, limit: number): Promise<Paginated<QueueJobSummary>>;
11
+ retry(jobId: string): Promise<void>;
12
+ remove(jobId: string): Promise<void>;
13
+ private findJob;
14
+ private toSummary;
15
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.QueueAdminService = exports.LISTABLE_STATES = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const job_producer_1 = require("./job.producer");
15
+ const pagination_util_1 = require("../utils/pagination.util");
16
+ exports.LISTABLE_STATES = [
17
+ "waiting",
18
+ "active",
19
+ "completed",
20
+ "failed",
21
+ "delayed",
22
+ ];
23
+ let QueueAdminService = class QueueAdminService {
24
+ constructor(producer) {
25
+ this.producer = producer;
26
+ }
27
+ async counts() {
28
+ const queue = this.producer.requireQueue();
29
+ const counts = await queue.getJobCounts(...exports.LISTABLE_STATES);
30
+ return {
31
+ waiting: counts.waiting ?? 0,
32
+ active: counts.active ?? 0,
33
+ completed: counts.completed ?? 0,
34
+ failed: counts.failed ?? 0,
35
+ delayed: counts.delayed ?? 0,
36
+ };
37
+ }
38
+ async list(state, page, limit) {
39
+ const queue = this.producer.requireQueue();
40
+ const start = (page - 1) * limit;
41
+ const [jobs, counts] = await Promise.all([
42
+ queue.getJobs([state], start, start + limit - 1),
43
+ queue.getJobCounts(state),
44
+ ]);
45
+ const items = jobs.filter(Boolean).map((job) => this.toSummary(job, state));
46
+ return new pagination_util_1.Paginated(items, counts[state] ?? 0, page, limit);
47
+ }
48
+ async retry(jobId) {
49
+ const job = await this.findJob(jobId);
50
+ await job.retry();
51
+ }
52
+ async remove(jobId) {
53
+ const job = await this.findJob(jobId);
54
+ await job.remove();
55
+ }
56
+ async findJob(jobId) {
57
+ const queue = this.producer.requireQueue();
58
+ const job = await queue.getJob(jobId);
59
+ if (!job) {
60
+ throw new common_1.NotFoundException("Job não encontrado");
61
+ }
62
+ return job;
63
+ }
64
+ toSummary(job, state) {
65
+ const progress = job.progress;
66
+ return {
67
+ id: String(job.id),
68
+ name: job.name,
69
+ state,
70
+ ownerId: job.data?.ownerId ?? null,
71
+ attemptsMade: job.attemptsMade,
72
+ percent: typeof progress === "object" && progress !== null
73
+ ? (progress.percent ?? null)
74
+ : null,
75
+ failedReason: job.failedReason ?? null,
76
+ createdAt: new Date(job.timestamp).toISOString(),
77
+ finishedAt: job.finishedOn ? new Date(job.finishedOn).toISOString() : null,
78
+ };
79
+ }
80
+ };
81
+ exports.QueueAdminService = QueueAdminService;
82
+ exports.QueueAdminService = QueueAdminService = __decorate([
83
+ (0, common_1.Injectable)(),
84
+ __metadata("design:paramtypes", [job_producer_1.JobProducer])
85
+ ], QueueAdminService);
@@ -0,0 +1,2 @@
1
+ import { RedisOptions } from "ioredis";
2
+ export declare const buildRedisOptions: () => RedisOptions;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildRedisOptions = void 0;
4
+ const buildRedisOptions = () => ({
5
+ host: process.env.REDIS_HOST,
6
+ port: Number(process.env.REDIS_PORT) || 6379,
7
+ password: process.env.REDIS_PASSWORD || undefined,
8
+ maxRetriesPerRequest: null,
9
+ enableReadyCheck: false,
10
+ });
11
+ exports.buildRedisOptions = buildRedisOptions;
@@ -17,6 +17,7 @@ export declare abstract class BaseGateway implements OnGatewayConnection, OnGate
17
17
  handleConnection(socket: Socket): Promise<void>;
18
18
  handleDisconnect(socket: Socket): void;
19
19
  requestSessionRefresh(userId: string): void;
20
+ emitToUser<T>(userId: string, event: string, data: T): void;
20
21
  protected emitTo<T>(rooms: string[], event: string, data: T): void;
21
22
  private scheduleExpiry;
22
23
  }
@@ -43,6 +43,9 @@ class BaseGateway {
43
43
  requestSessionRefresh(userId) {
44
44
  this.emitTo([(0, socket_constants_1.userRoom)(userId)], socket_constants_1.SESSION_REFRESH_EVENT, { userId });
45
45
  }
46
+ emitToUser(userId, event, data) {
47
+ this.emitTo([(0, socket_constants_1.userRoom)(userId)], event, data);
48
+ }
46
49
  emitTo(rooms, event, data) {
47
50
  const targets = rooms.filter((room) => room.length > 0);
48
51
  if (targets.length === 0) {
@@ -29,6 +29,7 @@ exports.AuditModule = AuditModule = __decorate([
29
29
  domain_1.AuditService,
30
30
  { provide: core_1.APP_INTERCEPTOR, useClass: presentation_1.AuditInterceptor },
31
31
  presentation_1.HttpErrorListener,
32
+ presentation_1.UserPermissionsChangedListener,
32
33
  presentation_1.UserRolesChangedListener,
33
34
  infra_1.AuditDataSubscriber,
34
35
  ],
@@ -2,4 +2,5 @@ export * from "./audit.controller";
2
2
  export * from "./audit.interceptor";
3
3
  export * from "./decorators/auditable.decorator";
4
4
  export * from "./httpError.listener";
5
+ export * from "./userPermissionsChanged.listener";
5
6
  export * from "./userRolesChanged.listener";
@@ -18,4 +18,5 @@ __exportStar(require("./audit.controller"), exports);
18
18
  __exportStar(require("./audit.interceptor"), exports);
19
19
  __exportStar(require("./decorators/auditable.decorator"), exports);
20
20
  __exportStar(require("./httpError.listener"), exports);
21
+ __exportStar(require("./userPermissionsChanged.listener"), exports);
21
22
  __exportStar(require("./userRolesChanged.listener"), exports);
@@ -0,0 +1,7 @@
1
+ import { UserPermissionsChangedEvent } from "../../../core/events/appEvent.enum";
2
+ import { AuditService } from "../domain/audit.service";
3
+ export declare class UserPermissionsChangedListener {
4
+ private readonly audit;
5
+ constructor(audit: AuditService);
6
+ onPermissionsChanged(event: UserPermissionsChangedEvent): Promise<void>;
7
+ }