@servicelabsco/nestjs-utility-services 3.0.4 → 3.0.6

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 (124) hide show
  1. package/CHANGELOG.md +50 -6
  2. package/README.md +164 -60
  3. package/dist/auth/es6.classes.d.ts +3 -6
  4. package/dist/auth/es6.classes.js +2 -6
  5. package/dist/auth/es6.classes.js.map +1 -1
  6. package/dist/auth/index.d.ts +0 -2
  7. package/dist/auth/index.js +0 -2
  8. package/dist/auth/index.js.map +1 -1
  9. package/dist/common/libraries/common.entity.js +4 -6
  10. package/dist/common/libraries/common.entity.js.map +1 -1
  11. package/dist/config/sentry.config.d.ts +1 -1
  12. package/dist/platformUtility/es6.classes.d.ts +1 -2
  13. package/dist/platformUtility/es6.classes.js +1 -10
  14. package/dist/platformUtility/es6.classes.js.map +1 -1
  15. package/dist/platformUtility/jobs/index.d.ts +0 -1
  16. package/dist/platformUtility/jobs/index.js +0 -1
  17. package/dist/platformUtility/jobs/index.js.map +1 -1
  18. package/dist/platformUtility/services/es6.jobs.service.d.ts +1 -3
  19. package/dist/platformUtility/services/es6.jobs.service.js +1 -5
  20. package/dist/platformUtility/services/es6.jobs.service.js.map +1 -1
  21. package/dist/platformUtility/subscribers/dispatcher.subscriber.d.ts +1 -4
  22. package/dist/platformUtility/subscribers/dispatcher.subscriber.js +43 -30
  23. package/dist/platformUtility/subscribers/dispatcher.subscriber.js.map +1 -1
  24. package/dist/system/es6.classes.d.ts +8 -11
  25. package/dist/system/es6.classes.js +14 -20
  26. package/dist/system/es6.classes.js.map +1 -1
  27. package/dist/system/index.d.ts +1 -0
  28. package/dist/system/index.js +1 -0
  29. package/dist/system/index.js.map +1 -1
  30. package/dist/system/jobs/client.credential.job.d.ts +0 -2
  31. package/dist/system/jobs/client.credential.job.js +0 -4
  32. package/dist/system/jobs/client.credential.job.js.map +1 -1
  33. package/dist/system/jobs/code.fix.script.job.d.ts +0 -4
  34. package/dist/system/jobs/code.fix.script.job.js +0 -21
  35. package/dist/system/jobs/code.fix.script.job.js.map +1 -1
  36. package/dist/system/jobs/index.d.ts +0 -10
  37. package/dist/system/jobs/index.js +0 -10
  38. package/dist/system/jobs/index.js.map +1 -1
  39. package/dist/system/jobs/material.view.job.d.ts +0 -4
  40. package/dist/system/jobs/material.view.job.js +0 -21
  41. package/dist/system/jobs/material.view.job.js.map +1 -1
  42. package/dist/system/jobs/property.job.d.ts +0 -3
  43. package/dist/system/jobs/property.job.js +0 -9
  44. package/dist/system/jobs/property.job.js.map +1 -1
  45. package/dist/system/jobs/recurring.query.job.d.ts +0 -4
  46. package/dist/system/jobs/recurring.query.job.js +0 -21
  47. package/dist/system/jobs/recurring.query.job.js.map +1 -1
  48. package/dist/system/jobs/scheduled.event.job.d.ts +0 -4
  49. package/dist/system/jobs/scheduled.event.job.js +0 -21
  50. package/dist/system/jobs/scheduled.event.job.js.map +1 -1
  51. package/dist/system/services/es6.jobs.service.d.ts +1 -21
  52. package/dist/system/services/es6.jobs.service.js +1 -41
  53. package/dist/system/services/es6.jobs.service.js.map +1 -1
  54. package/dist/system/subscribers/client.credential.subscriber.d.ts +9 -0
  55. package/dist/system/subscribers/client.credential.subscriber.js +35 -0
  56. package/dist/system/subscribers/client.credential.subscriber.js.map +1 -0
  57. package/dist/system/subscribers/code.fix.script.subscriber.d.ts +11 -0
  58. package/dist/system/subscribers/code.fix.script.subscriber.js +53 -0
  59. package/dist/system/subscribers/code.fix.script.subscriber.js.map +1 -0
  60. package/dist/system/subscribers/index.d.ts +6 -0
  61. package/dist/{auth/jobs → system/subscribers}/index.js +6 -1
  62. package/dist/system/subscribers/index.js.map +1 -0
  63. package/dist/system/subscribers/material.view.subscriber.d.ts +11 -0
  64. package/dist/system/subscribers/material.view.subscriber.js +53 -0
  65. package/dist/system/subscribers/material.view.subscriber.js.map +1 -0
  66. package/dist/system/subscribers/property.subscriber.d.ts +10 -0
  67. package/dist/{auth/subscribers/session.identifier.subscriber.js → system/subscribers/property.subscriber.js} +17 -17
  68. package/dist/system/subscribers/property.subscriber.js.map +1 -0
  69. package/dist/system/subscribers/recurring.query.subscriber.d.ts +11 -0
  70. package/dist/system/subscribers/recurring.query.subscriber.js +53 -0
  71. package/dist/system/subscribers/recurring.query.subscriber.js.map +1 -0
  72. package/dist/system/subscribers/scheduled.event.subscriber.d.ts +11 -0
  73. package/dist/system/subscribers/scheduled.event.subscriber.js +53 -0
  74. package/dist/system/subscribers/scheduled.event.subscriber.js.map +1 -0
  75. package/dist/system/system.module.js +1 -1
  76. package/dist/system/system.module.js.map +1 -1
  77. package/docs/subscribe-for.md +201 -19
  78. package/package.json +1 -1
  79. package/dist/auth/jobs/index.d.ts +0 -1
  80. package/dist/auth/jobs/index.js.map +0 -1
  81. package/dist/auth/jobs/session.identifier.job.d.ts +0 -9
  82. package/dist/auth/jobs/session.identifier.job.js +0 -30
  83. package/dist/auth/jobs/session.identifier.job.js.map +0 -1
  84. package/dist/auth/services/es6.jobs.service.d.ts +0 -8
  85. package/dist/auth/services/es6.jobs.service.js +0 -37
  86. package/dist/auth/services/es6.jobs.service.js.map +0 -1
  87. package/dist/auth/subscribers/index.d.ts +0 -1
  88. package/dist/auth/subscribers/index.js +0 -18
  89. package/dist/auth/subscribers/index.js.map +0 -1
  90. package/dist/auth/subscribers/session.identifier.subscriber.d.ts +0 -12
  91. package/dist/auth/subscribers/session.identifier.subscriber.js.map +0 -1
  92. package/dist/platformUtility/jobs/remote.request.log.job.d.ts +0 -9
  93. package/dist/platformUtility/jobs/remote.request.log.job.js +0 -33
  94. package/dist/platformUtility/jobs/remote.request.log.job.js.map +0 -1
  95. package/dist/system/jobs/client.job.d.ts +0 -12
  96. package/dist/system/jobs/client.job.js +0 -46
  97. package/dist/system/jobs/client.job.js.map +0 -1
  98. package/dist/system/jobs/code.fix.log.job.d.ts +0 -9
  99. package/dist/system/jobs/code.fix.log.job.js +0 -33
  100. package/dist/system/jobs/code.fix.log.job.js.map +0 -1
  101. package/dist/system/jobs/data.log.job.d.ts +0 -9
  102. package/dist/system/jobs/data.log.job.js +0 -33
  103. package/dist/system/jobs/data.log.job.js.map +0 -1
  104. package/dist/system/jobs/executable.script.job.d.ts +0 -9
  105. package/dist/system/jobs/executable.script.job.js +0 -33
  106. package/dist/system/jobs/executable.script.job.js.map +0 -1
  107. package/dist/system/jobs/mail.event.job.d.ts +0 -9
  108. package/dist/system/jobs/mail.event.job.js +0 -33
  109. package/dist/system/jobs/mail.event.job.js.map +0 -1
  110. package/dist/system/jobs/mail.recipient.job.d.ts +0 -9
  111. package/dist/system/jobs/mail.recipient.job.js +0 -33
  112. package/dist/system/jobs/mail.recipient.job.js.map +0 -1
  113. package/dist/system/jobs/mail.validation.job.d.ts +0 -9
  114. package/dist/system/jobs/mail.validation.job.js +0 -31
  115. package/dist/system/jobs/mail.validation.job.js.map +0 -1
  116. package/dist/system/jobs/mobile.validation.job.d.ts +0 -9
  117. package/dist/system/jobs/mobile.validation.job.js +0 -31
  118. package/dist/system/jobs/mobile.validation.job.js.map +0 -1
  119. package/dist/system/jobs/report.sheet.job.d.ts +0 -9
  120. package/dist/system/jobs/report.sheet.job.js +0 -33
  121. package/dist/system/jobs/report.sheet.job.js.map +0 -1
  122. package/dist/system/jobs/sms.message.job.d.ts +0 -9
  123. package/dist/system/jobs/sms.message.job.js +0 -31
  124. package/dist/system/jobs/sms.message.job.js.map +0 -1
