@acorex/platform 21.0.0-next.2 → 21.0.0-next.3

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 (69) hide show
  1. package/auth/index.d.ts +97 -238
  2. package/common/index.d.ts +778 -213
  3. package/core/index.d.ts +562 -433
  4. package/fesm2022/acorex-platform-auth.mjs +160 -200
  5. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  6. package/fesm2022/acorex-platform-common.mjs +1012 -125
  7. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  8. package/fesm2022/acorex-platform-core.mjs +685 -400
  9. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  10. package/fesm2022/acorex-platform-domain.mjs +54 -11
  11. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  12. package/fesm2022/acorex-platform-layout-builder.mjs +412 -270
  13. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  14. package/fesm2022/acorex-platform-layout-components.mjs +2112 -3153
  15. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  16. package/fesm2022/acorex-platform-layout-designer.mjs +7 -7
  17. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  18. package/fesm2022/acorex-platform-layout-entity.mjs +756 -648
  19. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-layout-views.mjs +4 -4
  21. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-layout-widget-core.mjs +248 -174
  23. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  24. package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs → acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs} +2 -2
  25. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +1 -0
  26. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-m8rHZP8L.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs} +2 -2
  27. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +1 -0
  28. package/fesm2022/acorex-platform-layout-widgets.mjs +3058 -1038
  29. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  30. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs → acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs} +26 -5
  31. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +1 -0
  32. package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs → acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs} +4 -5
  33. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs.map +1 -0
  34. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +101 -0
  35. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +1 -0
  36. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.mjs → acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs} +3 -3
  37. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +1 -0
  38. package/fesm2022/acorex-platform-themes-default.mjs +166 -30
  39. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  40. package/fesm2022/acorex-platform-themes-shared.mjs +27 -27
  41. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  42. package/layout/builder/index.d.ts +4 -1
  43. package/layout/components/index.d.ts +405 -327
  44. package/layout/designer/index.d.ts +3 -3
  45. package/layout/entity/index.d.ts +163 -108
  46. package/layout/widget-core/index.d.ts +39 -49
  47. package/layout/widgets/index.d.ts +368 -54
  48. package/package.json +5 -5
  49. package/themes/default/index.d.ts +15 -2
  50. package/themes/shared/index.d.ts +10 -10
  51. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs +0 -50
  52. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs.map +0 -1
  53. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs +0 -42
  54. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs.map +0 -1
  55. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs +0 -55
  56. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs.map +0 -1
  57. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs +0 -50
  58. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs.map +0 -1
  59. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs +0 -48
  60. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs.map +0 -1
  61. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs +0 -42
  62. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs.map +0 -1
  63. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs.map +0 -1
  64. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-m8rHZP8L.mjs.map +0 -1
  65. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs.map +0 -1
  66. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs.map +0 -1
  67. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs +0 -101
  68. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs.map +0 -1
  69. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Injector, Injectable, signal, inject, Input, Directive, provideAppInitializer, Optional, Inject, NgModule, input, output, Component } from '@angular/core';
3
- import { of, map, BehaviorSubject, shareReplay, defaultIfEmpty, switchMap, filter, firstValueFrom, first } from 'rxjs';
4
- import { AXPBroadcastEventService } from '@acorex/platform/core';
2
+ import { InjectionToken, Injector, Injectable, signal, inject, Input, Directive, provideAppInitializer, Optional, Inject, NgModule } from '@angular/core';
3
+ import { AXPBroadcastEventService, AXP_MODULE_PROVIDER_LOADER, AXPModuleProviderRegistry, AXP_SESSION_SERVICE } from '@acorex/platform/core';
5
4
  import { isEmpty } from 'lodash-es';
5
+ import { map, BehaviorSubject, shareReplay, defaultIfEmpty, switchMap, filter, from, first } from 'rxjs';
6
6
 
