@flusys/nestjs-task-manager 5.3.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 (137) hide show
  1. package/README.md +245 -0
  2. package/cjs/config/index.js +19 -0
  3. package/cjs/config/message-keys.js +92 -0
  4. package/cjs/config/task-manager.constants.js +11 -0
  5. package/cjs/controllers/index.js +22 -0
  6. package/cjs/controllers/task-board.controller.js +219 -0
  7. package/cjs/controllers/task-comment.controller.js +103 -0
  8. package/cjs/controllers/task-label.controller.js +112 -0
  9. package/cjs/controllers/task-list.controller.js +158 -0
  10. package/cjs/controllers/task.controller.js +199 -0
  11. package/cjs/docs/index.js +18 -0
  12. package/cjs/docs/task-manager-swagger.config.js +43 -0
  13. package/cjs/dtos/index.js +22 -0
  14. package/cjs/dtos/task-board.dto.js +310 -0
  15. package/cjs/dtos/task-comment.dto.js +131 -0
  16. package/cjs/dtos/task-label.dto.js +120 -0
  17. package/cjs/dtos/task-list.dto.js +198 -0
  18. package/cjs/dtos/task.dto.js +367 -0
  19. package/cjs/entities/index.js +72 -0
  20. package/cjs/entities/task-activity.entity.js +98 -0
  21. package/cjs/entities/task-assignee.entity.js +67 -0
  22. package/cjs/entities/task-board-member.entity.js +94 -0
  23. package/cjs/entities/task-board-with-company.entity.js +57 -0
  24. package/cjs/entities/task-board.entity.js +88 -0
  25. package/cjs/entities/task-comment.entity.js +80 -0
  26. package/cjs/entities/task-label.entity.js +72 -0
  27. package/cjs/entities/task-list.entity.js +104 -0
  28. package/cjs/entities/task-task-label.entity.js +67 -0
  29. package/cjs/entities/task.entity.js +151 -0
  30. package/cjs/gateways/index.js +18 -0
  31. package/cjs/gateways/task-board.gateway.js +199 -0
  32. package/cjs/index.js +26 -0
  33. package/cjs/interfaces/index.js +19 -0
  34. package/cjs/interfaces/task-manager-module.interface.js +4 -0
  35. package/cjs/interfaces/task.interface.js +4 -0
  36. package/cjs/modules/index.js +18 -0
  37. package/cjs/modules/task-manager.module.js +131 -0
  38. package/cjs/services/index.js +25 -0
  39. package/cjs/services/task-activity.service.js +76 -0
  40. package/cjs/services/task-board.service.js +235 -0
  41. package/cjs/services/task-comment.service.js +103 -0
  42. package/cjs/services/task-label.service.js +97 -0
  43. package/cjs/services/task-list.service.js +115 -0
  44. package/cjs/services/task-manager-config.service.js +69 -0
  45. package/cjs/services/task-manager-datasource.provider.js +84 -0
  46. package/cjs/services/task.service.js +359 -0
  47. package/config/index.d.ts +2 -0
  48. package/config/message-keys.d.ts +65 -0
  49. package/config/task-manager.constants.d.ts +1 -0
  50. package/controllers/index.d.ts +5 -0
  51. package/controllers/task-board.controller.d.ts +27 -0
  52. package/controllers/task-comment.controller.d.ts +22 -0
  53. package/controllers/task-label.controller.d.ts +22 -0
  54. package/controllers/task-list.controller.d.ts +26 -0
  55. package/controllers/task.controller.d.ts +28 -0
  56. package/docs/index.d.ts +1 -0
  57. package/docs/task-manager-swagger.config.d.ts +2 -0
  58. package/dtos/index.d.ts +5 -0
  59. package/dtos/task-board.dto.d.ts +44 -0
  60. package/dtos/task-comment.dto.d.ts +16 -0
  61. package/dtos/task-label.dto.d.ts +16 -0
  62. package/dtos/task-list.dto.d.ts +26 -0
  63. package/dtos/task.dto.d.ts +48 -0
  64. package/entities/index.d.ts +22 -0
  65. package/entities/task-activity.entity.d.ts +9 -0
  66. package/entities/task-assignee.entity.d.ts +5 -0
  67. package/entities/task-board-member.entity.d.ts +12 -0
  68. package/entities/task-board-with-company.entity.d.ts +4 -0
  69. package/entities/task-board.entity.d.ts +8 -0
  70. package/entities/task-comment.entity.d.ts +7 -0
  71. package/entities/task-label.entity.d.ts +6 -0
  72. package/entities/task-list.entity.d.ts +9 -0
  73. package/entities/task-task-label.entity.d.ts +5 -0
  74. package/entities/task.entity.d.ts +23 -0
  75. package/fesm/config/index.js +2 -0
  76. package/fesm/config/message-keys.js +65 -0
  77. package/fesm/config/task-manager.constants.js +1 -0
  78. package/fesm/controllers/index.js +5 -0
  79. package/fesm/controllers/task-board.controller.js +209 -0
  80. package/fesm/controllers/task-comment.controller.js +93 -0
  81. package/fesm/controllers/task-label.controller.js +102 -0
  82. package/fesm/controllers/task-list.controller.js +148 -0
  83. package/fesm/controllers/task.controller.js +189 -0
  84. package/fesm/docs/index.js +1 -0
  85. package/fesm/docs/task-manager-swagger.config.js +33 -0
  86. package/fesm/dtos/index.js +5 -0
  87. package/fesm/dtos/task-board.dto.js +277 -0
  88. package/fesm/dtos/task-comment.dto.js +110 -0
  89. package/fesm/dtos/task-label.dto.js +99 -0
  90. package/fesm/dtos/task-list.dto.js +174 -0
  91. package/fesm/dtos/task.dto.js +337 -0
  92. package/fesm/entities/index.js +46 -0
  93. package/fesm/entities/task-activity.entity.js +88 -0
  94. package/fesm/entities/task-assignee.entity.js +57 -0
  95. package/fesm/entities/task-board-member.entity.js +76 -0
  96. package/fesm/entities/task-board-with-company.entity.js +47 -0
  97. package/fesm/entities/task-board.entity.js +78 -0
  98. package/fesm/entities/task-comment.entity.js +70 -0
  99. package/fesm/entities/task-label.entity.js +62 -0
  100. package/fesm/entities/task-list.entity.js +94 -0
  101. package/fesm/entities/task-task-label.entity.js +57 -0
  102. package/fesm/entities/task.entity.js +133 -0
  103. package/fesm/gateways/index.js +1 -0
  104. package/fesm/gateways/task-board.gateway.js +148 -0
  105. package/fesm/index.js +9 -0
  106. package/fesm/interfaces/index.js +2 -0
  107. package/fesm/interfaces/task-manager-module.interface.js +1 -0
  108. package/fesm/interfaces/task.interface.js +1 -0
  109. package/fesm/modules/index.js +1 -0
  110. package/fesm/modules/task-manager.module.js +121 -0
  111. package/fesm/services/index.js +8 -0
  112. package/fesm/services/task-activity.service.js +66 -0
  113. package/fesm/services/task-board.service.js +225 -0
  114. package/fesm/services/task-comment.service.js +93 -0
  115. package/fesm/services/task-label.service.js +87 -0
  116. package/fesm/services/task-list.service.js +105 -0
  117. package/fesm/services/task-manager-config.service.js +59 -0
  118. package/fesm/services/task-manager-datasource.provider.js +74 -0
  119. package/fesm/services/task.service.js +349 -0
  120. package/gateways/index.d.ts +1 -0
  121. package/gateways/task-board.gateway.d.ts +22 -0
  122. package/index.d.ts +9 -0
  123. package/interfaces/index.d.ts +2 -0
  124. package/interfaces/task-manager-module.interface.d.ts +19 -0
  125. package/interfaces/task.interface.d.ts +52 -0
  126. package/modules/index.d.ts +1 -0
  127. package/modules/task-manager.module.d.ts +8 -0
  128. package/package.json +91 -0
  129. package/services/index.d.ts +8 -0
  130. package/services/task-activity.service.d.ts +8 -0
  131. package/services/task-board.service.d.ts +32 -0
  132. package/services/task-comment.service.d.ts +18 -0
  133. package/services/task-label.service.d.ts +18 -0
  134. package/services/task-list.service.d.ts +19 -0
  135. package/services/task-manager-config.service.d.ts +12 -0
  136. package/services/task-manager-datasource.provider.d.ts +18 -0
  137. package/services/task.service.d.ts +44 -0
