@acorex-platform/framework-client 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/fesm2022/acorex-platform-framework-client-auth.mjs +113 -45
  2. package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs → acorex-platform-framework-client-common-common-settings.provider-Cyr1DaiD.mjs} +19 -2
  4. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs.map → acorex-platform-framework-client-common-common-settings.provider-Cyr1DaiD.mjs.map} +1 -1
  5. package/fesm2022/acorex-platform-framework-client-common.mjs +445 -191
  6. package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-framework-client-core.mjs +7 -2
  8. package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-framework-client-layout-components.mjs +399 -132
  10. package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
  11. package/fesm2022/{acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-i9oZEXUR.mjs → acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-D2kZxLOh.mjs} +616 -196
  12. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-D2kZxLOh.mjs.map +1 -0
  13. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-DyrvSBEY.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-BManmr01.mjs} +10 -5
  14. package/fesm2022/acorex-platform-framework-client-layout-entity-attachments-page.component-BManmr01.mjs.map +1 -0
  15. package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-B8s_JEV8.mjs → acorex-platform-framework-client-layout-entity-bulk-entity.command-B8XsnrnO.mjs} +2 -2
  16. package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-B8s_JEV8.mjs.map → acorex-platform-framework-client-layout-entity-bulk-entity.command-B8XsnrnO.mjs.map} +1 -1
  17. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-C0LgUzzv.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-DGZVS11E.mjs} +28 -12
  18. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-DGZVS11E.mjs.map +1 -0
  19. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-fATD9Uax.mjs → acorex-platform-framework-client-layout-entity-gallery-page.component-Be348QCj.mjs} +2 -2
  20. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-fATD9Uax.mjs.map → acorex-platform-framework-client-layout-entity-gallery-page.component-Be348QCj.mjs.map} +1 -1
  21. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +1 -1
  22. package/fesm2022/acorex-platform-framework-client-layout-views.mjs +71 -10
  23. package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
  24. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +147 -171
  25. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
  26. package/fesm2022/{acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-Drmmu4HQ.mjs → acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-M8SZFPQx.mjs} +342 -60
  27. package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-M8SZFPQx.mjs.map +1 -0
  28. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-BiuahYd8.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DsLgZbZA.mjs} +3 -3
  29. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-BiuahYd8.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DsLgZbZA.mjs.map} +1 -1
  30. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-CU_5b_te.mjs → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-Vpz3itLZ.mjs} +2 -2
  31. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-CU_5b_te.mjs.map → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-Vpz3itLZ.mjs.map} +1 -1
  32. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +1 -1
  33. package/fesm2022/acorex-platform-framework-client-realtime.mjs +49 -7
  34. package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -1
  35. package/fesm2022/acorex-platform-framework-client-themes-default.mjs +40 -20
  36. package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
  37. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +1 -1
  38. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
  39. package/i18n/en-AU/general.json +16 -4
  40. package/i18n/en-AU/layout.json +2 -1
  41. package/i18n/en-US/general.json +16 -4
  42. package/i18n/en-US/layout.json +2 -1
  43. package/i18n/fa-IR/general.json +16 -4
  44. package/i18n/fa-IR/layout.json +2 -1
  45. package/layout/widget-core/README.md +1 -1
  46. package/layout/widgets/README.md +2 -2
  47. package/package.json +2 -2
  48. package/types/acorex-platform-framework-client-auth.d.ts +15 -1
  49. package/types/acorex-platform-framework-client-common.d.ts +73 -7
  50. package/types/acorex-platform-framework-client-layout-components.d.ts +38 -7
  51. package/types/acorex-platform-framework-client-layout-entity.d.ts +86 -34
  52. package/types/acorex-platform-framework-client-layout-views.d.ts +15 -0
  53. package/types/acorex-platform-framework-client-layout-widget-core.d.ts +38 -13
  54. package/types/acorex-platform-framework-client-layout-widgets.d.ts +25 -7
  55. package/types/acorex-platform-framework-client-realtime.d.ts +5 -0
  56. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-i9oZEXUR.mjs.map +0 -1
  57. package/fesm2022/acorex-platform-framework-client-layout-entity-attachments-page.component-DyrvSBEY.mjs.map +0 -1
  58. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-C0LgUzzv.mjs.map +0 -1
  59. package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-Drmmu4HQ.mjs.map +0 -1