@@ -14,5 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./session.identifier.job"), exports);
17
+ __exportStar(require("./client.credential.subscriber"), exports);
18
+ __exportStar(require("./code.fix.script.subscriber"), exports);
19
+ __exportStar(require("./material.view.subscriber"), exports);
20
+ __exportStar(require("./property.subscriber"), exports);
21
+ __exportStar(require("./recurring.query.subscriber"), exports);
22
+ __exportStar(require("./scheduled.event.subscriber"), exports);
18
23
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/system/subscribers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iEAA+C;AAAA,+DAA6C;AAAA,6DAA2C;AAAA,wDAAsC;AAAA,+DAA6C;AAAA,+DAA4C"}
@@ -0,0 +1,11 @@
1
+ import { DataSource, InsertEvent, UpdateEvent } from 'typeorm';
2
+ import { CommonSubscriber } from '../../common/libraries/common.subscriber';
3
+ import { MaterialViewEntity } from '../entities/material.view.entity';
4
+ export declare class MaterialViewSubscriber extends CommonSubscriber<MaterialViewEntity> {
5
+ private readonly dataSource;
6
+ constructor(dataSource: DataSource);
7
+ listenTo(): typeof MaterialViewEntity;
8
+ beforeInsert(event: InsertEvent<MaterialViewEntity>): Promise<void>;
9
+ beforeUpdate(event: UpdateEvent<MaterialViewEntity>): Promise<void>;
10
+ private validateTiming;
11
+ }
@@ -0,0 +1,53 @@
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.MaterialViewSubscriber = void 0;
13
+ const date_fns_1 = require("date-fns");
14
+ const typeorm_1 = require("typeorm");
15
+ const form_exception_1 = require("../../common/exceptions/form.exception");
16
+ const common_subscriber_1 = require("../../common/libraries/common.subscriber");
17
+ const platform_utility_1 = require("../../common/libraries/platform.utility");
18
+ const material_view_entity_1 = require("../entities/material.view.entity");
19
+ let MaterialViewSubscriber = class MaterialViewSubscriber extends common_subscriber_1.CommonSubscriber {
20
+ constructor(dataSource) {
21
+ super();
22
+ this.dataSource = dataSource;
23
+ dataSource.subscribers.push(this);
24
+ }
25
+ listenTo() {
26
+ return material_view_entity_1.MaterialViewEntity;
27
+ }
28
+ async beforeInsert(event) {
29
+ event.entity.attributes = {
30
+ ...event.entity.attributes,
31
+ ...{},
32
+ };
33
+ this.validateTiming(event.entity?.timing);
34
+ if (!event.entity.last_scheduled_time)
35
+ event.entity.last_scheduled_time = (0, date_fns_1.subMinutes)(new Date(), 15);
36
+ }
37
+ async beforeUpdate(event) {
38
+ this.validateTiming(event.entity?.timing);
39
+ if (!event.entity.last_scheduled_time)
40
+ event.entity.last_scheduled_time = (0, date_fns_1.subMinutes)(new Date(), 15);
41
+ }
42
+ validateTiming(timing) {
43
+ if (timing && !platform_utility_1.PlatformUtility.isValidCronExpression(timing)) {
44
+ throw new form_exception_1.FormException({ column: 'timing', err: `Invalid cron expression: ${timing}` });
45
+ }
46
+ }
47
+ };
48
+ exports.MaterialViewSubscriber = MaterialViewSubscriber;
49
+ exports.MaterialViewSubscriber = MaterialViewSubscriber = __decorate([
50
+ (0, typeorm_1.EventSubscriber)(),
51
+ __metadata("design:paramtypes", [typeorm_1.DataSource])
52
+ ], MaterialViewSubscriber);
53
+ //# sourceMappingURL=material.view.subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material.view.subscriber.js","sourceRoot":"","sources":["../../../src/system/subscribers/material.view.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,uCAAsC;AACtC,qCAAgF;AAChF,2EAAuE;AACvE,gFAA4E;AAC5E,8EAA0E;AAC1E,2EAAsE;AAO/D,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,oCAAoC;IAC5E,YAA6B,UAAsB;QAC/C,KAAK,EAAE,CAAC;QADiB,eAAU,GAAV,UAAU,CAAY;QAE/C,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACJ,OAAO,yCAAkB,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAsC;QACrD,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG;YACtB,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU;YAC1B,GAAG,EAAE;SACR,CAAC;QAEF,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB;YAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB,GAAG,IAAA,qBAAU,EAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAsC;QACrD,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB;YAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB,GAAG,IAAA,qBAAU,EAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzG,CAAC;IAEO,cAAc,CAAC,MAAiC;QACpD,IAAI,MAAM,IAAI,CAAC,kCAAe,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,8BAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,4BAA4B,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7F,CAAC;IACL,CAAC;CACJ,CAAA;AAhCY,wDAAsB;iCAAtB,sBAAsB;IADlC,IAAA,yBAAe,GAAE;qCAE2B,oBAAU;GAD1C,sBAAsB,CAgClC"}
@@ -0,0 +1,10 @@
1
+ import { DataSource, InsertEvent, UpdateEvent } from 'typeorm';
2
+ import { CommonSubscriber } from '../../common/libraries/common.subscriber';
3
+ import { PropertyEntity } from '../entities/property.entity';
4
+ export declare class PropertySubscriber extends CommonSubscriber<PropertyEntity> {
5
+ private readonly dataSource;
6
+ constructor(dataSource: DataSource);
7
+ listenTo(): typeof PropertyEntity;
8
+ beforeInsert(event: InsertEvent<PropertyEntity>): Promise<void>;
9
+ beforeUpdate(evt: UpdateEvent<PropertyEntity>): Promise<void>;
10
+ }
@@ -9,32 +9,32 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.SessionIdentifierSubscriber = void 0;
12
+ exports.PropertySubscriber = void 0;
13
13
  const typeorm_1 = require("typeorm");
