@mis-wis/common 0.2.0 → 0.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.
@@ -15,9 +15,10 @@ import { LoaderModule } from 'mis-crystal-design-system/loader';
15
15
  import { map, forkJoin, ReplaySubject } from 'rxjs';
16
16
  import * as i2$2 from '@angular/forms';
17
17
  import { Validators, ReactiveFormsModule } from '@angular/forms';
18
- import { parseZone } from 'moment';
19
- import * as i1$3 from 'mis-design-system/mis-modal';
20
- import { MODAL_DATA_VAR } from 'mis-design-system/mis-modal';
18
+ import dayjs from 'dayjs';
19
+ import customParseFormat from 'dayjs/plugin/customParseFormat';
20
+ import * as i1$3 from 'mis-crystal-design-system/modal';
21
+ import { MODAL_DATA_VAR } from 'mis-crystal-design-system/modal';
21
22
  import * as i6 from 'mis-crystal-design-system/dropdown';
22
23
  import { DropdownModule } from 'mis-crystal-design-system/dropdown';
23
24
  import * as i7 from 'mis-crystal-design-system/datepicker_v2';
@@ -229,19 +230,22 @@ const CONSTANTS_LOGGER = {
229
230
  };
230
231
 
231
232
  const envMap = {
232
- dev: "https://bff.devcl.moveinsync.com",
233
- qa: "https://bff.stage.moveinsync.com",
234
- production: "https://bff.moveinsync.com",
235
- uat: "https://wisbff-uat.moveinsync.com",
236
- "production-green": "https://wisempweb-green.moveinsync.com",
237
- "production-beta": "https://bff-beta.moveinsync.com",
238
- "production-eu": "https://bff.eu.moveinsync.com",
239
- "production-eu-green": "https://bff-green.eu.moveinsync.com",
240
- "production-mu": "https://bff.moveinsync.in"
233
+ dev: "https://ui-logger.stage.moveinsync.com",
234
+ qa: "https://ui-logger.stage.moveinsync.com",
235
+ production: "https://ui-logger.moveinsync.com",
236
+ uat: "https://ui-logger-uat.moveinsync.com",
237
+ "production-green": "https://ui-logger-green.moveinsync.com",
238
+ "production-beta": "https://ui-logger-beta.moveinsync.com",
239
+ "production-eu": "https://ui-logger.eu.moveinsync.com",
240
+ "production-eu-green": "https://ui-logger-green.eu.moveinsync.com",
241
+ "production-eu-beta": "https://ui-logger-beta.eu.moveinsync.com",
242
+ "production-mu": "https://ui-logger.moveinsync.in",
243
+ "production-mu-green": "https://ui-logger-green.moveinsync.in",
244
+ "production-mu-beta": "https://ui-logger-beta.moveinsync.in",
241
245
  };
242
246
  function environmentHandler(env) {
243
247
  if (!env) {
244
- return "/bff";
248
+ return "/logger";
245
249
  }
246
250
  return envMap[env];
247
251
  }
@@ -395,7 +399,10 @@ const CONSTANTS_ASSETS_WIS_COMMON = {
395
399
  ICONS: {}
396
400
  };
397
401
 
402
+ dayjs.extend(customParseFormat);
398
403
  const PROPERTIES = ["NON_SHIFT_TRIPS_CATEGORIES", "USE_VALID_OFFICE_FOR_IRREGULAR_TRIPS"];