@@ -534,6 +534,18 @@ function collectErrorCodes(error) {
534
534
  }
535
535
  return codes;
536
536
  }
537
+ /**
538
+ * True when the API rejected the call because no access cookie / bearer was sent.
539
+ * An expired HttpOnly access cookie is omitted by the browser, so the server says
540
+ * "required" rather than "invalid or expired".
541
+ */
542
+ function isMissingAccessTokenError(error) {
543
+ const text = collectErrorText(error);
544
+ if (!text.trim()) {
545
+ return false;
546
+ }
547
+ return /bearer access token is required/i.test(text) || /access token is required/i.test(text);
548
+ }
537
549
  /**
538
550
  * True only when refresh failed because the refresh cookie / session family is dead.
539
551
  * Network / 5xx / Redis unavailable / empty transient results → false.
@@ -1047,59 +1059,31 @@ class AXPSessionService {
1047
1059
  this.applicationsListCache = null;
1048
1060
  }
1049
1061
  try {
1050
- const strategyName = this.resolveStrategyName();
1051
- if (!strategyName) {
1052
- throw new Error('Strategy not found');
1053
- }
1054
- const strategy = this.authStrategyRegistry.get(strategyName);
1055
- if (!strategy) {
1056
- throw new Error(`Authentication strategy '${strategyName}' is not supported`);
1062
+ // Refresh outside the UpdateSession lock. The access cookie expires sooner than
1063
+ // the refresh cookie; a stale click must not run UpdateSession while that lock is held,
1064
+ // or the 401 refresh path deadlocks on the same Web Lock.
1065
+ await this.refreshAccessCookieIfStale();
1066
+ try {
1067
+ await this.commitSessionUpdate(params, isApplicationUpdate, isTenantUpdate, startedAt);
1057
1068
  }
1058
- // Same lock as cookie refresh — UpdateSession rotates refresh `jti`.
1059
- // A restore in another tab must not consume the previous cookie concurrently.
1060
- const result = await withAuthRefreshLock(() => strategy.updateToken(params));
1061
- if (result?.succeed) {
1062
- if (params?.['code']) {
1063
- // OAuth code exchange replaces identity metadata; wipe stale local fields first.
1064
- this.clearSession();
1065
- clearOAuthPendingStrategy();
1066
- }
1067
- else {
1068
- this.permissionsSubject.next([]);
1069
- this.featuresSubject.next([]);
1070
- this.invalidateAccessPolicyCache();
1069
+ catch (error) {
1070
+ if (!isMissingAccessTokenError(error)) {
1071
+ throw error;
1071
1072
  }
1072
- this.setSession({
1073
- strategy: strategyName,
1074
- user: result.data.user,
1075
- tenant: result.data?.tenant ?? null,
1076
- application: this.resolveApplicationAfterUpdate(result.data?.application ?? null, isApplicationUpdate, isTenantUpdate),
1077
- expiresIn: result.data?.expiresIn,
1078
- locked: false,
1079
- cookieSession: true,
1080
- });
1081
- await this.reloadAccessPolicyIfReady('updateToken');
1082
- await this.syncSessionAuthorization();
1083
- traceAuthWorkspace('UpdateSession complete', () => ({
1084
- ms: Date.now() - startedAt,
1085
- status: this.status.value,
1086
- tenantId: this.tenant?.id,
1087
- applicationId: this.application?.id,
1073
+ warnAuthWorkspace('UpdateSession missing access cookie — refreshing', () => ({
1074
+ error: error instanceof Error ? error.message : String(error),
1088
1075
  }));
1089
- }
1090
- else {
1091
- throw new Error('UpdateSession failed');
1076
+ const refreshed = await this.refreshToken();
1077
+ if (!refreshed) {
1078
+ throw error;
1079
+ }
1080
+ await this.commitSessionUpdate(params, isApplicationUpdate, isTenantUpdate, startedAt);
1092
1081
  }
1093
1082
  }
1094
1083
  catch (error) {
1095
1084
  traceAuthLifecycleError('UpdateSession failed', () => ({
1096
1085
  error: error instanceof Error ? error.message : String(error),
1097
1086
  }));
1098
- warnAuthWorkspace('UpdateSession failed — identity session kept', () => ({
1099
- error: error instanceof Error ? error.message : String(error),
1100
- tenantId: params?.['tenant']?.id ?? params?.['tenantId'] ?? null,
1101
- applicationId: params?.['application']?.id ?? params?.['applicationId'] ?? null,
1102
- }));
1103
1087
  if (params?.['code']) {
1104
1088
  clearOAuthPendingStrategy();
1105
1089
  }
@@ -1108,6 +1092,11 @@ class AXPSessionService {
1108
1092
  this.syncContextSubjectsFromStorage();
1109
1093
  const stored = this.getSessionData();
1110
1094
  if (stored?.user && stored.cookieSession) {
1095
+ warnAuthWorkspace('UpdateSession failed — identity session kept', () => ({
1096
+ error: error instanceof Error ? error.message : String(error),
1097
+ tenantId: params?.['tenant']?.id ?? params?.['tenantId'] ?? null,
1098
+ applicationId: params?.['application']?.id ?? params?.['applicationId'] ?? null,
1099
+ }));
1111
1100
  await this.syncSessionAuthorization();
1112
1101
  }
1113
1102
  throw error;
@@ -1571,6 +1560,85 @@ class AXPSessionService {
1571
1560
  invalidateAccessPolicyCache() {
1572
1561
  this.accessPolicyCache?.invalidate();
1573
1562
  }
1563
+ /**
1564
+ * Access cookie max-age matches the JWT (often 15m) while the refresh cookie lasts days.
1565
+ * After it expires the browser omits it, and UpdateSession is not retried by the HTTP
1566
+ * interceptor (auth commands skip 401 refresh to avoid a lock deadlock).
1567
+ */
1568
+ isAccessCookieStale() {
1569
+ const expiresIn = this.getSessionData()?.expiresIn;
1570
+ if (!expiresIn) {
1571
+ return false;
1572
+ }
1573
+ const expiresAt = new Date(expiresIn).getTime();
1574
+ if (Number.isNaN(expiresAt)) {
1575
+ return false;
1576
+ }
1577
+ const skewMs = 15_000;
1578
+ return expiresAt <= Date.now() + skewMs;
1579
+ }
1580
+ async refreshAccessCookieIfStale() {
1581
+ if (!this.isAccessCookieStale() || !this.hasSessionCredentials()) {
1582
+ return;
1583
+ }
1584
+ traceAuthWorkspace('Access cookie stale — refreshing before UpdateSession', () => ({
1585
+ expiresIn: this.getSessionData()?.expiresIn ?? null,
1586
+ }));
1587
+ try {
1588
+ await this.refreshToken();
1589
+ }
1590
+ catch (error) {
1591
+ if (isDefinitiveAuthRefreshFailure(error)) {
1592
+ throw error;
1593
+ }
1594
+ warnAuthWorkspace('Stale access refresh failed — continuing UpdateSession', () => ({
1595
+ error: error instanceof Error ? error.message : String(error),
1596
+ }));
1597
+ }
1598
+ }
1599
+ async commitSessionUpdate(params, isApplicationUpdate, isTenantUpdate, startedAt) {
1600
+ const strategyName = this.resolveStrategyName();
1601
+ if (!strategyName) {
1602
+ throw new Error('Strategy not found');
1603
+ }
1604
+ const strategy = this.authStrategyRegistry.get(strategyName);
1605
+ if (!strategy) {
1606
+ throw new Error(`Authentication strategy '${strategyName}' is not supported`);
1607
+ }
1608
+ // Same lock as cookie refresh — UpdateSession rotates refresh `jti`.
1609
+ // A restore in another tab must not consume the previous cookie concurrently.
1610
+ const result = await withAuthRefreshLock(() => strategy.updateToken(params));
1611
+ if (!result?.succeed) {
1612
+ throw new Error('UpdateSession failed');
1613
+ }
1614
+ if (params?.['code']) {
1615
+ // OAuth code exchange replaces identity metadata; wipe stale local fields first.
1616
+ this.clearSession();
1617
+ clearOAuthPendingStrategy();
1618
+ }
1619
+ else {
1620
+ this.permissionsSubject.next([]);
1621
+ this.featuresSubject.next([]);
1622
+ this.invalidateAccessPolicyCache();
1623
+ }
1624
+ this.setSession({
1625
+ strategy: strategyName,
1626
+ user: result.data.user,
1627
+ tenant: result.data?.tenant ?? null,
1628
+ application: this.resolveApplicationAfterUpdate(result.data?.application ?? null, isApplicationUpdate, isTenantUpdate),
1629
+ expiresIn: result.data?.expiresIn,
1630
+ locked: false,
1631
+ cookieSession: true,
1632
+ });
1633
+ await this.reloadAccessPolicyIfReady('updateToken');
1634
+ await this.syncSessionAuthorization();
1635
+ traceAuthWorkspace('UpdateSession complete', () => ({
1636
+ ms: Date.now() - startedAt,
1637
+ status: this.status.value,
1638
+ tenantId: this.tenant?.id,
1639
+ applicationId: this.application?.id,
1640
+ }));
1641
+ }
1574
1642
  isApplicationContextUpdate(params) {
1575
1643
  return params?.['application'] != null || params?.['applicationId'] != null;
1576
1644
  }