7
7
  const AXP_APPLICATION_LOADER = new InjectionToken('AXP_APPLICATION_LOADER', {
8
8
  providedIn: 'root',
@@ -11,25 +11,29 @@ const AXP_APPLICATION_LOADER = new InjectionToken('AXP_APPLICATION_LOADER', {
11
11
  },
12
12
  });
13
13
  class AXPApplicationDefaultLoader {
14
- getList(context) {
15
- return of([
14
+ async getList(context) {
15
+ return [
16
16
  {
17
17
  id: '1',
18
18
  name: 'default-app',
19
19
  title: 'Default Application',
20
20
  version: '1.0.0',
21
- editionName: 'Standard',
22
- features: [],
21
+ edition: {
22
+ id: 'default-edition-1',
23
+ title: 'Standard',
24
+ },
23
25
  },
24
26
  {
25
27
  id: '2',
26
28
  name: 'default-app',
27
29
  title: 'Default Application',
28
30
  version: '1.0.0',
29
- editionName: 'Standard',
30
- features: [],
31
+ edition: {
32
+ id: 'default-edition-2',
33
+ title: 'Standard',
34
+ },
31
35
  },
32
- ]);
36
+ ];
33
37
  }
34
38
  }
35
39
 
@@ -40,14 +44,14 @@ const AXP_TENANT_LOADER = new InjectionToken('AXP_TENANT_LOADER', {
40
44
  },
41
45
  });
42
46
  class AXPTenantDefaultLoader {
43
- getList(context) {
44
- return of([
47
+ async getList(context) {
48
+ return [
45
49
  {
46
50
  id: '1',
47
51
  name: 'default-tenant',
48
52
  title: 'Default Tenant',
49
53
  },
50
- ]);
54
+ ];
51
55
  }
52
56
  }
53
57
 
@@ -85,8 +89,8 @@ const AXP_FEATURE_LOADER = new InjectionToken('AXP_FEATURE_LOADER', {
85
89
  },
86
90
  });
87
91
  class AXPFeatureDefaultLoader {
88
- getList(context) {
89
- return of([]);
92
+ async getList(context) {
93
+ return [];
90
94
  }
91
95
  }
92
96
 
@@ -173,6 +177,13 @@ const AXPFeatureGuard = (route, state) => {
173
177
  }));
174
178
  };
175
179
 