14
14
  const common_subscriber_1 = require("../../common/libraries/common.subscriber");
15
- const session_identifier_entity_1 = require("../entities/session.identifier.entity");
16
- const session_identifier_job_1 = require("../jobs/session.identifier.job");
17
- let SessionIdentifierSubscriber = class SessionIdentifierSubscriber extends common_subscriber_1.CommonSubscriber {
18
- constructor(dataSource, sessionIdentifierJob) {
15
+ const custom_crypt_1 = require("../../common/libraries/custom.crypt");
16
+ const property_entity_1 = require("../entities/property.entity");
17
+ let PropertySubscriber = class PropertySubscriber extends common_subscriber_1.CommonSubscriber {
18
+ constructor(dataSource) {
19
19
  super();
20
20
  this.dataSource = dataSource;
21
- this.sessionIdentifierJob = sessionIdentifierJob;
22
21
  dataSource.subscribers.push(this);
23
22
  }
24
23
  listenTo() {
25
- return session_identifier_entity_1.SessionIdentifierEntity;
24
+ return property_entity_1.PropertyEntity;
26
25
  }
27
- async afterInsert(evt) {
28
- return this.enqueueDispatch(evt.queryRunner, this.sessionIdentifierJob, this.getEventData(evt));
26
+ async beforeInsert(event) {
27
+ if (event.entity.is_encrypted)
28
+ event.entity.value = custom_crypt_1.CustomCrypt.encrypt(event.entity.value);
29
29
  }
30
- async afterUpdate(evt) {
31
- return this.enqueueDispatch(evt.queryRunner, this.sessionIdentifierJob, this.getEventData(evt));
30
+ async beforeUpdate(evt) {
31
+ if (evt.entity.is_encrypted && evt.entity.value !== evt.databaseEntity.value)
32
+ evt.entity.value = custom_crypt_1.CustomCrypt.encrypt(evt.entity.value);
32
33
  }
33
34
  };
34
- exports.SessionIdentifierSubscriber = SessionIdentifierSubscriber;
35
- exports.SessionIdentifierSubscriber = SessionIdentifierSubscriber = __decorate([
35
+ exports.PropertySubscriber = PropertySubscriber;
36
+ exports.PropertySubscriber = PropertySubscriber = __decorate([
36
37
  (0, typeorm_1.EventSubscriber)(),
37
- __metadata("design:paramtypes", [typeorm_1.DataSource,
38
- session_identifier_job_1.SessionIdentifierJob])
39
- ], SessionIdentifierSubscriber);
40
- //# sourceMappingURL=session.identifier.subscriber.js.map
38
+ __metadata("design:paramtypes", [typeorm_1.DataSource])
39
+ ], PropertySubscriber);
40
+ //# sourceMappingURL=property.subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property.subscriber.js","sourceRoot":"","sources":["../../../src/system/subscribers/property.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAAgF;AAChF,gFAA4E;AAC5E,sEAAkE;AAClE,iEAA6D;AAQtD,IAAM,kBAAkB,GAAxB,MAAM,kBAAmB,SAAQ,oCAAgC;IACpE,YAA6B,UAAsB;QAC/C,KAAK,EAAE,CAAC;QADiB,eAAU,GAAV,UAAU,CAAY;QAE/C,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACJ,OAAO,gCAAc,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAkC;QACjD,IAAI,KAAK,CAAC,MAAM,CAAC,YAAY;YAAE,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,0BAAW,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChG,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,GAAgC;QAC/C,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,GAAG,CAAC,cAAc,CAAC,KAAK;YAAE,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,0BAAW,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3I,CAAC;CACJ,CAAA;AAjBY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,yBAAe,GAAE;qCAE2B,oBAAU;GAD1C,kBAAkB,CAiB9B"}
@@ -0,0 +1,11 @@
1
+ import { DataSource, InsertEvent, UpdateEvent } from 'typeorm';
2
+ import { CommonSubscriber } from '../../common/libraries/common.subscriber';
3
+ import { RecurringQueryEntity } from '../entities/recurring.query.entity';
4
+ export declare class RecurringQuerySubscriber extends CommonSubscriber<RecurringQueryEntity> {
5
+ private readonly dataSource;
6
+ constructor(dataSource: DataSource);
7
+ listenTo(): typeof RecurringQueryEntity;
8
+ beforeInsert(event: InsertEvent<RecurringQueryEntity>): Promise<void>;
9
+ beforeUpdate(event: UpdateEvent<RecurringQueryEntity>): Promise<void>;
10
+ private validateTiming;
11
+ }
@@ -0,0 +1,53 @@
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.RecurringQuerySubscriber = void 0;
13
+ const date_fns_1 = require("date-fns");
14
+ const typeorm_1 = require("typeorm");
15
+ const form_exception_1 = require("../../common/exceptions/form.exception");
16
+ const common_subscriber_1 = require("../../common/libraries/common.subscriber");
17
+ const platform_utility_1 = require("../../common/libraries/platform.utility");
18
+ const recurring_query_entity_1 = require("../entities/recurring.query.entity");
19
+ let RecurringQuerySubscriber = class RecurringQuerySubscriber extends common_subscriber_1.CommonSubscriber {
20
+ constructor(dataSource) {
21
+ super();
22
+ this.dataSource = dataSource;
23
+ dataSource.subscribers.push(this);
24
+ }
25
+ listenTo() {
26
+ return recurring_query_entity_1.RecurringQueryEntity;
27
+ }
28
+ async beforeInsert(event) {
29
+ event.entity.attributes = {
30
+ ...event.entity.attributes,
31
+ ...{},
32
+ };
33
+ this.validateTiming(event.entity?.timing);
34
+ if (!event.entity.last_scheduled_time)
35
+ event.entity.last_scheduled_time = (0, date_fns_1.subMinutes)(new Date(), 15);
36
+ }
37
+ async beforeUpdate(event) {
38
+ this.validateTiming(event.entity?.timing);
39
+ if (!event.entity.last_scheduled_time)
40
+ event.entity.last_scheduled_time = (0, date_fns_1.subMinutes)(new Date(), 15);
41
+ }
42
+ validateTiming(timing) {
43
+ if (timing && !platform_utility_1.PlatformUtility.isValidCronExpression(timing)) {
44
+ throw new form_exception_1.FormException({ column: 'timing', err: `Invalid cron expression: ${timing}` });
45
+ }
46
+ }
47
+ };
48
+ exports.RecurringQuerySubscriber = RecurringQuerySubscriber;
49
+ exports.RecurringQuerySubscriber = RecurringQuerySubscriber = __decorate([
50
+ (0, typeorm_1.EventSubscriber)(),
51
+ __metadata("design:paramtypes", [typeorm_1.DataSource])
52
+ ], RecurringQuerySubscriber);
53
+ //# sourceMappingURL=recurring.query.subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring.query.subscriber.js","sourceRoot":"","sources":["../../../src/system/subscribers/recurring.query.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,uCAAsC;AACtC,qCAAgF;AAChF,2EAAuE;AACvE,gFAA4E;AAC5E,8EAA0E;AAC1E,+EAA0E;AAOnE,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,oCAAsC;IAChF,YAA6B,UAAsB;QAC/C,KAAK,EAAE,CAAC;QADiB,eAAU,GAAV,UAAU,CAAY;QAE/C,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACJ,OAAO,6CAAoB,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAwC;QACvD,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG;YACtB,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU;YAC1B,GAAG,EAAE;SACR,CAAC;QAEF,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB;YAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB,GAAG,IAAA,qBAAU,EAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAwC;QACvD,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB;YAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB,GAAG,IAAA,qBAAU,EAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzG,CAAC;IAEO,cAAc,CAAC,MAAiC;QACpD,IAAI,MAAM,IAAI,CAAC,kCAAe,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,8BAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,4BAA4B,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7F,CAAC;IACL,CAAC;CACJ,CAAA;AAhCY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,yBAAe,GAAE;qCAE2B,oBAAU;GAD1C,wBAAwB,CAgCpC"}
@@ -0,0 +1,11 @@
1
+ import { DataSource, InsertEvent, UpdateEvent } from 'typeorm';
2
+ import { CommonSubscriber } from '../../common/libraries/common.subscriber';
3
+ import { ScheduledEventEntity } from '../entities/scheduled.event.entity';
4
+ export declare class ScheduledEventSubscriber extends CommonSubscriber<ScheduledEventEntity> {
5
+ private readonly dataSource;
6
+ constructor(dataSource: DataSource);
7
+ listenTo(): typeof ScheduledEventEntity;
8
+ beforeInsert(event: InsertEvent<ScheduledEventEntity>): Promise<void>;
9
+ beforeUpdate(event: UpdateEvent<ScheduledEventEntity>): Promise<void>;
10
+ private validateTiming;
11
+ }
@@ -0,0 +1,53 @@
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.ScheduledEventSubscriber = void 0;
13
+ const date_fns_1 = require("date-fns");
14
+ const typeorm_1 = require("typeorm");
15
+ const form_exception_1 = require("../../common/exceptions/form.exception");
16
+ const common_subscriber_1 = require("../../common/libraries/common.subscriber");
17
+ const platform_utility_1 = require("../../common/libraries/platform.utility");
18
+ const scheduled_event_entity_1 = require("../entities/scheduled.event.entity");
19
+ let ScheduledEventSubscriber = class ScheduledEventSubscriber extends common_subscriber_1.CommonSubscriber {
20
+ constructor(dataSource) {
21
+ super();
22
+ this.dataSource = dataSource;
23
+ dataSource.subscribers.push(this);
24
+ }
25
+ listenTo() {
26
+ return scheduled_event_entity_1.ScheduledEventEntity;
27
+ }
28
+ async beforeInsert(event) {
29
+ event.entity.attributes = {
30
+ ...event.entity.attributes,
31
+ ...{},
32
+ };
33
+ this.validateTiming(event.entity?.timing);
34
+ if (!event.entity?.last_scheduled_time)
35
+ event.entity.last_scheduled_time = (0, date_fns_1.subMinutes)(new Date(), 15);
36
+ }
37
+ async beforeUpdate(event) {
38
+ this.validateTiming(event.entity?.timing);
39
+ if (!event.entity?.last_scheduled_time)
40
+ event.entity.last_scheduled_time = (0, date_fns_1.subMinutes)(new Date(), 15);
41
+ }
42
+ validateTiming(timing) {
43
+ if (timing && !platform_utility_1.PlatformUtility.isValidCronExpression(timing)) {
44
+ throw new form_exception_1.FormException({ column: 'timing', err: `Invalid cron expression: ${timing}` });
45
+ }
46
+ }
47
+ };
48
+ exports.ScheduledEventSubscriber = ScheduledEventSubscriber;
49
+ exports.ScheduledEventSubscriber = ScheduledEventSubscriber = __decorate([
50
+ (0, typeorm_1.EventSubscriber)(),
51
+ __metadata("design:paramtypes", [typeorm_1.DataSource])
52
+ ], ScheduledEventSubscriber);
53
+ //# sourceMappingURL=scheduled.event.subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduled.event.subscriber.js","sourceRoot":"","sources":["../../../src/system/subscribers/scheduled.event.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,uCAAsC;AACtC,qCAAgF;AAChF,2EAAuE;AACvE,gFAA4E;AAC5E,8EAA0E;AAC1E,+EAA0E;AAOnE,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,oCAAsC;IAChF,YAA6B,UAAsB;QAC/C,KAAK,EAAE,CAAC;QADiB,eAAU,GAAV,UAAU,CAAY;QAE/C,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACJ,OAAO,6CAAoB,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAwC;QACvD,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG;YACtB,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU;YAC1B,GAAG,EAAE;SACR,CAAC;QAEF,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,mBAAmB;YAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB,GAAG,IAAA,qBAAU,EAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1G,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAwC;QACvD,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,mBAAmB;YAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB,GAAG,IAAA,qBAAU,EAAC,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1G,CAAC;IAEO,cAAc,CAAC,MAAiC;QACpD,IAAI,MAAM,IAAI,CAAC,kCAAe,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,8BAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,4BAA4B,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7F,CAAC;IACL,CAAC;CACJ,CAAA;AAhCY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,yBAAe,GAAE;qCAE2B,oBAAU;GAD1C,wBAAwB,CAgCpC"}
@@ -22,7 +22,7 @@ exports.SystemModule = SystemModule = __decorate([
22
22
  (0, common_1.Module)({
23
23
  imports: [typeorm_1.TypeOrmModule.forFeature(es6_classes_1.default.entities), (0, common_1.forwardRef)(() => auth_module_1.AuthModule), (0, common_1.forwardRef)(() => platform_utility_module_1.PlatformUtilityModule)],
24
24
  controllers: es6_classes_1.default.controllers,
25
- providers: [...es6_classes_1.default.services, ...es6_classes_1.default.jobs],
25
+ providers: [...es6_classes_1.default.services, ...es6_classes_1.default.subscribers, ...es6_classes_1.default.jobs],
26
26
  exports: [...es6_classes_1.default.services, ...es6_classes_1.default.jobs],
27
27
  })
28
28
  ], SystemModule);
@@ -1 +1 @@
1
- {"version":3,"file":"system.module.js","sourceRoot":"","sources":["../../src/system/system.module.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAoD;AACpD,qDAAiD;AACjD,wFAAmF;AACnF,gEAAuC;AACvC,6CAAgD;AAQzC,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IANxB,IAAA,eAAM,EAAC;QACJ,OAAO,EAAE,CAAC,uBAAa,CAAC,UAAU,CAAC,qBAAU,CAAC,QAAQ,CAAC,EAAE,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,wBAAU,CAAC,EAAE,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,+CAAqB,CAAC,CAAC;QAC/H,WAAW,EAAE,qBAAU,CAAC,WAAW;QACnC,SAAS,EAAE,CAAC,GAAG,qBAAU,CAAC,QAAQ,EAAE,GAAG,qBAAU,CAAC,IAAI,CAAC;QACvD,OAAO,EAAE,CAAC,GAAG,qBAAU,CAAC,QAAQ,EAAE,GAAG,qBAAU,CAAC,IAAI,CAAC;KACxD,CAAC;GACW,YAAY,CAAG"}
1
+ {"version":3,"file":"system.module.js","sourceRoot":"","sources":["../../src/system/system.module.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAoD;AACpD,qDAAiD;AACjD,wFAAmF;AACnF,gEAAuC;AACvC,6CAAgD;AAQzC,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IANxB,IAAA,eAAM,EAAC;QACJ,OAAO,EAAE,CAAC,uBAAa,CAAC,UAAU,CAAC,qBAAU,CAAC,QAAQ,CAAC,EAAE,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,wBAAU,CAAC,EAAE,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,+CAAqB,CAAC,CAAC;QAC/H,WAAW,EAAE,qBAAU,CAAC,WAAW;QACnC,SAAS,EAAE,CAAC,GAAG,qBAAU,CAAC,QAAQ,EAAE,GAAG,qBAAU,CAAC,WAAW,EAAE,GAAG,qBAAU,CAAC,IAAI,CAAC;QAClF,OAAO,EAAE,CAAC,GAAG,qBAAU,CAAC,QAAQ,EAAE,GAAG,qBAAU,CAAC,IAAI,CAAC;KACxD,CAAC;GACW,YAAY,CAAG"}
@@ -1,39 +1,221 @@
1
- # `@SubscribeFor`multi-job entity bindings
1
+ # Jobs & subscribers guide for consuming apps
2
2
 
3
- `@SubscribeFor(EntityClass)` binds a `CommonJob` (or subclass) to TypeORM
4
- insert/update events for that entity. `DispatcherSubscriber` routes those
5
- events; you do **not** need a standalone `*.subscriber.ts` for pure
6
- after-persist side effects.
3
+ This package (`@servicelabsco/nestjs-utility-services`, **NU**) owns many
4
+ TypeORM entities and some platform jobs. Downstream apps (Expense, Access,
5
+ etc.) often need extra side effects or pre-persist mutations on those
6
+ entities or on their own entities.
7
7
 
8
- ## Multiple jobs per entity
8
+ This doc is the **contract** for how to do that without fighting NU’s
9
+ dispatcher or double-enqueuing work.
9
10
 
10
- More than one job may decorate the same entity. Typical pattern: keep the
11
- platform job (e.g. `DocumentJob`) and add an app-local job for tenant-specific
12
- side effects.
11
+ ---
12
+
13
+ ## Mental model
14
+
15
+ | When | Where it lives | Mechanism |
16
+ | --- | --- | --- |
17
+ | Mutate the row **before** it hits the DB (hash secret, encrypt, validate cron, stamp defaults) | Standalone `*.subscriber.ts` extending `CommonSubscriber` | TypeORM `beforeInsert` / `beforeUpdate` |
18
+ | Run **after** the row is saved (cache refresh, schedule event, sync counts, app-local side effects) | `CommonJob` with `@SubscribeFor(Entity)` | `DispatcherSubscriber` → `delayedDispatch` → `handle(DatabaseEventDto)` |
19
+ | Ad-hoc / cron / webhook work **not** tied to an entity save | Plain `CommonJob` (no `@SubscribeFor`) | Call `job.dispatch(...)` / `delayedDispatch(...)` yourself |
20
+
21
+ **Jobs are post-persist queue work. Subscribers own pre-persist mutation.**
22
+ `DispatcherSubscriber` never calls job `beforeInsert` / `beforeUpdate`.
23
+
24
+ ```
25
+ entity.save()
26
+
27
+ ├─ beforeInsert / beforeUpdate → your CommonSubscriber (sync, in-transaction)
28
+ ├─ SQL INSERT / UPDATE
29
+ └─ afterInsert / afterUpdate → DispatcherSubscriber
30
+ └─ every @SubscribeFor(Entity) job
31
+ delayedDispatch → BullMQ → handle()
32
+ ```
33
+
34
+ ---
35
+
36
+ ## What consuming apps should do
37
+
38
+ ### 1. Extra side effects on an NU entity (most common)
39
+
40
+ NU already ships a job for many entities (e.g. `DocumentJob`, `PropertyJob`).
41
+ You usually want **another** job for product-specific work — do **not** fork or
42
+ wrap the platform job.
13
43
 
14
44
  ```ts
15
45
  import { Injectable } from '@nestjs/common';
16
- import { CommonJob, DatabaseEventDto, DocumentEntity, SubscribeFor } from '@servicelabsco/nestjs-utility-services';
46
+ import {
47
+ CommonJob,
48
+ DatabaseEventDto,
49
+ DocumentEntity,
50
+ SubscribeFor,
51
+ } from '@servicelabsco/nestjs-utility-services';
17
52
 
18
53
  @SubscribeFor(DocumentEntity)
19
54
  @Injectable()
20
55
  export class LocalDocumentJob extends CommonJob {
56
+ constructor(protected readonly queueService: QueueService /* + your deps */) {
57
+ super('<unique-32-char-md5-hash>'); // must be unique across the whole fleet
58
+ }
59
+
21
60
  async handle(evt: DatabaseEventDto<DocumentEntity>) {
22
- // app-local side effects — do not wrap DocumentJob.handle
61
+ // tenant / product side effects only
62
+ // DocumentJob still runs separately via the same dispatcher fan-out
63
+ }
64
+ }
65
+ ```
66
+
67
+ **Register the job** as a Nest provider in your app module (or your module’s
68
+ `es6.classes.ts` `jobs` array). If it is not in DI, boot fails when
69
+ `DispatcherSubscriber` cannot resolve it.
70
+
71
+ **Worker:** the process with `BULL_QUEUE_WORKER=true` must load the module that
72
+ provides your job, or the queue will not find a handler for that hash.
73
+
74
+ ### 2. Pre-persist hooks on an NU (or local) entity
75
+
76
+ Put them on a standalone subscriber. Do **not** put `beforeInsert` /
77
+ `beforeUpdate` on a `@SubscribeFor` job — they will never run via the
78
+ dispatcher.
79
+
80
+ ```ts
81
+ import { DataSource, EventSubscriber, InsertEvent, UpdateEvent } from 'typeorm';
82
+ import { CommonSubscriber } from '@servicelabsco/nestjs-utility-services';
83
+
84
+ @EventSubscriber()
85
+ export class LocalCredentialSubscriber extends CommonSubscriber<YourEntity> {
86
+ constructor(private readonly dataSource: DataSource) {
87
+ super();
88
+ dataSource.subscribers.push(this); // required so TypeORM sees the instance
89
+ }
90
+
91
+ listenTo() {
92
+ return YourEntity;
93
+ }
94
+
95
+ async beforeInsert(event: InsertEvent<YourEntity>) {
96
+ event.entity.secret = hash(event.entity.secret);
97
+ }
98
+
99
+ async beforeUpdate(event: UpdateEvent<YourEntity>) {
100
+ // …
23
101
  }
24
102
  }
25
103
  ```
26
104
 
27
- Register `LocalDocumentJob` as a Nest provider (your module’s `es6.classes` /
28
- providers). Each job keeps its own BullMQ hash / queue identity.
105
+ Register the subscriber in your module `providers` (or `es6.classes.subscribers`).
106
+
107
+ Coexistence with NU’s `@SubscribeFor` job on the same entity is **allowed**.
108
+ Boot will not throw.
109
+
110
+ ### 3. Both mutation + post-persist for the same entity
111
+
112
+ Use **both** files: subscriber for before*, job with `@SubscribeFor` for after*.
113
+
114
+ ```ts
115
+ // ✅ subscriber — mutation only
116
+ async beforeInsert(e) { e.entity.x = normalize(e.entity.x); }
117
+
118
+ // ✅ job — @SubscribeFor(Entity), handle() only
119
+ async handle(evt: DatabaseEventDto<Entity>) { await this.refreshCache(evt.entity); }
120
+ ```
121
+
122
+ **Never** call `this.someSubscribeForJob.delayedDispatch(...)` from the
123
+ standalone subscriber for a job that already has `@SubscribeFor` — that
124
+ enqueues the same work twice.
125
+
126
+ ### 4. Your own entity (not from NU)
127
+
128
+ Same rules:
129
+
130
+ - Need queue work on insert/update → `@SubscribeFor(YourEntity)` on a `CommonJob`.
131
+ - Need before* → standalone `CommonSubscriber`.
132
+ - Need neither → no subscriber and no `@SubscribeFor` (plain services are enough).
133
+
134
+ Do **not** create empty jobs that only `return evt.entity` — they still enqueue
135
+ Bull work on every save.
136
+
137
+ ### 5. Manual / scheduled jobs (no entity binding)
138
+
139
+ Omit `@SubscribeFor`. Dispatch explicitly:
140
+
141
+ ```ts
142
+ await this.myJob.dispatch(payload);
143
+ await this.myJob.delayedDispatch(payload, 5_000);
144
+ ```
145
+
146
+ Keep a stable hash in `super('…')` and register the job in DI + worker like any
147
+ other job.
148
+
149
+ ---
150
+
151
+ ## Wiring checklist (consuming app)
29
152
 
30
- ### Behaviour
153
+ 1. **Import NU modules** your app needs (`AuthModule`, `SystemModule`,
154
+ `PlatformUtilityModule`, …) so `DispatcherSubscriber` and platform jobs load.
155
+ 2. **Provide** every `@SubscribeFor` job and every standalone subscriber in a
156
+ Nest module that the API **and** worker import.
157
+ 3. **Worker** (`BULL_QUEUE_WORKER=true`) must resolve the same job providers;
158
+ otherwise jobs enqueue but never run.
159
+ 4. **Hash** (`super('…')`) must be unique — collisions break `PlatformUtility.getJob`
160
+ / Bull routing.
161
+ 5. Prefer your app’s `es6.classes.ts` pattern if you use `slnu syncClassess`;
162
+ otherwise list classes in `@Module({ providers, exports })`.
163
+
164
+ ---
165
+
166
+ ## Behaviour reference
31
167
 
32
168
  | Hook | Behaviour |
33
169
  | --- | --- |
34
- | `afterInsert` / `afterUpdate` | Fan-out to **all** bound jobs, registration order (sequential enqueue). |
35
- | `beforeInsert` / `beforeUpdate` | **First** registered job only (single owner for pre-persist mutation). |
36
- | Standalone `CommonSubscriber` on the same entity | Still **throws at boot** — pick `@SubscribeFor` **or** a standalone subscriber, not both. |
170
+ | `afterInsert` / `afterUpdate` | Fan-out to **all** `@SubscribeFor` jobs for that entity (registration order, sequential enqueue). |
171
+ | `beforeInsert` / `beforeUpdate` | **Only** on standalone `CommonSubscriber`s. Never routed to jobs. |
172
+ | Standalone subscriber + `@SubscribeFor` | Allowed. Mutation on subscriber; post-persist via dispatcher. |
173
+ | Transactional saves | Dispatch is buffered until commit (see `CommonSubscriber` / dispatcher); rolled back on rollback. |
174
+
175
+ Platform modules usually register before the app, so NU’s job is typically
176
+ **first** when multiple jobs bind the same entity.
177
+
178
+ ---
179
+
180
+ ## Anti-patterns
181
+
182
+ | Don’t | Do instead |
183
+ | --- | --- |
184
+ | Put `beforeInsert` on a `@SubscribeFor` job | Standalone `CommonSubscriber` |
185
+ | `delayedDispatch` the same `@SubscribeFor` job from a subscriber | Let `DispatcherSubscriber` enqueue once |
186
+ | Empty job (`handle` no-op / `return evt.entity`) “for later” | Omit the job until you have real work |
187
+ | Subclass / re-export NU’s job just to add a line of logic | Second `@SubscribeFor` job in your app |
188
+ | Forget to register the job on the worker | Import the same module in `worker` bootstrap |
189
+ | Hand-roll a pass-through subscriber that only calls `entityJob.delayedDispatch` | `@SubscribeFor` on the job |
190
+
191
+ ---
37
192
 
38
- Platform modules usually load before the app, so NU’s job is typically first in
39
- the list when both bind the same entity.
193
+ ## What NU already owns (do not reimplement)
194
+
195
+ Examples of platform post-persist jobs (non-exhaustive): document/comment count
196
+ sync, property cache refresh, client-credential cache, credential IP cache,
197
+ column/relationship mappers, user-group ACL sync, scheduled / recurring /
198
+ material-view / code-fix scheduling.
199
+
200
+ Examples of platform **pre-persist** subscribers: property encryption, client
201
+ credential hashing, cron validation + defaults for scheduled events, recurring
202
+ queries, material views, code-fix scripts.
203
+
204
+ If NU already does the work you need, call its services or rely on its job —
205
+ don’t duplicate with another empty or overlapping job.
206
+
207
+ ---
208
+
209
+ ## Quick decision tree
210
+
211
+ ```
212
+ Need something on entity save?
213
+ ├─ Change fields before SQL?
214
+ │ └─ CommonSubscriber + beforeInsert/beforeUpdate
215
+ ├─ Side effects after SQL?
216
+ │ ├─ Already covered by an NU @SubscribeFor job?
217
+ │ │ └─ Add your own @SubscribeFor job (fan-out) if product-specific
218
+ │ └─ Else @SubscribeFor on a new CommonJob
219
+ └─ Not tied to a save?
220
+ └─ CommonJob without @SubscribeFor; dispatch manually
221
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicelabsco/nestjs-utility-services",
3
- "version": "3.0.4",
3
+ "version": "3.0.6",
4
4
  "description": "NestJS generic packages to support development",
5
5
  "author": "Hemant Kumar Sah <hemantanshu@gmail.com>",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- export * from './session.identifier.job';
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/jobs/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2DAAwC"}
@@ -1,9 +0,0 @@
1
- import { DatabaseEventDto } from '../../common/dtos/database.event.dto';
2
- import { CommonJob } from '../../common/libraries/common.job';
3
- import { QueueService } from '../../platformUtility/services/queue.service';
4
- import { SessionIdentifierEntity } from '../entities/session.identifier.entity';
5
- export declare class SessionIdentifierJob extends CommonJob {
6
- protected readonly queueService: QueueService;
7
- constructor(queueService: QueueService);
8
- handle(evt: DatabaseEventDto<SessionIdentifierEntity>): Promise<SessionIdentifierEntity>;
9
- }
@@ -1,30 +0,0 @@
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.SessionIdentifierJob = void 0;
13
- const common_1 = require("@nestjs/common");
14
- const common_job_1 = require("../../common/libraries/common.job");
15
- const queue_service_1 = require("../../platformUtility/services/queue.service");
16
- let SessionIdentifierJob = class SessionIdentifierJob extends common_job_1.CommonJob {
17
- constructor(queueService) {
18
- super('29692aaae7ba9e4217568e6c4ba3b36c');
19
- this.queueService = queueService;
20
- }
21
- async handle(evt) {
22
- return evt.entity;
23
- }
24
- };
25
- exports.SessionIdentifierJob = SessionIdentifierJob;
26
- exports.SessionIdentifierJob = SessionIdentifierJob = __decorate([
27
- (0, common_1.Injectable)(),
28
- __metadata("design:paramtypes", [queue_service_1.QueueService])
29
- ], SessionIdentifierJob);
30
- //# sourceMappingURL=session.identifier.job.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session.identifier.job.js","sourceRoot":"","sources":["../../../src/auth/jobs/session.identifier.job.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,kEAA8D;AAC9D,gFAA4E;AAGrE,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,sBAAS;IAC/C,YAA+B,YAA0B;QACrD,KAAK,CAAC,kCAAkC,CAAC,CAAC;QADf,iBAAY,GAAZ,YAAY,CAAc;IAEzD,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,GAA8C;QACvD,OAAO,GAAG,CAAC,MAAM,CAAC;IACtB,CAAC;CACJ,CAAA;AAPY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;qCAEoC,4BAAY;GADhD,oBAAoB,CAOhC"}
@@ -1,8 +0,0 @@
1
- import { SessionIdentifierJob } from '../jobs/session.identifier.job';
2
- export declare class Es6JobsService {
3
- private readonly sessionIdentifierJob;
4
- private jobs;
5
- constructor(sessionIdentifierJob: SessionIdentifierJob);
6
- alignJobs(): void;
7
- setJobs(): void;
8
- }