@@ -2826,5 +2894,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
2826
2894
  * Generated bundle index. Do not edit.
2827
2895
  */
2828
2896
 
2829
- export { AUTH_SESSION_TRACE_NS, AUTH_SESSION_TRACE_TITLE, AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureEvaluatorScopeProvider, AXPFeatureGuard, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPPlatformAuthRuntimeService, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPSignInMethod, AXPSignInMethodRegistry, AXPUnauthenticatedError, AXPUnauthorizedError, AXPUserProfileIdentityService, AXP_ACCESS_POLICY_CACHE_PORT, AXP_APPLICATION_LOADER, AXP_DEFAULT_PLATFORM_OAUTH_CLIENT_ID, AXP_DEFAULT_PLATFORM_OAUTH_SCOPE, AXP_FEATURE_CHECKER, AXP_FEATURE_LOADER, AXP_LOGIN_CHALLENGE_PROVIDER, AXP_OAUTH_PKCE_VERIFIER_KEY, AXP_PERMISSION_CHECKER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_PERMISSION_MODULES_RESOLVER, AXP_PLATFORM_OAUTH_CSRF_COOKIE, AXP_TENANT_LOADER, AXP_USER_AVATAR_CACHE_PORT, DEFINITIVE_AUTH_REFRESH_CODES, JwtUtil, MAX_ACTIVE_DEVICE_SESSIONS_CODE, PkceUtil, TimeUtil, asAuthListProvidersResponse, clearOAuthPendingStrategy, clearSessionLimitPendingTenant, commandMessageTextForError, exchangePlatformOAuthAuthorizationCode, fetchPlatformOAuthDiscoveryDocument, findIdentityProvider, getOAuthPendingStrategy, hasLegacyOAuthPkceVerifier, hasOAuthPendingFlow, initPlatformOAuthAuthorization, isDefinitiveAuthRefreshFailure, isMaxActiveDeviceSessionsError, isOAuthRedirectInFlight, platformOAuthSessionUpdateParams, readPlatformOAuthCsrfToken, readSessionLimitPendingTenant, resolvePlatformOAuthAuthorizeEndpoint, resolvePlatformOAuthClientConfig, resolvePlatformOAuthIssuer, resolvePlatformOAuthRedirectUri, resolvePlatformOAuthTokenEndpoint, resolveStatusAfterSoftRestore, setOAuthPendingStrategy, shouldPlatformOAuthBindSession, shouldRetryAccessPolicyAuthorization, storeSessionLimitPendingTenant, toPlatformOAuthSignInResult, traceAuthAccessPolicy, traceAuthCatalog, traceAuthGuard, traceAuthLifecycle, traceAuthLifecycleError, traceAuthRestore, traceAuthWorkspace, warnAuthAccessPolicy, warnAuthLifecycle, warnAuthWorkspace };
2897
+ export { AUTH_SESSION_TRACE_NS, AUTH_SESSION_TRACE_TITLE, AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureEvaluatorScopeProvider, AXPFeatureGuard, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPPlatformAuthRuntimeService, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPSignInMethod, AXPSignInMethodRegistry, AXPUnauthenticatedError, AXPUnauthorizedError, AXPUserProfileIdentityService, AXP_ACCESS_POLICY_CACHE_PORT, AXP_APPLICATION_LOADER, AXP_DEFAULT_PLATFORM_OAUTH_CLIENT_ID, AXP_DEFAULT_PLATFORM_OAUTH_SCOPE, AXP_FEATURE_CHECKER, AXP_FEATURE_LOADER, AXP_LOGIN_CHALLENGE_PROVIDER, AXP_OAUTH_PKCE_VERIFIER_KEY, AXP_PERMISSION_CHECKER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_PERMISSION_MODULES_RESOLVER, AXP_PLATFORM_OAUTH_CSRF_COOKIE, AXP_TENANT_LOADER, AXP_USER_AVATAR_CACHE_PORT, DEFINITIVE_AUTH_REFRESH_CODES, JwtUtil, MAX_ACTIVE_DEVICE_SESSIONS_CODE, PkceUtil, TimeUtil, asAuthListProvidersResponse, clearOAuthPendingStrategy, clearSessionLimitPendingTenant, commandMessageTextForError, exchangePlatformOAuthAuthorizationCode, fetchPlatformOAuthDiscoveryDocument, findIdentityProvider, getOAuthPendingStrategy, hasLegacyOAuthPkceVerifier, hasOAuthPendingFlow, initPlatformOAuthAuthorization, isDefinitiveAuthRefreshFailure, isMaxActiveDeviceSessionsError, isMissingAccessTokenError, isOAuthRedirectInFlight, platformOAuthSessionUpdateParams, readPlatformOAuthCsrfToken, readSessionLimitPendingTenant, resolvePlatformOAuthAuthorizeEndpoint, resolvePlatformOAuthClientConfig, resolvePlatformOAuthIssuer, resolvePlatformOAuthRedirectUri, resolvePlatformOAuthTokenEndpoint, resolveStatusAfterSoftRestore, setOAuthPendingStrategy, shouldPlatformOAuthBindSession, shouldRetryAccessPolicyAuthorization, storeSessionLimitPendingTenant, toPlatformOAuthSignInResult, traceAuthAccessPolicy, traceAuthCatalog, traceAuthGuard, traceAuthLifecycle, traceAuthLifecycleError, traceAuthRestore, traceAuthWorkspace, warnAuthAccessPolicy, warnAuthLifecycle, warnAuthWorkspace };
2830
2898
  //# sourceMappingURL=acorex-platform-framework-client-auth.mjs.map