@@ -0,0 +1,225 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
29
+ import { UtilsService } from '@flusys/nestjs-shared/modules';
30
+ import { applyCompanyFilter } from '@flusys/nestjs-shared/utils';
31
+ import { BadRequestException, Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
32
+ import { IsNull } from 'typeorm';
33
+ import { TASK_BOARD_MESSAGES } from '../config';
34
+ import { BoardMemberRole, TaskBoardMember, TaskBoard, TaskBoardWithCompany } from '../entities';
35
+ import { TaskManagerConfigService } from './task-manager-config.service';
36
+ import { TaskManagerDataSourceProvider } from './task-manager-datasource.provider';
37
+ export class TaskBoardService extends ApiService {
38
+ resolveEntity() {
39
+ return this.config.isCompanyFeatureEnabled() ? TaskBoardWithCompany : TaskBoard;
40
+ }
41
+ async convertSingleDtoToEntity(dto, user) {
42
+ await this.ensureDataSourceRepository();
43
+ let entity = {};
44
+ if ('id' in dto && dto.id) {
45
+ const existing = await this.repository.findOne({
46
+ where: {
47
+ id: dto.id
48
+ }
49
+ });
50
+ if (!existing) throw new NotFoundException({
51
+ message: 'Board not found',
52
+ messageKey: TASK_BOARD_MESSAGES.NOT_FOUND
53
+ });
54
+ entity = existing;
55
+ }
56
+ const merged = {
57
+ ...entity,
58
+ name: dto.name ?? entity.name,
59
+ description: dto.description !== undefined ? dto.description ?? null : entity.description ?? null,
60
+ color: dto.color ?? entity.color ?? '#3B82F6',
61
+ isActive: ('isActive' in dto ? dto.isActive : undefined) ?? entity.isActive ?? true
62
+ };
63
+ if (this.config.isCompanyFeatureEnabled()) {
64
+ merged.companyId = user?.companyId ?? null;
65
+ }
66
+ return merged;
67
+ }
68
+ async getExtraManipulateQuery(query, filterDto, user) {
69
+ await super.getExtraManipulateQuery(query, filterDto, user);
70
+ applyCompanyFilter(query, {
71
+ isCompanyFeatureEnabled: this.config.isCompanyFeatureEnabled(),
72
+ entityAlias: 'task_board'
73
+ }, user);
74
+ if (user?.id) {
75
+ query.innerJoin('task_board_member', 'tbm_filter', 'tbm_filter.board_id = task_board.id AND tbm_filter.user_id = :currentUserId AND tbm_filter.deleted_at IS NULL', {
76
+ currentUserId: user.id
77
+ });
78
+ }
79
+ query.addSelect('task_board.createdAt').addSelect('task_board.updatedAt').addSelect(`(SELECT CAST(COUNT(*) AS INTEGER) FROM task_board_member tbm WHERE tbm.board_id = task_board.id AND tbm.deleted_at IS NULL)`, 'total_members').addSelect(`(SELECT CAST(COUNT(*) AS INTEGER) FROM task_list tl WHERE tl.board_id = task_board.id AND tl.is_active = true AND tl.deleted_at IS NULL)`, 'total_lists').addSelect(`(SELECT CAST(COUNT(*) AS INTEGER) FROM task t WHERE t.board_id = task_board.id AND t.deleted_at IS NULL)`, 'total_tasks');
80
+ return {
81
+ query,
82
+ isRaw: true
83
+ };
84
+ }
85
+ convertEntityToResponseDto(entity, isRaw) {
86
+ if (!isRaw) return super.convertEntityToResponseDto(entity, isRaw);
87
+ const prefix = `${this.entityName}_`;
88
+ const mapped = {};
89
+ for (const [key, value] of Object.entries(entity)){
90
+ const rawKey = key.startsWith(prefix) ? key.slice(prefix.length) : key;
91
+ const camelKey = rawKey.replace(/_([a-z])/g, (_, c)=>c.toUpperCase());
92
+ mapped[camelKey] = typeof value === 'string' && value !== '' && !isNaN(Number(value)) ? Number(value) : value;
93
+ }
94
+ return mapped;
95
+ }
96
+ async addMember(dto, user) {
97
+ await this.ensureDataSourceRepository();
98
+ const memberRepo = await this.ensureMemberRepository();
99
+ const board = await this.repository.findOne({
100
+ where: {
101
+ id: dto.boardId
102
+ }
103
+ });
104
+ if (!board) throw new NotFoundException({
105
+ message: 'Board not found',
106
+ messageKey: TASK_BOARD_MESSAGES.NOT_FOUND
107
+ });
108
+ const existing = await memberRepo.findOne({
109
+ where: {
110
+ boardId: dto.boardId,
111
+ userId: dto.userId,
112
+ deletedAt: IsNull()
113
+ }
114
+ });
115
+ if (existing) throw new BadRequestException({
116
+ message: 'User is already a board member',
117
+ messageKey: TASK_BOARD_MESSAGES.MEMBER_ALREADY_EXISTS
118
+ });
119
+ const softDeleted = await memberRepo.findOne({
120
+ where: {
121
+ boardId: dto.boardId,
122
+ userId: dto.userId
123
+ },
124
+ withDeleted: true
125
+ });
126
+ if (softDeleted) {
127
+ await memberRepo.restore({
128
+ id: softDeleted.id
129
+ });
130
+ await memberRepo.update({
131
+ id: softDeleted.id
132
+ }, {
133
+ role: dto.role ?? BoardMemberRole.MEMBER
134
+ });
135
+ return memberRepo.findOne({
136
+ where: {
137
+ id: softDeleted.id
138
+ }
139
+ });
140
+ }
141
+ const member = memberRepo.create({
142
+ boardId: dto.boardId,
143
+ userId: dto.userId,
144
+ role: dto.role ?? BoardMemberRole.MEMBER,
145
+ createdById: user.id
146
+ });
147
+ return memberRepo.save(member);
148
+ }
149
+ async removeMember(dto) {
150
+ const memberRepo = await this.ensureMemberRepository();
151
+ const member = await memberRepo.findOne({
152
+ where: {
153
+ boardId: dto.boardId,
154
+ userId: dto.userId,
155
+ deletedAt: IsNull()
156
+ }
157
+ });
158
+ if (!member) throw new NotFoundException({
159
+ message: 'Member not found',
160
+ messageKey: TASK_BOARD_MESSAGES.MEMBER_NOT_FOUND
161
+ });
162
+ await memberRepo.update({
163
+ id: member.id
164
+ }, {
165
+ deletedAt: new Date()
166
+ });
167
+ }
168
+ async getMembers(boardId) {
169
+ const memberRepo = await this.ensureMemberRepository();
170
+ const { entities, raw } = await memberRepo.createQueryBuilder('tbm').leftJoin('app_user', 'u', 'u.id = tbm.user_id').addSelect('u.name', 'userName').addSelect('u.email', 'userEmail').where('tbm.board_id = :boardId', {
171
+ boardId
172
+ }).andWhere('tbm.deleted_at IS NULL').orderBy('tbm.created_at', 'ASC').getRawAndEntities();
173
+ return entities.map((entity, i)=>({
174
+ ...entity,
175
+ userName: raw[i]?.userName ?? null,
176
+ userEmail: raw[i]?.userEmail ?? null
177
+ }));
178
+ }
179
+ async isBoardMember(boardId, userId) {
180
+ const memberRepo = await this.ensureMemberRepository();
181
+ const count = await memberRepo.count({
182
+ where: {
183
+ boardId,
184
+ userId,
185
+ deletedAt: IsNull()
186
+ }
187
+ });
188
+ return count > 0;
189
+ }
190
+ async afterInsertOperation(entities, user, _qr) {
191
+ if (!user?.id) return;
192
+ const memberRepo = await this.ensureMemberRepository();
193
+ await memberRepo.save(entities.map((board)=>memberRepo.create({
194
+ boardId: board.id,
195
+ userId: user.id,
196
+ role: BoardMemberRole.OWNER,
197
+ createdById: user.id
198
+ })));
199
+ }
200
+ async ensureMemberRepository() {
201
+ if (!this.memberRepository) {
202
+ this.memberRepository = await this.dataSourceProvider.getRepository(TaskBoardMember);
203
+ }
204
+ return this.memberRepository;
205
+ }
206
+ constructor(cacheManager, utilsService, config, dataSourceProvider){
207
+ super('task_board', cacheManager, utilsService, TaskBoardService.name, true, 'task-manager', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "config", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "memberRepository", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.config = config, this.dataSourceProvider = dataSourceProvider, this.memberRepository = null;
208
+ }
209
+ }
210
+ TaskBoardService = _ts_decorate([
211
+ Injectable({
212
+ scope: Scope.REQUEST
213
+ }),
214
+ _ts_param(0, Inject('CACHE_INSTANCE')),
215
+ _ts_param(1, Inject(UtilsService)),
216
+ _ts_param(2, Inject(TaskManagerConfigService)),
217
+ _ts_param(3, Inject(TaskManagerDataSourceProvider)),
218
+ _ts_metadata("design:type", Function),
219
+ _ts_metadata("design:paramtypes", [
220
+ typeof HybridCache === "undefined" ? Object : HybridCache,
221
+ typeof UtilsService === "undefined" ? Object : UtilsService,
222
+ typeof TaskManagerConfigService === "undefined" ? Object : TaskManagerConfigService,
223
+ typeof TaskManagerDataSourceProvider === "undefined" ? Object : TaskManagerDataSourceProvider
224
+ ])
225
+ ], TaskBoardService);
@@ -0,0 +1,93 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
29
+ import { UtilsService } from '@flusys/nestjs-shared/modules';
30
+ import { ForbiddenException, Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
31
+ import { TASK_COMMENT_MESSAGES } from '../config';
32
+ import { TaskComment } from '../entities';
33
+ import { TaskManagerDataSourceProvider } from './task-manager-datasource.provider';
34
+ export class TaskCommentService extends ApiService {
35
+ async convertSingleDtoToEntity(dto, user) {
36
+ await this.ensureDataSourceRepository();
37
+ let entity = {};
38
+ if ('id' in dto && dto.id) {
39
+ const existing = await this.repository.findOne({
40
+ where: {
41
+ id: dto.id
42
+ }
43
+ });
44
+ if (!existing) throw new NotFoundException({
45
+ message: 'Comment not found',
46
+ messageKey: TASK_COMMENT_MESSAGES.NOT_FOUND
47
+ });
48
+ if (existing.userId !== user?.id) throw new ForbiddenException({
49
+ message: 'Cannot edit another user comment',
50
+ messageKey: TASK_COMMENT_MESSAGES.FORBIDDEN
51
+ });
52
+ entity = existing;
53
+ }
54
+ const taskId = ('taskId' in dto ? dto.taskId : undefined) ?? entity.taskId;
55
+ return {
56
+ ...entity,
57
+ taskId,
58
+ userId: entity.userId !== undefined ? entity.userId : user?.id ?? null,
59
+ content: dto.content,
60
+ parentCommentId: 'parentCommentId' in dto ? dto.parentCommentId ?? null : entity.parentCommentId ?? null
61
+ };
62
+ }
63
+ async getFilterQuery(query, filter, _user) {
64
+ for (const [key, value] of Object.entries(filter)){
65
+ if (key === 'taskId') {
66
+ query.andWhere('task_comment.taskId = :taskId', {
67
+ taskId: value
68
+ });
69
+ }
70
+ }
71
+ return {
72
+ query,
73
+ isRaw: false
74
+ };
75
+ }
76
+ constructor(cacheManager, utilsService, dataSourceProvider){
77
+ super('task_comment', cacheManager, utilsService, TaskCommentService.name, false, 'task-manager', TaskComment, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider;
78
+ }
79
+ }
80
+ TaskCommentService = _ts_decorate([
81
+ Injectable({
82
+ scope: Scope.REQUEST
83
+ }),
84
+ _ts_param(0, Inject('CACHE_INSTANCE')),
85
+ _ts_param(1, Inject(UtilsService)),
86
+ _ts_param(2, Inject(TaskManagerDataSourceProvider)),
87
+ _ts_metadata("design:type", Function),
88
+ _ts_metadata("design:paramtypes", [
89
+ typeof HybridCache === "undefined" ? Object : HybridCache,
90
+ typeof UtilsService === "undefined" ? Object : UtilsService,
91
+ typeof TaskManagerDataSourceProvider === "undefined" ? Object : TaskManagerDataSourceProvider
92
+ ])
93
+ ], TaskCommentService);
@@ -0,0 +1,87 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { ApiService, HybridCache } from '@flusys/nestjs-shared/classes';
29
+ import { UtilsService } from '@flusys/nestjs-shared/modules';
30
+ import { Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
31
+ import { TASK_LABEL_MESSAGES } from '../config';
32
+ import { TaskLabel } from '../entities';
33
+ import { TaskManagerDataSourceProvider } from './task-manager-datasource.provider';
34
+ export class TaskLabelService extends ApiService {
35
+ async convertSingleDtoToEntity(dto, _user) {
36
+ await this.ensureDataSourceRepository();
37
+ let entity = {};
38
+ if ('id' in dto && dto.id) {
39
+ const existing = await this.repository.findOne({
40
+ where: {
41
+ id: dto.id
42
+ }
43
+ });
44
+ if (!existing) throw new NotFoundException({
45
+ message: 'Label not found',
46
+ messageKey: TASK_LABEL_MESSAGES.NOT_FOUND
47
+ });
48
+ entity = existing;
49
+ }
50
+ return {
51
+ ...entity,
52
+ boardId: dto.boardId ?? entity.boardId,
53
+ name: dto.name ?? entity.name,
54
+ color: dto.color ?? entity.color ?? '#10B981'
55
+ };
56
+ }
57
+ async getFilterQuery(query, filter, _user) {
58
+ for (const [key, value] of Object.entries(filter)){
59
+ if (key === 'boardId') {
60
+ query.andWhere('task_label.boardId = :boardId', {
61
+ boardId: value
62
+ });
63
+ }
64
+ }
65
+ return {
66
+ query,
67
+ isRaw: false
68
+ };
69
+ }
70
+ constructor(cacheManager, utilsService, dataSourceProvider){
71
+ super('task_label', cacheManager, utilsService, TaskLabelService.name, true, 'task-manager', TaskLabel, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider;
72
+ }
73
+ }
74
+ TaskLabelService = _ts_decorate([
75
+ Injectable({
76
+ scope: Scope.REQUEST
77
+ }),
78
+ _ts_param(0, Inject('CACHE_INSTANCE')),
79
+ _ts_param(1, Inject(UtilsService)),
80
+ _ts_param(2, Inject(TaskManagerDataSourceProvider)),
81
+ _ts_metadata("design:type", Function),
82
+ _ts_metadata("design:paramtypes", [
83
+ typeof HybridCache === "undefined" ? Object : HybridCache,
84
+ typeof UtilsService === "undefined" ? Object : UtilsService,
85
+ typeof TaskManagerDataSourceProvider === "undefined" ? Object : TaskManagerDataSourceProvider
86
+ ])
87
+ ], TaskLabelService);
@@ -0,0 +1,105 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { ApiService, HybridCache } from '@flusys/nestjs-shared/classes';
29
+ import { UtilsService } from '@flusys/nestjs-shared/modules';
30
+ import { Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
31
+ import { TASK_LIST_MESSAGES } from '../config';
32
+ import { TaskList } from '../entities';
33
+ import { TaskManagerDataSourceProvider } from './task-manager-datasource.provider';
34
+ export class TaskListService extends ApiService {
35
+ async convertSingleDtoToEntity(dto, _user) {
36
+ await this.ensureDataSourceRepository();
37
+ let entity = {};
38
+ if ('id' in dto && dto.id) {
39
+ const existing = await this.repository.findOne({
40
+ where: {
41
+ id: dto.id
42
+ }
43
+ });
44
+ if (!existing) throw new NotFoundException({
45
+ message: 'List not found',
46
+ messageKey: TASK_LIST_MESSAGES.NOT_FOUND
47
+ });
48
+ entity = existing;
49
+ }
50
+ return {
51
+ ...entity,
52
+ boardId: dto.boardId ?? entity.boardId,
53
+ name: dto.name ?? entity.name,
54
+ color: dto.color ?? entity.color ?? '#6B7280',
55
+ position: dto.position ?? entity.position ?? 0,
56
+ isDoneList: ('isDoneList' in dto ? dto.isDoneList : undefined) ?? entity.isDoneList ?? false,
57
+ isActive: ('isActive' in dto ? dto.isActive : undefined) ?? entity.isActive ?? true
58
+ };
59
+ }
60
+ async getFilterQuery(query, filter, _user) {
61
+ for (const [key, value] of Object.entries(filter)){
62
+ if (key === 'boardId') {
63
+ query.andWhere('task_list.boardId = :boardId', {
64
+ boardId: value
65
+ });
66
+ } else if (key === 'isActive' && typeof value === 'boolean') {
67
+ query.andWhere('task_list.isActive = :isActive', {
68
+ isActive: value
69
+ });
70
+ }
71
+ }
72
+ query.orderBy('task_list.position', 'ASC');
73
+ return {
74
+ query,
75
+ isRaw: false
76
+ };
77
+ }
78
+ async reorderLists(dto) {
79
+ await this.ensureDataSourceRepository();
80
+ await Promise.all(dto.orderedIds.map((id, i)=>this.repository.update({
81
+ id,
82
+ boardId: dto.boardId
83
+ }, {
84
+ position: i * 100
85
+ })));
86
+ await this.clearCacheForAll();
87
+ }
88
+ constructor(cacheManager, utilsService, dataSourceProvider){
89
+ super('task_list', cacheManager, utilsService, TaskListService.name, true, 'task-manager', TaskList, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider;
90
+ }
91
+ }
92
+ TaskListService = _ts_decorate([
93
+ Injectable({
94
+ scope: Scope.REQUEST
95
+ }),
96
+ _ts_param(0, Inject('CACHE_INSTANCE')),
97
+ _ts_param(1, Inject(UtilsService)),
98
+ _ts_param(2, Inject(TaskManagerDataSourceProvider)),
99
+ _ts_metadata("design:type", Function),
100
+ _ts_metadata("design:paramtypes", [
101
+ typeof HybridCache === "undefined" ? Object : HybridCache,
102
+ typeof UtilsService === "undefined" ? Object : UtilsService,
103
+ typeof TaskManagerDataSourceProvider === "undefined" ? Object : TaskManagerDataSourceProvider
104
+ ])
105
+ ], TaskListService);
@@ -0,0 +1,59 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { Inject, Injectable } from '@nestjs/common';
29
+ import { TASK_MANAGER_MODULE_OPTIONS } from '../config/task-manager.constants';
30
+ import { TaskManagerModuleOptions } from '../interfaces';
31
+ export class TaskManagerConfigService {
32
+ isCompanyFeatureEnabled() {
33
+ return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
34
+ }
35
+ getDatabaseMode() {
36
+ return this.options.bootstrapAppConfig?.databaseMode ?? 'single';
37
+ }
38
+ isMultiTenant() {
39
+ return this.getDatabaseMode() === 'multi-tenant';
40
+ }
41
+ getJwtSecret() {
42
+ return this.options.config?.jwtSecret;
43
+ }
44
+ getOptions() {
45
+ return this.options;
46
+ }
47
+ constructor(options){
48
+ _define_property(this, "options", void 0);
49
+ this.options = options;
50
+ }
51
+ }
52
+ TaskManagerConfigService = _ts_decorate([
53
+ Injectable(),
54
+ _ts_param(0, Inject(TASK_MANAGER_MODULE_OPTIONS)),
55
+ _ts_metadata("design:type", Function),
56
+ _ts_metadata("design:paramtypes", [
57
+ typeof TaskManagerModuleOptions === "undefined" ? Object : TaskManagerModuleOptions
58
+ ])
59
+ ], TaskManagerConfigService);
@@ -0,0 +1,74 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ function _ts_param(paramIndex, decorator) {
24
+ return function(target, key) {
25
+ decorator(target, key, paramIndex);
26
+ };
27
+ }
28
+ import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
29
+ import { Inject, Injectable, Optional, Scope } from '@nestjs/common';
30
+ import { REQUEST } from '@nestjs/core';
31
+ import { Request } from 'express';
32
+ import { getTaskManagerEntitiesByConfig } from '../entities';
33
+ import { TaskManagerConfigService } from './task-manager-config.service';
34
+ export class TaskManagerDataSourceProvider extends MultiTenantDataSourceService {
35
+ static buildParentOptions(options) {
36
+ return {
37
+ bootstrapAppConfig: options.bootstrapAppConfig,
38
+ defaultDatabaseConfig: options.config?.defaultDatabaseConfig,
39
+ tenantDefaultDatabaseConfig: options.config?.tenantDefaultDatabaseConfig,
40
+ tenants: options.config?.tenants
41
+ };
42
+ }
43
+ getEnableCompanyFeatureForTenant(tenant) {
44
+ return tenant?.enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
45
+ }
46
+ async createDataSourceFromConfig(config) {
47
+ const currentTenant = this.getCurrentTenant();
48
+ const enableCompanyFeature = this.getEnableCompanyFeatureForTenant(currentTenant ?? undefined);
49
+ const entities = getTaskManagerEntitiesByConfig(enableCompanyFeature);
50
+ return super.createDataSourceFromConfig(config, entities);
51
+ }
52
+ constructor(configService, request){
53
+ super(TaskManagerDataSourceProvider.buildParentOptions(configService.getOptions()), request), _define_property(this, "configService", void 0), this.configService = configService;
54
+ }
55
+ }
56
+ _define_property(TaskManagerDataSourceProvider, "tenantConnections", new Map());
57
+ _define_property(TaskManagerDataSourceProvider, "singleDataSource", null);
58
+ _define_property(TaskManagerDataSourceProvider, "tenantsRegistry", new Map());
59
+ _define_property(TaskManagerDataSourceProvider, "initialized", false);
60
+ _define_property(TaskManagerDataSourceProvider, "connectionLocks", new Map());
61
+ _define_property(TaskManagerDataSourceProvider, "singleConnectionLock", null);
62
+ TaskManagerDataSourceProvider = _ts_decorate([
63
+ Injectable({
64
+ scope: Scope.REQUEST
65
+ }),
66
+ _ts_param(0, Inject(TaskManagerConfigService)),
67
+ _ts_param(1, Optional()),
68
+ _ts_param(1, Inject(REQUEST)),
69
+ _ts_metadata("design:type", Function),
70
+ _ts_metadata("design:paramtypes", [
71
+ typeof TaskManagerConfigService === "undefined" ? Object : TaskManagerConfigService,
72
+ typeof Request === "undefined" ? Object : Request
73
+ ])
74
+ ], TaskManagerDataSourceProvider);