180
+ /**
181
+ * Optional injection token for feature checker.
182
+ * If provided, the checker will be called to potentially override
183
+ * feature enablement results based on custom logic.
184
+ */
185
+ const AXP_FEATURE_CHECKER = new InjectionToken('AXP_FEATURE_CHECKER');
186
+
176
187
  const AXP_PERMISSION_LOADER = new InjectionToken('AXP_PERMISSION_LOADER', {
177
188
  providedIn: 'root',
178
189
  factory: () => {
@@ -180,11 +191,18 @@ const AXP_PERMISSION_LOADER = new InjectionToken('AXP_PERMISSION_LOADER', {
180
191
  }
181
192
  });
182
193
  class AXPPermissionDefaultLoader {
183
- getList(context) {
184
- return of([]);
194
+ async getList(context) {
195
+ return [];
185
196
  }
186
197
  }
187
198
 
199
+ /**
200
+ * Optional injection token for permission checker.
201
+ * If provided, the checker will be called to potentially override
202
+ * authorization results based on custom logic.
203
+ */
204
+ const AXP_PERMISSION_CHECKER = new InjectionToken('AXP_PERMISSION_CHECKER');
205
+
188
206
  class AXPSessionContext {
189
207
  get user() {
190
208
  return this._user;
@@ -218,10 +236,13 @@ class AXPSessionService {
218
236
  constructor() {
219
237
  this.eventService = inject(AXPBroadcastEventService);
220
238
  this.authStrategyRegistry = inject(AXPAuthStrategyRegistryService);
239
+ this.injector = inject(Injector);
221
240
  this.permissionLoader = inject(AXP_PERMISSION_LOADER);
222
241
  this.featureLoader = inject(AXP_FEATURE_LOADER);
223
242
  this.tenantLoader = inject(AXP_TENANT_LOADER);
224
243
  this.applicationLoader = inject(AXP_APPLICATION_LOADER);
244
+ this.permissionChecker = inject(AXP_PERMISSION_CHECKER, { optional: true });
245
+ this.featureChecker = inject(AXP_FEATURE_CHECKER, { optional: true });
225
246
  this.status = new BehaviorSubject(AXPSessionStatus.Unauthenticated);
226
247
  this.status$ = this.status.asObservable().pipe(shareReplay(1));
227
248
  // Add loading state to prevent premature redirects
@@ -244,13 +265,22 @@ class AXPSessionService {
244
265
  // Add a new observable that considers loading state
245
266
  this.isAuthenticatedWithLoading$ = this.isLoading$.pipe(switchMap((loading) => {
246
267
  if (loading) {
268
+ // Wait for loading to complete, then return authentication status
247
269
  return this.isLoading$.pipe(filter((isLoading) => !isLoading), switchMap(() => this.isAuthenticated$));
248
270
  }
271
+ // If not loading, return current authentication status
249
272
  return this.isAuthenticated$;
250
273
  }), shareReplay(1));
251
274
  this.isAuthorized$ = this.status$.pipe(map((status) => status === AXPSessionStatus.Authorized), shareReplay(1));
252
275
  }
253
276
  static { this.SESSION_KEY = 'AXP_SESSION'; }
277
+ /**
278
+ * Get module provider loader lazily to avoid circular dependency.
279
+ * ModuleProviderLoader depends on AXPSessionService, which is this service.
280
+ */
281
+ getModuleProviderLoader() {
282
+ return this.injector.get(AXP_MODULE_PROVIDER_LOADER);
283
+ }
254
284
  get user() {
255
285
  const session = this.getSessionData();
256
286
  if (session?.user && !this.currentUserSubject.value) {
@@ -266,7 +296,7 @@ class AXPSessionService {
266
296
  return this.currentTenantSubject.value;
267
297
  }
268
298
  get tenants$() {
269
- return this.tenantLoader.getList(this.getContext());
299
+ return from(this.tenantLoader.getList(this.getContext()));
270
300
  }
271
301
  get application() {
272
302
  const session = this.getSessionData();
@@ -276,7 +306,7 @@ class AXPSessionService {
276
306
  return this.currentApplicationSubject.value;
277
307
  }
278
308
  get applications$() {
279
- return this.applicationLoader.getList(this.getContext());
309
+ return from(this.applicationLoader.getList(this.getContext()));
280
310
  }
281
311
  get permissions() {
282
312
  return this.permissionsSubject.value ?? [];
@@ -291,7 +321,18 @@ class AXPSessionService {
291
321
  if (sessionData) {
292
322
  if (sessionData.user) {
293
323
  this.currentUserSubject.next(sessionData.user);
324
+ // Restore tenant and application from session data
325
+ if (sessionData.tenant) {
326
+ this.currentTenantSubject.next(sessionData.tenant);
327
+ }
328
+ if (sessionData.application) {
329
+ this.currentApplicationSubject.next(sessionData.application);
330
+ }
294
331
  this.status.next(AXPSessionStatus.Authenticated);
332
+ // Load required modules first to ensure entities are available for loaders
333
+ // This is critical because loaders (like application.loader) need entities
334
+ // from required modules (ApplicationManagement, TenantManagement, SecurityManagement)
335
+ await this.getModuleProviderLoader().loadRequiredModules();
295
336
  await this.loadPermissions();
296
337
  await this.loadFeatures();
297
338
  await this.signInComplete();
@@ -409,6 +450,9 @@ class AXPSessionService {
409
450
  }
410
451
  //
411
452
  const userId = this.user?.id;
453
+ // Clear module provider loader cache before clearing session
454
+ // This ensures modules and providers from previous user are not cached
455
+ await this.getModuleProviderLoader().clear();
412
456
  this.clearSession();
413
457
  this.eventService.publish(AXPSessionStatus.SignedOut, { id: userId });
414
458
  this.isLoading.next(false);
@@ -457,7 +501,7 @@ class AXPSessionService {
457
501
  }
458
502
  async loadPermissions() {
459
503
  try {
460
- const permissions = await firstValueFrom(this.permissionLoader.getList(this.getContext()));
504
+ const permissions = await this.permissionLoader.getList(this.getContext());
461
505
  this.permissionsSubject.next(permissions ?? []);
462
506
  }
463
507
  catch (error) {
@@ -467,7 +511,7 @@ class AXPSessionService {
467
511
  }
468
512
  async loadFeatures() {
469
513
  try {
470
- const features = await firstValueFrom(this.featureLoader.getList(this.getContext()));
514
+ const features = await this.featureLoader.getList(this.getContext());
471
515
  this.featuresSubject.next(features ?? []);
472
516
  }
473
517
  catch (error) {
@@ -547,26 +591,39 @@ class AXPSessionService {
547
591
  localStorage.removeItem(AXPSessionService.SESSION_KEY);
548
592
  }
549
593
  authorize(...keys) {
550
- return keys.every((k) => isEmpty(k) || this.permissions.indexOf(k) > -1 || this.user?.name == 'root');
594
+ // Calculate base result
595
+ const baseResult = keys.every((k) => {
596
+ if (isEmpty(k))
597
+ return true;
598
+ // Check if user has the permission
599
+ const hasPermission = this.permissions.indexOf(k) > -1;
600
+ if (!hasPermission)
601
+ return false;
602
+ // Check if permission has required features (if permission definition service is available)
603
+ // Note: This is a lightweight check. Full feature validation happens in permission definition service.
604
+ return true;
605
+ });
606
+ // If permission checker is provided, use it to potentially override the result
607
+ if (this.permissionChecker) {
608
+ const context = this.getContext();
609
+ return this.permissionChecker.check(keys, context, baseResult);
610
+ }
611
+ return baseResult;
551
612
  }
552
613
  isFeatureEnabled(...keys) {
553
- return keys.every((k) => isEmpty(k) || this.features.some((c) => c.name == k && c.value == true));
614
+ // Calculate base result
615
+ const baseResult = keys.every((k) => isEmpty(k) || this.features.some((c) => c.name == k && c.value == true));
616
+ // If feature checker is provided, use it to potentially override the result
617
+ if (this.featureChecker) {
618
+ const context = this.getContext();
619
+ return this.featureChecker.check(keys, context, baseResult);
620
+ }
621
+ return baseResult;
554
622
  }
555
623
  getToken() {
556
624
  const sessionData = this.getSessionData();
557
625
  return sessionData?.accessToken;
558
626
  }
559
- checkTokenValidation() {
560
- let sessionData = this.getSessionData();
561
- if (sessionData && sessionData?.accessToken && sessionData.expiresIn) {
562
- const expiresInDate = new Date(sessionData.expiresIn);
563
- if (expiresInDate > new Date()) {
564
- // Token is still valid
565
- return true;
566
- }
567
- }
568
- return false;
569
- }
570
627
  getContext() {
571
628
  return new AXPSessionContext({
572
629
  user: this.user,
@@ -687,12 +744,13 @@ class AXPPermissionDefinitionGroupBuilder {
687
744
  this.context = context;
688
745
  this._group = group;
689
746
  }
690
- addPermission(name, title, description) {
747
+ addPermission(name, title, description, requiredFeatures) {
691
748
  const permission = {
692
749
  name,
693
750
  title,
694
751
  description,
695
- children: []
752
+ children: [],
753
+ requiredFeatures
696
754
  };
697
755
  this._group.permissions.push(permission);
698
756
  return new AXPPermissionDefinitionBuilder(this, permission);
@@ -712,16 +770,25 @@ class AXPPermissionDefinitionBuilder {
712
770
  this.groupBuilder = groupBuilder;
713
771
  this.permission = permission;
714
772
  }
715
- addChild(name, title, description) {
773
+ addChild(name, title, description, requiredFeatures) {
716
774
  const permission = {
717
775
  name,
718
776
  title,
719
777
  description,
720
- children: []
778
+ children: [],
779
+ requiredFeatures
721
780
  };
722
781
  this.permission.children.push(permission);
723
782
  return this;
724
783
  }
784
+ /**
785
+ * Set required features for this permission.
786
+ * @param features - Array of feature names (e.g., ['PlatformManagement.menu-customization'])
787
+ */
788
+ requireFeatures(...features) {
789
+ this.permission.requiredFeatures = features;
790
+ return this;
791
+ }
725
792
  endPermission() {
726
793
  return this.groupBuilder;
727
794
  }
@@ -736,6 +803,8 @@ const AXP_PERMISSION_DEFINITION_PROVIDER = new InjectionToken('AXP_PERMISSION_DE
736
803
  class AXPPermissionDefinitionService {
737
804
  constructor() {
738
805
  this.providers = inject(AXP_PERMISSION_DEFINITION_PROVIDER, { optional: true });
806
+ this.providerRegistry = inject(AXPModuleProviderRegistry);
807
+ this.sessionService = inject(AXPSessionService);
739
808
  this.cache = null;
740
809
  }
741
810
  async load() {
@@ -743,6 +812,7 @@ class AXPPermissionDefinitionService {
743
812
  return;
744
813
  }
745
814
  const context = new AXPPermissionDefinitionProviderContext();
815
+ // Load providers from DI tokens (backward compatibility)
746
816
  if (Array.isArray(this.providers)) {
747
817
  for (const provider of this.providers) {
748
818
  if (provider instanceof Promise) {
@@ -756,7 +826,49 @@ class AXPPermissionDefinitionService {
756
826
  }
757
827
  }
758
828
  }
759
- this.cache = context.getGroupDefinitions();
829
+ // Load providers from registry (manifest-based, conditionally loaded)
830
+ const registryProviders = this.providerRegistry.getPermissionProviders();
831
+ for (const provider of registryProviders) {
832
+ await provider.define(context);
833
+ }
834
+ // Filter permissions based on required features
835
+ const allGroups = context.getGroupDefinitions();
836
+ this.cache = this.filterByFeatures(allGroups);
837
+ }
838
+ /**
839
+ * Filter permissions based on required features.
840
+ * Removes permissions that have required features that are not enabled.
841
+ */
842
+ filterByFeatures(groups) {
843
+ return groups.map(group => ({
844
+ ...group,
845
+ permissions: this.filterPermissions(group.permissions)
846
+ })).filter(group => group.permissions.length > 0);
847
+ }
848
+ /**
849
+ * Recursively filter permissions and their children based on required features.
850
+ */
851
+ filterPermissions(permissions) {
852
+ return permissions
853
+ .filter(permission => {
854
+ // Check if required features are enabled
855
+ if (permission.requiredFeatures && permission.requiredFeatures.length > 0) {
856
+ const allFeaturesEnabled = permission.requiredFeatures.every(featureName => this.sessionService.isFeatureEnabled(featureName));
857
+ if (!allFeaturesEnabled) {
858
+ return false; // Filter out this permission
859
+ }
860
+ }
861
+ return true;
862
+ })
863
+ .map(permission => ({
864
+ ...permission,
865
+ children: this.filterPermissions(permission.children)
866
+ }))
867
+ .filter(permission => {
868
+ // Remove permissions that have no children if they were only containers
869
+ // (This is optional - you might want to keep parent permissions even without children)
870
+ return true;
871
+ });
760
872
  }
761
873
  async reload() {
762
874
  this.cache = null;
@@ -882,6 +994,10 @@ class AXPAuthModule {
882
994
  const initializerFn = initializeAppState(inject(AXPSessionService));
883
995
  return initializerFn();
884
996
  }),
997
+ {
998
+ provide: AXP_SESSION_SERVICE,
999
+ useExisting: AXPSessionService,
1000
+ },
885
1001
  ] }); }
886
1002
  }
887
1003
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPAuthModule, decorators: [{
@@ -895,6 +1011,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
895
1011
  const initializerFn = initializeAppState(inject(AXPSessionService));
896
1012
  return initializerFn();
897
1013
  }),
1014
+ {
1015
+ provide: AXP_SESSION_SERVICE,
1016
+ useExisting: AXPSessionService,
1017
+ },
898
1018
  ],
899
1019
  }]
900
1020
  }], ctorParameters: () => [{ type: undefined, decorators: [{
@@ -984,169 +1104,9 @@ class TimeUtil {
984
1104
  }
985
1105
  //#endregion
986
1106
 
987
- //#region ---- Challenge Data Types ----
988
- //#endregion
989
-
990
- //#region ---- Abstract Challenge Provider ----
991
- /**
992
- * Abstract base class for login challenge providers
993
- *
994
- * Implement this class to create custom challenge mechanisms like:
995
- * - Image CAPTCHA
996
- * - reCAPTCHA
997
- * - SMS verification
998
- * - Email verification
999
- *
1000
- * @example
1001
- * ```typescript
1002
- * @Injectable()
1003
- * export class MyImageCaptchaProvider extends AXPLoginChallengeProvider {
1004
- * readonly name = 'image-captcha';
1005
- *
1006
- * checkResponse(error: unknown): AXPChallengeCheckResult | null {
1007
- * if (error instanceof HttpErrorResponse) {
1008
- * if (error.error?.requiresCaptcha) {
1009
- * return { required: true };
1010
- * }
1011
- * }
1012
- * return null;
1013
- * }
1014
- *
1015
- * async getChallenge(): Promise<AXPLoginChallengeData> {
1016
- * const response = await this.http.get('/api/captcha').toPromise();
1017
- * return {
1018
- * id: response.id,
1019
- * content: response.image,
1020
- * contentType: 'image-base64'
1021
- * };
1022
- * }
1023
- *
1024
- * async refreshChallenge(): Promise<AXPLoginChallengeData> {
1025
- * return this.getChallenge();
1026
- * }
1027
- *
1028
- * getChallengeComponent(): Type<AXPLoginChallengeComponentBase> {
1029
- * return MyCaptchaChallengeComponent;
1030
- * }
1031
- * }
1032
- * ```
1033
- */
1034
- class AXPLoginChallengeProvider {
1035
- /**
1036
- * Returns the component type for rendering the challenge UI
1037
- *
1038
- * Override this method to provide a custom challenge UI component.
1039
- * If not overridden (returns null), the login component will use
1040
- * a default built-in UI.
1041
- *
1042
- * @returns Component type extending AXPLoginChallengeComponentBase, or null for default UI
1043
- */
1044
- getChallengeComponent() {
1045
- return null;
1046
- }
1047
- }
1048
- //#endregion
1049
-
1050
- //#region ---- Injection Token ----
1051
- /**
1052
- * Injection token for the login challenge provider
1053
- *
1054
- * This token is optional - if not provided, no challenge mechanism will be used.
1055
- *
1056
- * @example
1057
- * ```typescript
1058
- * // In your app module or provider configuration:
1059
- * providers: [
1060
- * {
1061
- * provide: AXP_LOGIN_CHALLENGE_PROVIDER,
1062
- * useClass: MyImageCaptchaProvider
1063
- * }
1064
- * ]
1065
- *
1066
- * // In a component:
1067
- * private challengeProvider = inject(AXP_LOGIN_CHALLENGE_PROVIDER, { optional: true });
1068
- * ```
1069
- */
1070
- const AXP_LOGIN_CHALLENGE_PROVIDER = new InjectionToken('AXP_LOGIN_CHALLENGE_PROVIDER');
1071
- //#endregion
1072
-
1073
- //#region ---- Base Challenge Component ----
1074
- /**
1075
- * Base class for login challenge UI components
1076
- *
1077
- * Providers can extend this class to create custom challenge UIs.
1078
- * The login component will render this component and listen to its outputs.
1079
- *
1080
- * @example
1081
- * ```typescript
1082
- * @Component({
1083
- * selector: 'my-captcha-challenge',
1084
- * template: `
1085
- * <div class="captcha-container">
1086
- * <img [src]="'data:image/png;base64,' + challengeData().content" />
1087
- * <input
1088
- * type="text"
1089
- * [value]="response()"
1090
- * (input)="onResponseChange($event)"
1091
- * />
1092
- * <button (click)="onRefreshClick()">Refresh</button>
1093
- * </div>
1094
- * `
1095
- * })
1096
- * export class MyCaptchaChallengeComponent extends AXPLoginChallengeComponentBase {
1097
- * response = signal('');
1098
- *
1099
- * onResponseChange(event: Event) {
1100
- * const value = (event.target as HTMLInputElement).value;
1101
- * this.response.set(value);
1102
- * this.responseChange.emit(value);
1103
- * }
1104
- *
1105
- * onRefreshClick() {
1106
- * this.refreshRequest.emit();
1107
- * }
1108
- * }
1109
- * ```
1110
- */
1111
- class AXPLoginChallengeComponentBase {
1112
- constructor() {
1113
- //#region ---- Inputs ----
1114
- /**
1115
- * Challenge data to display
1116
- * Contains the image/content and metadata from the server
1117
- */
1118
- this.challengeData = input.required(...(ngDevMode ? [{ debugName: "challengeData" }] : []));
1119
- /**
1120
- * Whether the challenge is currently loading (e.g., refreshing)
1121
- */
1122
- this.isLoading = input(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
1123
- //#endregion
1124
- //#region ---- Outputs ----
1125
- /**
1126
- * Emits when the user enters or changes their response
1127
- * The login component will capture this value and include it in credentials
1128
- */
1129
- this.responseChange = output();
1130
- /**
1131
- * Emits when the user requests a new challenge (e.g., clicks refresh button)
1132
- * The login component will call provider.refreshChallenge()
1133
- */
1134
- this.refreshRequest = output();
1135
- }
1136
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLoginChallengeComponentBase, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1137
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.12", type: AXPLoginChallengeComponentBase, isStandalone: true, selector: "ng-component", inputs: { challengeData: { classPropertyName: "challengeData", publicName: "challengeData", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { responseChange: "responseChange", refreshRequest: "refreshRequest" }, ngImport: i0, template: '', isInline: true }); }
1138
- }
1139
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLoginChallengeComponentBase, decorators: [{
1140
- type: Component,
1141
- args: [{
1142
- template: '',
1143
- standalone: true,
1144
- }]
1145
- }], propDecorators: { challengeData: [{ type: i0.Input, args: [{ isSignal: true, alias: "challengeData", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], responseChange: [{ type: i0.Output, args: ["responseChange"] }], refreshRequest: [{ type: i0.Output, args: ["refreshRequest"] }] } });
1146
-
1147
1107
  /**
1148
1108
  * Generated bundle index. Do not edit.
1149
1109
  */
1150
1110
 
1151
- export { AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureGuard, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPUnauthorizedError, AXP_APPLICATION_LOADER, AXP_FEATURE_LOADER, AXP_LOGIN_CHALLENGE_PROVIDER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, JwtUtil, PkceUtil, TimeUtil, initializeAppState };
1111
+ export { AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureGuard, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPUnauthorizedError, AXP_APPLICATION_LOADER, AXP_FEATURE_CHECKER, AXP_FEATURE_LOADER, AXP_PERMISSION_CHECKER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, JwtUtil, PkceUtil, TimeUtil, initializeAppState };
1152
1112
  //# sourceMappingURL=acorex-platform-auth.mjs.map