404
+ const DATE_FORMAT = "DD/MM/YYYY";
405
+ const PICKUP_TIME_FORMAT = "DD/MM/YYYY HH/mm/ss";
399
406
  class CreateNonShiftModalComponent {
400
407
  constructor(modalData, modalRef, fb, http, toast) {
401
408
  this.modalData = modalData;
@@ -405,8 +412,8 @@ class CreateNonShiftModalComponent {
405
412
  this.toast = toast;
406
413
  this.CONSTANTS_ASSETS_WIS_COMMON = CONSTANTS_ASSETS_WIS_COMMON;
407
414
  this.dateConfig = {
408
- minDate: parseZone().format("DD/MM/YYYY"),
409
- format: "DD/MM/YYYY"
415
+ minDate: dayjs().format(DATE_FORMAT),
416
+ format: DATE_FORMAT
410
417
  };
411
418
  this.offices = [];
412
419
  this.locationDropdownData = [];
@@ -441,7 +448,7 @@ class CreateNonShiftModalComponent {
441
448
  });
442
449
  }
443
450
  initializeForm() {
444
- const currentTime = this.modalData?.date ?? parseZone().format("DD/MM/YYYY");
451
+ const currentTime = this.modalData?.date ?? dayjs().format(DATE_FORMAT);
445
452
  this.createTripsheetForm = this.fb.group({
446
453
  direction: [this.modalData?.shiftType === "logout" ? "OUT" : "IN", Validators.required],
447
454
  location: [{ label: "", value: "" }],
@@ -512,7 +519,7 @@ class CreateNonShiftModalComponent {
512
519
  }
513
520
  const formValue = this.createTripsheetForm.value;
514
521
  const pickupTime = `${formValue.date} ${formValue.hours.value}/${formValue.mins.value}/00`;
515
- const pickupTimeDate = parseZone(pickupTime).toDate();
522
+ const pickupTimeDate = dayjs(pickupTime, PICKUP_TIME_FORMAT).toDate();
516
523
  if (this.isDateAndTimeFromPast(pickupTimeDate)) {
517
524
  this.toast.displayMsg("Please select a future date and time.");
518
525
  return;
@@ -687,6 +694,23 @@ class SessionClaimNotFoundError extends SessionError {
687
694
  this.name = 'SessionClaimNotFoundError';
688
695
  }
689
696
  }
697
+ /** Renders failures as `claim (reason), claim (reason)` for error messages. */
698
+ function describeClaimFailures(failures) {
699
+ return failures.map(f => `${f.claim} (${f.reason})`).join(', ');
700
+ }
701
+ /**
702
+ * Every claim `run`'s `next` failed to read, reported once after the block has finished.
703
+ * Extends `SessionClaimNotFoundError` — and reports the first failure as `claim` — so handlers
704
+ * written against the single-claim error keep working.
705
+ */
706
+ class SessionClaimsMissingError extends SessionClaimNotFoundError {
707
+ constructor(failures) {
708
+ super(failures[0].claim);
709
+ this.failures = failures;
710
+ this.name = 'SessionClaimsMissingError';
711
+ this.message = `Session claims not found: ${describeClaimFailures(failures)}.`;
712
+ }
713
+ }
690
714
 
691
715
  const DEFAULT_SESSION_TOKEN_PREFIX = 'sso-wis-token';
692
716
  const DEFAULT_SESSION_TOKEN_FALLBACK_KEY = 'x-wis-token';
@@ -697,6 +721,7 @@ class SessionService {
697
721
  this.config = {};
698
722
  this.cachedToken = null;
699
723
  this.cachedState = null;
724
+ this.collecting = null;
700
725
  }
701
726
  init(config) {
702
727
  this.config = { ...config };
@@ -720,18 +745,50 @@ class SessionService {
720
745
  }
721
746
  /**
722
747
  * Statement-style variant of `read` for blocks of assignments/side effects with no return value.
748
+ *
749
+ * `next` always runs to completion: a claim that is absent or blank yields `undefined` instead of
750
+ * throwing, and every such failure is reported once afterwards via `handlers.error`, as a
751
+ * `SessionClaimsMissingError` listing all of them. An unusable token (missing, expired,
752
+ * undecodable) still aborts `next` immediately with the matching `SessionError`.
753
+ *
754
+ * Collecting covers the synchronous body of `next` only — claim reads deferred into a subscription,
755
+ * timeout or promise run after it has returned and throw as usual.
756
+ *
757
+ * An error `next` throws for any other reason propagates untouched, except that any claims missing
758
+ * at the time are appended to its message and attached as `sessionClaimFailures` — a collected
759
+ * `undefined` reaching the block is the usual cause, and that is the part worth knowing.
723
760
  */
724
761
  run(handlers) {
725
- this.read({
726
- next: s => { handlers.next(s); return undefined; },
727
- error: err => { handlers.error(err); return undefined; }
728
- });
762
+ const failures = [];
763
+ const previous = this.collecting;
764
+ this.collecting = failures;
765
+ try {
766
+ handlers.next(this);
767
+ }
768
+ catch (e) {
769
+ if (e instanceof SessionError) {
770
+ handlers.error(e);
771
+ return;
772
+ }
773
+ if (failures.length && e instanceof Error) {
774
+ e.sessionClaimFailures = failures;
775
+ e.message = `${e.message} — session claims missing during run(): ${describeClaimFailures(failures)}`;
776
+ }
777
+ throw e;
778
+ }
779
+ finally {
780
+ this.collecting = previous;
781
+ }
782
+ if (failures.length) {
783
+ handlers.error(new SessionClaimsMissingError(failures));
784
+ }
729
785
  }
730
786
  get isVET() {
731
787
  return this.state.isVET;
732
788
  }
733
789
  get sub() { return this.getClaim('sub'); }
734
790
  get empGuid() { return this.getClaim('employeeGUID'); }
791
+ get employeeId() { return this.getClaim('employeeId'); }
735
792
  get internalSsoRole() { return this.getClaim('internal_sso_role'); }
736
793
  get roles() { return this.getClaim('roles'); }
737
794
  get sessionId() { return this.getClaim('sessionId'); }
@@ -744,13 +801,22 @@ class SessionService {
744
801
  get vetUserId() { return this.getClaim('vetUserId'); }
745
802
  get source() { return this.getClaim('source'); }
746
803
  get roleId() {
747
- const claims = this.getClaims();
748
- const raw = claims.internal_sso_role?.trim() || claims.roles?.[0]?.trim();
749
- if (!raw || !/^\d+$/.test(raw)) {
750
- throw new SessionClaimNotFoundError('roleId');
804
+ const raw = this.resolveRole(this.getClaims());
805
+ if (!raw) {
806
+ return this.missingClaim('roleId', 'absent');
751
807
  }
752
808
  return Number(raw);
753
809
  }
810
+ /** First numeric role in `internal_sso_role` then `roles`, or `''` when the token carries none. */
811
+ resolveRole(claims) {
812
+ const candidates = [claims.internal_sso_role, ...(claims.roles ?? [])];
813
+ return candidates
814
+ .map(value => value?.trim())
815
+ .find(value => this.isDigitsOnly(value)) ?? '';
816
+ }
817
+ isDigitsOnly(value) {
818
+ return !!value && /^\d+$/.test(value);
819
+ }
754
820
  getClaims() {
755
821
  const state = this.state;
756
822
  if (state.status === 'ok') {
@@ -769,10 +835,18 @@ class SessionService {
769
835
  const value = claims[key];
770
836
  const isEmptyString = typeof value === 'string' && value.trim() === '';
771
837
  if (value === undefined || value === null || isEmptyString) {
772
- throw new SessionClaimNotFoundError(key);
838
+ return this.missingClaim(key, isEmptyString ? 'blank' : 'absent');
773
839
  }
774
840
  return (typeof value === 'string' ? value.trim() : value);
775
841
  }
842
+ /** Records the failure and yields `undefined` while `run` is collecting; throws otherwise. */
843
+ missingClaim(claim, reason) {
844
+ if (this.collecting) {
845
+ this.collecting.push({ claim, reason });
846
+ return undefined;
847
+ }
848
+ throw new SessionClaimNotFoundError(claim);
849
+ }
776
850
  get state() {
777
851
  const { token, isVET } = this.findToken();
778
852
  if (!this.cachedState || token !== this.cachedToken) {
@@ -838,5 +912,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
838
912
  * Generated bundle index. Do not edit.
839
913
  */
840
914
 
841
- export { AuthInterceptor, AuthModule, AuthService, ConfigurationService, CreateNonShiftModalComponent, LoaderService, LoggerModule, LoggerService, MfeCommunicationService, SessionClaimNotFoundError, SessionError, SessionService, SessionTokenExpiredError, SessionTokenInvalidError, SessionTokenNotFoundError, SidenavComponent, WisCommonModule, filterNavList, getCookie, getQueryParam, removeCookie, setCookie };
915
+ export { AuthInterceptor, AuthModule, AuthService, ConfigurationService, CreateNonShiftModalComponent, LoaderService, LoggerModule, LoggerService, MfeCommunicationService, SessionClaimNotFoundError, SessionClaimsMissingError, SessionError, SessionService, SessionTokenExpiredError, SessionTokenInvalidError, SessionTokenNotFoundError, SidenavComponent, WisCommonModule, describeClaimFailures, filterNavList, getCookie, getQueryParam, removeCookie, setCookie };
842
916
  //# sourceMappingURL=mis-wis-common.mjs.map