@rytass/bpm-core-nestjs-module 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +2 -0
  3. package/package.json +10 -3
  4. package/src/index.d.ts +1 -0
  5. package/src/index.js +1 -0
  6. package/src/index.js.map +1 -1
  7. package/src/lib/bpm/bpm-root.module.d.ts +18 -0
  8. package/src/lib/bpm/bpm-root.module.js +8 -0
  9. package/src/lib/bpm/bpm-root.module.js.map +1 -1
  10. package/src/lib/calendar/business-calendar.provider.d.ts +11 -0
  11. package/src/lib/calendar/business-calendar.provider.js +20 -0
  12. package/src/lib/calendar/business-calendar.provider.js.map +1 -0
  13. package/src/lib/calendar/business-calendar.token.d.ts +38 -0
  14. package/src/lib/calendar/business-calendar.token.js +5 -0
  15. package/src/lib/calendar/business-calendar.token.js.map +1 -0
  16. package/src/lib/calendar/calendar.module.d.ts +18 -0
  17. package/src/lib/calendar/calendar.module.js +32 -0
  18. package/src/lib/calendar/calendar.module.js.map +1 -0
  19. package/src/lib/calendar/index.d.ts +5 -0
  20. package/src/lib/calendar/index.js +9 -0
  21. package/src/lib/calendar/index.js.map +1 -0
  22. package/src/lib/calendar/sla-schedule.service.d.ts +33 -0
  23. package/src/lib/calendar/sla-schedule.service.js +94 -0
  24. package/src/lib/calendar/sla-schedule.service.js.map +1 -0
  25. package/src/lib/calendar/weekday-business-calendar.d.ts +15 -0
  26. package/src/lib/calendar/weekday-business-calendar.js +28 -0
  27. package/src/lib/calendar/weekday-business-calendar.js.map +1 -0
  28. package/src/lib/common/iso-duration.d.ts +11 -0
  29. package/src/lib/common/iso-duration.js +13 -4
  30. package/src/lib/common/iso-duration.js.map +1 -1
  31. package/src/lib/notification/notification-options.d.ts +10 -0
  32. package/src/lib/notification/notification-options.js +19 -0
  33. package/src/lib/notification/notification-options.js.map +1 -1
  34. package/src/lib/notification/notification.enums.d.ts +13 -0
  35. package/src/lib/notification/notification.enums.js +14 -1
  36. package/src/lib/notification/notification.enums.js.map +1 -1
  37. package/src/lib/notification/notification.service.d.ts +8 -0
  38. package/src/lib/notification/notification.service.js +19 -1
  39. package/src/lib/notification/notification.service.js.map +1 -1
  40. package/src/lib/template/workflow-definition.validator.js +75 -1
  41. package/src/lib/template/workflow-definition.validator.js.map +1 -1
  42. package/src/lib/workflow-engine/workflow-engine.service.d.ts +20 -2
  43. package/src/lib/workflow-engine/workflow-engine.service.js +35 -10
  44. package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
  45. package/src/lib/workflow-engine/workflow-engine.tokens.d.ts +2 -1
  46. package/src/lib/workflow-engine/workflow-engine.tokens.js.map +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 0.7.0 (2026-08-10)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **bpm-core:** lint the new SLA and return-behaviour node fields ([f10c0bb](https://github.com/Rytass/BPMCore/commit/f10c0bb))
6
+ - **bpm-core:** enforce required return comments ([6cb288f](https://github.com/Rytass/BPMCore/commit/6cb288f))
7
+ - **bpm-core:** resolve task SLA due dates through a host business calendar ([3cb9d4d](https://github.com/Rytass/BPMCore/commit/3cb9d4d))
8
+
9
+ ### 🩹 Fixes
10
+
11
+ - **bpm-core:** stop SLA escalation from walking the whole management chain ([f7e4669](https://github.com/Rytass/BPMCore/commit/f7e4669))
12
+
13
+ ### ❤️ Thank You
14
+
15
+ - Chia Yu Pai @fantasywind
16
+ - Claude Opus 5 (1M context)
17
+
1
18
  # Changelog
2
19
 
3
20
  All notable changes to `@rytass/bpm-core-nestjs-module` are documented in this
package/README.md CHANGED
@@ -811,6 +811,7 @@ BPMRootModule.forRootAsync({
811
811
  | `memberResolverProvider` | required | Provider for `BPM_MEMBER_RESOLVER`. |
812
812
  | `attachmentStorageProvider` | local `.storage/attachments` | Host-provided `@rytass/storages` adapter. |
813
813
  | `workflowServiceTaskDispatcherProvider` | built-in `fetch` dispatcher | Host provider for executable workflow `WEBHOOK` service tasks. |
814
+ | `businessCalendarProvider` | Monday–Friday calendar | Host provider for `BPM_BUSINESS_CALENDAR`, used by `BUSINESS_DAY` SLAs. BPMCore ships no holiday data. |
814
815
  | `attachmentRoutePrefix` | `/attachments` | Drives both the BPM signed URL path and the Nest controller mount path for `AttachmentController`. Must be set at module wiring time (see "Attachment Storage" below). |
815
816
  | `attachmentStorageProviderId` | `local` | Value stored on attachment metadata for the active adapter. |
816
817
  | `attachmentPublicBaseUrl` | `http://localhost:17603` | Public base URL for signed attachment URLs. |
@@ -835,6 +836,7 @@ BPMRootModule.forRootAsync({
835
836
  | `notificationDeliveryRetryBaseDelayMs` | `60000` | Base retry delay multiplied by attempt count. |
836
837
  | `notificationSlaSchedulerEnabled` | `false` | Runs automatic SLA scan loop in this process. |
837
838
  | `notificationSlaScanIntervalMs` | `60000` | SLA scheduler interval. |
839
+ | `notificationSlaBusinessCalendarTimeZone` | `UTC` | IANA zone for the built-in weekday calendar. Ignored when `businessCalendarProvider` is set. |
838
840
  | `notificationSlaTimeoutRemindEnabled` | `true` | Enables SLA timeout `REMIND`. |
839
841
  | `notificationSlaTimeoutAutoApproveEnabled` | `false` | Enables SLA timeout `AUTO_APPROVE`. |
840
842
  | `notificationSlaTimeoutEscalateEnabled` | `false` | Enables SLA timeout `ESCALATE`. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rytass/bpm-core-nestjs-module",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Embeddable NestJS BPM approval workflow module: workflow engine, approval templates, forms, organization/member contracts, attachments, signatures, notifications, delegation, and TypeORM migrations.",
5
5
  "keywords": [
6
6
  "bpm",
@@ -42,6 +42,9 @@
42
42
  "bpm-auth": [
43
43
  "./src/lib/bpm-auth/index.d.ts"
44
44
  ],
45
+ "calendar": [
46
+ "./src/lib/calendar/index.d.ts"
47
+ ],
45
48
  "condition": [
46
49
  "./src/lib/condition/index.d.ts"
47
50
  ],
@@ -91,6 +94,10 @@
91
94
  "types": "./src/lib/bpm-auth/index.d.ts",
92
95
  "default": "./src/lib/bpm-auth/index.js"
93
96
  },
97
+ "./calendar": {
98
+ "types": "./src/lib/calendar/index.d.ts",
99
+ "default": "./src/lib/calendar/index.js"
100
+ },
94
101
  "./database": {
95
102
  "types": "./src/lib/database/index.d.ts",
96
103
  "default": "./src/lib/database/index.js"
@@ -141,8 +148,8 @@
141
148
  "@nestjs/core": "^11.0.0",
142
149
  "@nestjs/graphql": "^13.4.0",
143
150
  "@nestjs/typeorm": "^11.0.1",
144
- "@rytass/bpm-core-shared": "^0.6.0",
145
- "@rytass/secret-adapter-vault-nestjs": "^0.4.5 || ^0.5.0",
151
+ "@rytass/bpm-core-shared": "^0.7.0",
152
+ "@rytass/secret-adapter-vault-nestjs": "^0.4.5 || ^0.5.0 || ^0.6.0",
146
153
  "express": "^4.0.0 || ^5.0.0",
147
154
  "graphql": "^16.0.0",
148
155
  "reflect-metadata": "^0.1.13 || ^0.2.0",
package/src/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './lib/attachment';
2
2
  export * from './lib/bpm';
3
3
  export * from './lib/bpm-auth';
4
+ export * from './lib/calendar';
4
5
  export * from './lib/common';
5
6
  export * from './lib/condition';
6
7
  export * from './lib/database';
package/src/index.js CHANGED
@@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./lib/attachment"), exports);
5
5
  tslib_1.__exportStar(require("./lib/bpm"), exports);
6
6
  tslib_1.__exportStar(require("./lib/bpm-auth"), exports);
7
+ tslib_1.__exportStar(require("./lib/calendar"), exports);
7
8
  tslib_1.__exportStar(require("./lib/common"), exports);
8
9
  tslib_1.__exportStar(require("./lib/condition"), exports);
9
10
  tslib_1.__exportStar(require("./lib/database"), exports);
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/bpm-core/src/index.ts"],"names":[],"mappings":";;;AAAA,2DAAiC;AACjC,oDAA0B;AAC1B,yDAA+B;AAC/B,uDAA6B;AAC7B,0DAAgC;AAChC,yDAA+B;AAC/B,2DAAiC;AACjC,qDAA2B;AAC3B,yDAA+B;AAC/B,6DAAmC;AACnC,6DAAmC;AACnC,0DAAgC;AAChC,yDAA+B;AAC/B,gEAAsC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/bpm-core/src/index.ts"],"names":[],"mappings":";;;AAAA,2DAAiC;AACjC,oDAA0B;AAC1B,yDAA+B;AAC/B,yDAA+B;AAC/B,uDAA6B;AAC7B,0DAAgC;AAChC,yDAA+B;AAC/B,2DAAiC;AACjC,qDAA2B;AAC3B,yDAA+B;AAC/B,6DAAmC;AACnC,6DAAmC;AACnC,0DAAgC;AAChC,yDAA+B;AAC/B,gEAAsC"}
@@ -3,6 +3,7 @@ import { ModuleMetadata } from '@nestjs/common/interfaces';
3
3
  import { BPMRootAttachmentOptions } from '../attachment/attachment-options';
4
4
  import { AttachmentStorage } from '../attachment/attachment-storage.token';
5
5
  import { BPMAuthModuleOptions } from '../bpm-auth/bpm-auth.options';
6
+ import { BPMBusinessCalendar } from '../calendar/business-calendar.token';
6
7
  import { BPMRootIdentityOptions } from '../identity/identity-options';
7
8
  import { BPMMemberResolver } from '../identity/member-resolver.interface';
8
9
  import { BPMRootNotificationOptions } from '../notification/notification-options';
@@ -27,6 +28,16 @@ export interface BPMRootModuleOptions extends Pick<ModuleMetadata, 'imports'>, B
27
28
  * operations that require authentication will not receive a host session.
28
29
  */
29
30
  readonly authContextFactory?: BPMAuthModuleOptions['contextFactory'];
31
+ /**
32
+ * Host-provided business calendar used by workflow nodes whose SLA opts into
33
+ * `BUSINESS_DAY`.
34
+ *
35
+ * BPMCore ships no national holiday data. When omitted, BPM falls back to a
36
+ * Monday–Friday calendar (see `notificationSlaBusinessCalendarTimeZone`);
37
+ * hosts that need national holidays or make-up working days register their
38
+ * own `BPM_BUSINESS_CALENDAR` provider here.
39
+ */
40
+ readonly businessCalendarProvider?: Provider<BPMBusinessCalendar>;
30
41
  /**
31
42
  * Host-provided member resolver provider.
32
43
  *
@@ -72,6 +83,13 @@ export interface BPMRootModuleAsyncOptions extends Pick<ModuleMetadata, 'imports
72
83
  * use a Nest provider with `useFactory` / `inject` here.
73
84
  */
74
85
  readonly attachmentStorageProvider?: Provider<AttachmentStorage>;
86
+ /**
87
+ * Host-provided business calendar for `BUSINESS_DAY` SLAs.
88
+ *
89
+ * This provider is static at module wiring time. If secrets or a repository
90
+ * are required, use a Nest provider with `useFactory` / `inject` here.
91
+ */
92
+ readonly businessCalendarProvider?: Provider<BPMBusinessCalendar>;
75
93
  /**
76
94
  * Providers injected into `useFactory`.
77
95
  *
@@ -6,6 +6,7 @@ const tslib_1 = require("tslib");
6
6
  const common_1 = require("@nestjs/common");
7
7
  const attachment_module_1 = require("../attachment/attachment.module");
8
8
  const bpm_auth_module_1 = require("../bpm-auth/bpm-auth.module");
9
+ const calendar_module_1 = require("../calendar/calendar.module");
9
10
  const delegation_module_1 = require("../delegation/delegation.module");
10
11
  const form_module_1 = require("../form/form.module");
11
12
  const identity_module_1 = require("../identity/identity.module");
@@ -82,6 +83,7 @@ let BPMRootModule = BPMRootModule_1 = class BPMRootModule {
82
83
  return {
83
84
  exports: [
84
85
  notification_options_module_1.NotificationOptionsModule,
86
+ calendar_module_1.CalendarModule,
85
87
  bpm_auth_module_1.BPMAuthModule,
86
88
  identity_module_1.IdentityModule,
87
89
  organization_module_1.OrganizationModule,
@@ -99,6 +101,9 @@ let BPMRootModule = BPMRootModule_1 = class BPMRootModule {
99
101
  inject: options.inject,
100
102
  useFactory: options.useFactory,
101
103
  }),
104
+ calendar_module_1.CalendarModule.forRoot({
105
+ businessCalendarProvider: options.businessCalendarProvider,
106
+ }),
102
107
  bpm_auth_module_1.BPMAuthModule.forRootAsync(authOptions),
103
108
  identity_module_1.IdentityModule.forRootAsync({
104
109
  imports: options.imports,
@@ -139,6 +144,9 @@ exports.BPMRootModule = BPMRootModule = BPMRootModule_1 = tslib_1.__decorate([
139
144
  function createBPMFeatureModules(options) {
140
145
  return [
141
146
  notification_options_module_1.NotificationOptionsModule.forRoot(options),
147
+ calendar_module_1.CalendarModule.forRoot({
148
+ businessCalendarProvider: options.businessCalendarProvider,
149
+ }),
142
150
  bpm_auth_module_1.BPMAuthModule.forRoot(createBPMAuthModuleOptions(options)),
143
151
  identity_module_1.IdentityModule.forRoot({
144
152
  ...options,
@@ -1 +1 @@
1
- {"version":3,"file":"bpm-root.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/bpm/bpm-root.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAMwB;AAGxB,uEAAmE;AAEnE,iEAA4D;AAK5D,uEAAmE;AACnE,qDAAiD;AAEjD,iEAA6D;AAE7D,6EAAyE;AACzE,6FAAwF;AAExF,6EAAyE;AAEzE,oEAAgE;AAChE,iEAA6D;AAC7D,sFAAiF;AAiIjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEI,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,OAA6B;QAC1C,MAAM,cAAc,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;QAExD,OAAO;YACL,OAAO,EAAE,CAAC,GAAG,cAAc,CAAC;YAC5B,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,cAAc,CAAC;YACxD,MAAM,EAAE,eAAa;SACtB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,YAAY,CAAC,OAAkC;QACpD,MAAM,WAAW,GAA8B;YAC7C,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,KAAK,EACf,GAAG,IAAwB,EACI,EAAE;gBACjC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;gBAEtD,OAAO,0BAA0B,CAAC,WAAW,CAAC,CAAC;YACjD,CAAC;SACF,CAAC;QAEF,OAAO;YACL,OAAO,EAAE;gBACP,uDAAyB;gBACzB,+BAAa;gBACb,gCAAc;gBACd,wCAAkB;gBAClB,oCAAgB;gBAChB,wBAAU;gBACV,gCAAc;gBACd,oCAAgB;gBAChB,wCAAkB;gBAClB,kCAAe;gBACf,6CAAoB;aACrB;YACD,OAAO,EAAE;gBACP,uDAAyB,CAAC,YAAY,CAAC;oBACrC,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;iBAC/B,CAAC;gBACF,+BAAa,CAAC,YAAY,CAAC,WAAW,CAAC;gBACvC,gCAAc,CAAC,YAAY,CAAC;oBAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,sBAAsB,EAAE,OAAO,CAAC,sBAAsB;oBACtD,UAAU,EAAE,OAAO,CAAC,UAAU;iBAC/B,CAAC;gBACF,wCAAkB;gBAClB,oCAAgB,CAAC,YAAY,CAAC;oBAC5B,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;oBACpD,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,eAAe,EAAE,OAAO,CAAC,yBAAyB;oBAClD,UAAU,EAAE,OAAO,CAAC,UAAU;iBAC/B,CAAC;gBACF,wBAAU;gBACV,gCAAc;gBACd,oCAAgB;gBAChB,wCAAkB;gBAClB,kCAAe,CAAC,YAAY,CAAC;oBAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;iBAC/B,CAAC;gBACF,6CAAoB,CAAC,OAAO,CAAC;oBAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,6BAA6B,EAC3B,OAAO,CAAC,qCAAqC;iBAChD,CAAC;aACH;YACD,MAAM,EAAE,eAAa;SACtB,CAAC;IACJ,CAAC;CACF,CAAA;AA7FY,sCAAa;wBAAb,aAAa;IADzB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,aAAa,CA6FzB;AAED,SAAS,uBAAuB,CAC9B,OAA6B;IAE7B,OAAO;QACL,uDAAyB,CAAC,OAAO,CAAC,OAAO,CAAC;QAC1C,+BAAa,CAAC,OAAO,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC;QAC1D,gCAAc,CAAC,OAAO,CAAC;YACrB,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,sBAAsB,EAAE,OAAO,CAAC,sBAAsB;SACvD,CAAC;QACF,wCAAkB;QAClB,oCAAgB,CAAC,OAAO,CAAC;YACvB,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,eAAe,EAAE,OAAO,CAAC,yBAAyB;SACnD,CAAC;QACF,wBAAU;QACV,gCAAc;QACd,oCAAgB;QAChB,wCAAkB;QAClB,kCAAe,CAAC,OAAO,CAAC,OAAO,CAAC;QAChC,6CAAoB,CAAC,OAAO,CAAC;YAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,6BAA6B,EAC3B,OAAO,CAAC,qCAAqC;SAChD,CAAC;KACH,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CACjC,OAAgE;IAEhE,OAAO;QACL,cAAc,EAAE,OAAO,CAAC,kBAAkB;KAC3C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"bpm-root.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/bpm/bpm-root.module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Provider } from '@nestjs/common';
2
+ import { BPMBusinessCalendar } from './business-calendar.token';
3
+ /**
4
+ * Default {@link BPMBusinessCalendar} used when the host registers none.
5
+ *
6
+ * Treats Monday–Friday as working days in the time zone configured through
7
+ * `notificationSlaBusinessCalendarTimeZone`, and knows about no holidays. Hosts
8
+ * that need national holidays or make-up working days replace this provider via
9
+ * `BPMRootModule`'s `businessCalendarProvider`.
10
+ */
11
+ export declare const defaultBusinessCalendarProvider: Provider<BPMBusinessCalendar>;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultBusinessCalendarProvider = void 0;
4
+ const notification_options_1 = require("../notification/notification-options");
5
+ const business_calendar_token_1 = require("./business-calendar.token");
6
+ const weekday_business_calendar_1 = require("./weekday-business-calendar");
7
+ /**
8
+ * Default {@link BPMBusinessCalendar} used when the host registers none.
9
+ *
10
+ * Treats Monday–Friday as working days in the time zone configured through
11
+ * `notificationSlaBusinessCalendarTimeZone`, and knows about no holidays. Hosts
12
+ * that need national holidays or make-up working days replace this provider via
13
+ * `BPMRootModule`'s `businessCalendarProvider`.
14
+ */
15
+ exports.defaultBusinessCalendarProvider = {
16
+ inject: [notification_options_1.BPM_NOTIFICATION_OPTIONS],
17
+ provide: business_calendar_token_1.BPM_BUSINESS_CALENDAR,
18
+ useFactory: (options) => new weekday_business_calendar_1.BPMWeekdayBusinessCalendar(options.slaBusinessCalendarTimeZone),
19
+ };
20
+ //# sourceMappingURL=business-calendar.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"business-calendar.provider.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/business-calendar.provider.ts"],"names":[],"mappings":";;;AACA,+EAG8C;AAC9C,uEAGmC;AACnC,2EAAyE;AAEzE;;;;;;;GAOG;AACU,QAAA,+BAA+B,GAAkC;IAC5E,MAAM,EAAE,CAAC,+CAAwB,CAAC;IAClC,OAAO,EAAE,+CAAqB;IAC9B,UAAU,EAAE,CACV,OAAuC,EAClB,EAAE,CACvB,IAAI,sDAA0B,CAAC,OAAO,CAAC,2BAA2B,CAAC;CACtE,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { InjectionToken } from '@nestjs/common';
2
+ /**
3
+ * Host-provided business calendar used to resolve `BUSINESS_DAY` SLA due
4
+ * dates.
5
+ *
6
+ * BPMCore deliberately ships **no** national holiday data. A host that needs
7
+ * real working-day semantics (national holidays, make-up working Saturdays,
8
+ * company shutdown days) implements this contract against its own calendar
9
+ * source and registers it through `BPMRootModule`'s `businessCalendarProvider`.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * BPMRootModule.forRoot({
14
+ * businessCalendarProvider: {
15
+ * provide: BPM_BUSINESS_CALENDAR,
16
+ * useClass: TaiwanBusinessCalendar,
17
+ * },
18
+ * // ...
19
+ * });
20
+ * ```
21
+ */
22
+ export interface BPMBusinessCalendar {
23
+ /**
24
+ * IANA time zone the calendar's dates are expressed in, for example
25
+ * `Asia/Taipei`. BPM converts each instant to a local date in this zone
26
+ * before asking {@link BPMBusinessCalendar.isBusinessDay}, so day boundaries
27
+ * follow the host's calendar rather than the server's locale or UTC.
28
+ */
29
+ readonly timeZone: string;
30
+ /**
31
+ * Answers whether `localDate` is a working day.
32
+ *
33
+ * @param localDate Calendar date in `YYYY-MM-DD` form, already expressed in
34
+ * {@link BPMBusinessCalendar.timeZone}.
35
+ */
36
+ isBusinessDay(localDate: string): boolean | Promise<boolean>;
37
+ }
38
+ export declare const BPM_BUSINESS_CALENDAR: InjectionToken<BPMBusinessCalendar>;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BPM_BUSINESS_CALENDAR = void 0;
4
+ exports.BPM_BUSINESS_CALENDAR = Symbol('BPM_BUSINESS_CALENDAR');
5
+ //# sourceMappingURL=business-calendar.token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"business-calendar.token.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/business-calendar.token.ts"],"names":[],"mappings":";;;AAwCa,QAAA,qBAAqB,GAChC,MAAM,CAAC,uBAAuB,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { DynamicModule, Provider } from '@nestjs/common';
2
+ import { BPMBusinessCalendar } from './business-calendar.token';
3
+ export interface CalendarModuleOptions {
4
+ /**
5
+ * Host-provided business calendar. When omitted, BPM falls back to a
6
+ * Monday–Friday calendar with no holiday knowledge.
7
+ */
8
+ readonly businessCalendarProvider?: Provider<BPMBusinessCalendar>;
9
+ }
10
+ /**
11
+ * Supplies SLA scheduling to every BPM module.
12
+ *
13
+ * Global because the workflow engine computes due dates while creating tasks
14
+ * and hosts should not have to thread the calendar through each feature module.
15
+ */
16
+ export declare class CalendarModule {
17
+ static forRoot(options?: CalendarModuleOptions): DynamicModule;
18
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var CalendarModule_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.CalendarModule = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const business_calendar_provider_1 = require("./business-calendar.provider");
8
+ const sla_schedule_service_1 = require("./sla-schedule.service");
9
+ /**
10
+ * Supplies SLA scheduling to every BPM module.
11
+ *
12
+ * Global because the workflow engine computes due dates while creating tasks
13
+ * and hosts should not have to thread the calendar through each feature module.
14
+ */
15
+ let CalendarModule = CalendarModule_1 = class CalendarModule {
16
+ static forRoot(options = {}) {
17
+ return {
18
+ exports: [sla_schedule_service_1.BPMSlaScheduleService],
19
+ module: CalendarModule_1,
20
+ providers: [
21
+ options.businessCalendarProvider ?? business_calendar_provider_1.defaultBusinessCalendarProvider,
22
+ sla_schedule_service_1.BPMSlaScheduleService,
23
+ ],
24
+ };
25
+ }
26
+ };
27
+ exports.CalendarModule = CalendarModule;
28
+ exports.CalendarModule = CalendarModule = CalendarModule_1 = tslib_1.__decorate([
29
+ (0, common_1.Global)(),
30
+ (0, common_1.Module)({})
31
+ ], CalendarModule);
32
+ //# sourceMappingURL=calendar.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/calendar.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAAyE;AAEzE,6EAA+E;AAC/E,iEAA+D;AAU/D;;;;;GAKG;AAGI,IAAM,cAAc,sBAApB,MAAM,cAAc;IACzB,MAAM,CAAC,OAAO,CAAC,UAAiC,EAAE;QAChD,OAAO;YACL,OAAO,EAAE,CAAC,4CAAqB,CAAC;YAChC,MAAM,EAAE,gBAAc;YACtB,SAAS,EAAE;gBACT,OAAO,CAAC,wBAAwB,IAAI,4DAA+B;gBACnE,4CAAqB;aACtB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAXY,wCAAc;yBAAd,cAAc;IAF1B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,cAAc,CAW1B"}
@@ -0,0 +1,5 @@
1
+ export * from './business-calendar.provider';
2
+ export * from './business-calendar.token';
3
+ export * from './calendar.module';
4
+ export * from './sla-schedule.service';
5
+ export * from './weekday-business-calendar';
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./business-calendar.provider"), exports);
5
+ tslib_1.__exportStar(require("./business-calendar.token"), exports);
6
+ tslib_1.__exportStar(require("./calendar.module"), exports);
7
+ tslib_1.__exportStar(require("./sla-schedule.service"), exports);
8
+ tslib_1.__exportStar(require("./weekday-business-calendar"), exports);
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/index.ts"],"names":[],"mappings":";;;AAAA,uEAA6C;AAC7C,oEAA0C;AAC1C,4DAAkC;AAClC,iEAAuC;AACvC,sEAA4C"}
@@ -0,0 +1,33 @@
1
+ import { UserTaskNode } from '@rytass/bpm-core-shared/workflow';
2
+ import { BPMBusinessCalendar } from './business-calendar.token';
3
+ /**
4
+ * Resolves task SLA due dates, honouring {@link SlaConfig.calendar}.
5
+ *
6
+ * `CALENDAR` (the default) adds the ISO duration as elapsed wall time —
7
+ * identical to BPM's pre-0.7.0 behaviour. `BUSINESS_DAY` advances the duration's
8
+ * day component across business days only, asking the host-provided
9
+ * {@link BPMBusinessCalendar} about each candidate date; any sub-day component
10
+ * is then added as plain elapsed time on top of the resolved business day.
11
+ */
12
+ export declare class BPMSlaScheduleService {
13
+ private readonly businessCalendar;
14
+ private readonly logger;
15
+ private readonly dateFormatter;
16
+ constructor(businessCalendar: BPMBusinessCalendar);
17
+ resolveTaskSlaDueAt({ node, now, }: {
18
+ readonly node: UserTaskNode;
19
+ readonly now: Date;
20
+ }): Promise<Date | null>;
21
+ /**
22
+ * Walks forward one calendar day at a time from `now`, consuming one unit of
23
+ * `businessDays` for each date the host calendar reports as a working day,
24
+ * and returns how many calendar days were stepped.
25
+ *
26
+ * The starting date is never counted: an SLA of "1 business day" always lands
27
+ * on the *next* working day, whether the task was raised on a Monday or on a
28
+ * Saturday.
29
+ */
30
+ private countCalendarDaysForBusinessDays;
31
+ /** Formats an instant as a `YYYY-MM-DD` date in the calendar's time zone. */
32
+ private readLocalDate;
33
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var BPMSlaScheduleService_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.BPMSlaScheduleService = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const iso_duration_1 = require("../common/iso-duration");
8
+ const business_calendar_token_1 = require("./business-calendar.token");
9
+ /**
10
+ * Upper bound on how far the business-day search may walk before giving up.
11
+ *
12
+ * A host calendar that reports every date as a non-business day would
13
+ * otherwise loop forever (and, when the calendar is database-backed, issue one
14
+ * query per step). The allowance is generous enough for weekends plus a long
15
+ * holiday season, and capped so a misconfigured calendar degrades quickly.
16
+ */
17
+ const MAX_BUSINESS_DAY_SCAN_STEPS = 400;
18
+ function readBusinessDayScanLimit(days) {
19
+ return Math.min(days * 7 + 60, MAX_BUSINESS_DAY_SCAN_STEPS);
20
+ }
21
+ /**
22
+ * Resolves task SLA due dates, honouring {@link SlaConfig.calendar}.
23
+ *
24
+ * `CALENDAR` (the default) adds the ISO duration as elapsed wall time —
25
+ * identical to BPM's pre-0.7.0 behaviour. `BUSINESS_DAY` advances the duration's
26
+ * day component across business days only, asking the host-provided
27
+ * {@link BPMBusinessCalendar} about each candidate date; any sub-day component
28
+ * is then added as plain elapsed time on top of the resolved business day.
29
+ */
30
+ let BPMSlaScheduleService = BPMSlaScheduleService_1 = class BPMSlaScheduleService {
31
+ constructor(businessCalendar) {
32
+ this.businessCalendar = businessCalendar;
33
+ this.logger = new common_1.Logger(BPMSlaScheduleService_1.name);
34
+ this.dateFormatter = new Intl.DateTimeFormat('en-CA', {
35
+ day: '2-digit',
36
+ month: '2-digit',
37
+ timeZone: businessCalendar.timeZone,
38
+ year: 'numeric',
39
+ });
40
+ }
41
+ async resolveTaskSlaDueAt({ node, now, }) {
42
+ const sla = node.data.sla;
43
+ if (!sla?.duration) {
44
+ return null;
45
+ }
46
+ const parts = (0, iso_duration_1.parseIsoDurationParts)(sla.duration);
47
+ if (!parts) {
48
+ return null;
49
+ }
50
+ if (sla.calendar !== 'BUSINESS_DAY' || parts.days === 0) {
51
+ return new Date(now.getTime() + parts.days * iso_duration_1.MS_PER_DAY + parts.timeMs);
52
+ }
53
+ const advancedDays = await this.countCalendarDaysForBusinessDays(now, parts.days, node.id);
54
+ return new Date(now.getTime() + advancedDays * iso_duration_1.MS_PER_DAY + parts.timeMs);
55
+ }
56
+ /**
57
+ * Walks forward one calendar day at a time from `now`, consuming one unit of
58
+ * `businessDays` for each date the host calendar reports as a working day,
59
+ * and returns how many calendar days were stepped.
60
+ *
61
+ * The starting date is never counted: an SLA of "1 business day" always lands
62
+ * on the *next* working day, whether the task was raised on a Monday or on a
63
+ * Saturday.
64
+ */
65
+ async countCalendarDaysForBusinessDays(now, businessDays, nodeId) {
66
+ const scanLimit = readBusinessDayScanLimit(businessDays);
67
+ let remainingBusinessDays = businessDays;
68
+ let steps = 0;
69
+ while (remainingBusinessDays > 0 && steps < scanLimit) {
70
+ steps += 1;
71
+ const candidate = new Date(now.getTime() + steps * iso_duration_1.MS_PER_DAY);
72
+ if (await this.businessCalendar.isBusinessDay(this.readLocalDate(candidate))) {
73
+ remainingBusinessDays -= 1;
74
+ }
75
+ }
76
+ if (remainingBusinessDays > 0) {
77
+ this.logger.warn(`Business calendar reported no working day within ${scanLimit} days for node ${nodeId}; falling back to calendar time.`);
78
+ return businessDays;
79
+ }
80
+ return steps;
81
+ }
82
+ /** Formats an instant as a `YYYY-MM-DD` date in the calendar's time zone. */
83
+ readLocalDate(value) {
84
+ // `en-CA` renders ISO-ordered dates, so no part reassembly is needed.
85
+ return this.dateFormatter.format(value);
86
+ }
87
+ };
88
+ exports.BPMSlaScheduleService = BPMSlaScheduleService;
89
+ exports.BPMSlaScheduleService = BPMSlaScheduleService = BPMSlaScheduleService_1 = tslib_1.__decorate([
90
+ (0, common_1.Injectable)(),
91
+ tslib_1.__param(0, (0, common_1.Inject)(business_calendar_token_1.BPM_BUSINESS_CALENDAR)),
92
+ tslib_1.__metadata("design:paramtypes", [Object])
93
+ ], BPMSlaScheduleService);
94
+ //# sourceMappingURL=sla-schedule.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sla-schedule.service.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/sla-schedule.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { BPMBusinessCalendar } from './business-calendar.token';
2
+ /**
3
+ * Built-in fallback calendar: Monday through Friday are working days, weekends
4
+ * are not, and no holiday is known.
5
+ *
6
+ * This is what a host gets when it opts a node into `BUSINESS_DAY` without
7
+ * registering a calendar. It is intentionally naive — a host that cares about
8
+ * national holidays or make-up working days must supply its own
9
+ * {@link BPMBusinessCalendar}.
10
+ */
11
+ export declare class BPMWeekdayBusinessCalendar implements BPMBusinessCalendar {
12
+ readonly timeZone: string;
13
+ constructor(timeZone?: string);
14
+ isBusinessDay(localDate: string): boolean;
15
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BPMWeekdayBusinessCalendar = void 0;
4
+ const SATURDAY = 6;
5
+ const SUNDAY = 0;
6
+ /**
7
+ * Built-in fallback calendar: Monday through Friday are working days, weekends
8
+ * are not, and no holiday is known.
9
+ *
10
+ * This is what a host gets when it opts a node into `BUSINESS_DAY` without
11
+ * registering a calendar. It is intentionally naive — a host that cares about
12
+ * national holidays or make-up working days must supply its own
13
+ * {@link BPMBusinessCalendar}.
14
+ */
15
+ class BPMWeekdayBusinessCalendar {
16
+ constructor(timeZone = 'UTC') {
17
+ this.timeZone = timeZone;
18
+ }
19
+ isBusinessDay(localDate) {
20
+ // `localDate` is already expressed in this calendar's zone, so reading it
21
+ // back as a UTC instant yields the correct weekday without re-applying an
22
+ // offset.
23
+ const weekday = new Date(`${localDate}T00:00:00.000Z`).getUTCDay();
24
+ return weekday !== SATURDAY && weekday !== SUNDAY;
25
+ }
26
+ }
27
+ exports.BPMWeekdayBusinessCalendar = BPMWeekdayBusinessCalendar;
28
+ //# sourceMappingURL=weekday-business-calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weekday-business-calendar.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/calendar/weekday-business-calendar.ts"],"names":[],"mappings":";;;AAEA,MAAM,QAAQ,GAAG,CAAC,CAAC;AACnB,MAAM,MAAM,GAAG,CAAC,CAAC;AAEjB;;;;;;;;GAQG;AACH,MAAa,0BAA0B;IAGrC,YAAY,QAAQ,GAAG,KAAK;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,aAAa,CAAC,SAAiB;QAC7B,0EAA0E;QAC1E,0EAA0E;QAC1E,UAAU;QACV,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,SAAS,gBAAgB,CAAC,CAAC,SAAS,EAAE,CAAC;QAEnE,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,MAAM,CAAC;IACpD,CAAC;CACF;AAfD,gEAeC"}
@@ -1 +1,12 @@
1
+ export declare const MS_PER_DAY: number;
2
+ /**
3
+ * The day component and the sub-day (time) component of an ISO duration, kept
4
+ * apart because business-day SLA scheduling advances them differently: `days`
5
+ * skips non-business dates, `timeMs` is added as plain elapsed time.
6
+ */
7
+ export interface IsoDurationParts {
8
+ readonly days: number;
9
+ readonly timeMs: number;
10
+ }
1
11
  export declare function parseIsoDurationToMilliseconds(value: string): number | null;
12
+ export declare function parseIsoDurationParts(value: string): IsoDurationParts | null;
@@ -1,12 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MS_PER_DAY = void 0;
3
4
  exports.parseIsoDurationToMilliseconds = parseIsoDurationToMilliseconds;
5
+ exports.parseIsoDurationParts = parseIsoDurationParts;
4
6
  const ISO_DURATION_PATTERN = /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/u;
5
7
  const MS_PER_SECOND = 1000;
6
8
  const SECONDS_PER_MINUTE = 60;
7
9
  const MINUTES_PER_HOUR = 60;
8
10
  const HOURS_PER_DAY = 24;
11
+ exports.MS_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MS_PER_SECOND;
9
12
  function parseIsoDurationToMilliseconds(value) {
13
+ const parts = parseIsoDurationParts(value);
14
+ return parts ? parts.days * exports.MS_PER_DAY + parts.timeMs : null;
15
+ }
16
+ function parseIsoDurationParts(value) {
10
17
  const match = ISO_DURATION_PATTERN.exec(value.trim());
11
18
  if (!match) {
12
19
  return null;
@@ -15,11 +22,13 @@ function parseIsoDurationToMilliseconds(value) {
15
22
  const hours = readDurationUnit(match[2]);
16
23
  const minutes = readDurationUnit(match[3]);
17
24
  const seconds = readDurationUnit(match[4]);
18
- const totalSeconds = seconds +
25
+ const timeSeconds = seconds +
19
26
  minutes * SECONDS_PER_MINUTE +
20
- hours * MINUTES_PER_HOUR * SECONDS_PER_MINUTE +
21
- days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE;
22
- return totalSeconds > 0 ? totalSeconds * MS_PER_SECOND : null;
27
+ hours * MINUTES_PER_HOUR * SECONDS_PER_MINUTE;
28
+ if (days === 0 && timeSeconds === 0) {
29
+ return null;
30
+ }
31
+ return { days, timeMs: timeSeconds * MS_PER_SECOND };
23
32
  }
24
33
  function readDurationUnit(value) {
25
34
  return value ? Number(value) : 0;
@@ -1 +1 @@
1
- {"version":3,"file":"iso-duration.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/common/iso-duration.ts"],"names":[],"mappings":";;AAQA,wEAkBC;AA1BD,MAAM,oBAAoB,GACxB,wDAAwD,CAAC;AAE3D,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,SAAgB,8BAA8B,CAAC,KAAa;IAC1D,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAEtD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,YAAY,GAChB,OAAO;QACP,OAAO,GAAG,kBAAkB;QAC5B,KAAK,GAAG,gBAAgB,GAAG,kBAAkB;QAC7C,IAAI,GAAG,aAAa,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;IAE/D,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAyB;IACjD,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"iso-duration.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/common/iso-duration.ts"],"names":[],"mappings":";;;AAqBA,wEAIC;AAED,sDAqBC;AAhDD,MAAM,oBAAoB,GACxB,wDAAwD,CAAC;AAE3D,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,aAAa,GAAG,EAAE,CAAC;AAEZ,QAAA,UAAU,GACrB,aAAa,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,aAAa,CAAC;AAYxE,SAAgB,8BAA8B,CAAC,KAAa;IAC1D,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAE3C,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,kBAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC;AAED,SAAgB,qBAAqB,CAAC,KAAa;IACjD,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAEtD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,WAAW,GACf,OAAO;QACP,OAAO,GAAG,kBAAkB;QAC5B,KAAK,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;IAEhD,IAAI,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,EAAE,CAAC;AACvD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAyB;IACjD,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC"}
@@ -126,6 +126,15 @@ export interface BPMRootNotificationOptions {
126
126
  * tight loops in long-running API processes.
127
127
  */
128
128
  readonly notificationSlaScanIntervalMs?: number;
129
+ /**
130
+ * IANA time zone used by BPM's built-in Monday–Friday business calendar when
131
+ * the host registers no `businessCalendarProvider`.
132
+ *
133
+ * Only affects nodes whose SLA opts into `BUSINESS_DAY`. Defaults to `UTC`.
134
+ * Hosts that inject their own `BPMBusinessCalendar` declare the time zone on
135
+ * the calendar itself and this option is ignored.
136
+ */
137
+ readonly notificationSlaBusinessCalendarTimeZone?: string;
129
138
  /**
130
139
  * Enables the SLA timeout `REMIND` action.
131
140
  *
@@ -199,6 +208,7 @@ export interface BPMResolvedNotificationOptions {
199
208
  readonly deliveryRetryBaseDelayMs: number;
200
209
  readonly deliveryScanIntervalMs: number;
201
210
  readonly deliverySchedulerEnabled: boolean;
211
+ readonly slaBusinessCalendarTimeZone: string;
202
212
  readonly slaScanIntervalMs: number;
203
213
  readonly slaSchedulerEnabled: boolean;
204
214
  readonly slaTimeoutAutoApproveEnabled: boolean;