@abpjs/saas 2.7.0 → 3.0.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.
package/dist/index.mjs CHANGED
@@ -1,3 +1,61 @@
1
+ // src/config/enums/policy-names.ts
2
+ var eSaasPolicyNames = {
3
+ /** Policy for SaaS module (Tenants OR Editions) */
4
+ Saas: "Saas.Tenants || Saas.Editions",
5
+ /** Policy for Tenants management */
6
+ Tenants: "Saas.Tenants",
7
+ /** Policy for Editions management */
8
+ Editions: "Saas.Editions"
9
+ };
10
+
11
+ // src/config/enums/route-names.ts
12
+ var eSaasRouteNames = {
13
+ /** SaaS menu route name */
14
+ Saas: "Saas::Menu:Saas",
15
+ /** Tenants route name */
16
+ Tenants: "Saas::Tenants",
17
+ /** Editions route name */
18
+ Editions: "Saas::Editions"
19
+ };
20
+
21
+ // src/config/providers/route.provider.ts
22
+ var SAAS_ROUTE_CONFIG = {
23
+ path: "/saas",
24
+ name: eSaasRouteNames.Saas,
25
+ iconClass: "fas fa-building",
26
+ order: 2,
27
+ requiredPolicy: "Saas.Tenants || Saas.Editions",
28
+ children: [
29
+ {
30
+ path: "tenants",
31
+ name: eSaasRouteNames.Tenants,
32
+ requiredPolicy: "Saas.Tenants",
33
+ order: 1
34
+ },
35
+ {
36
+ path: "editions",
37
+ name: eSaasRouteNames.Editions,
38
+ requiredPolicy: "Saas.Editions",
39
+ order: 2
40
+ }
41
+ ]
42
+ };
43
+ function configureRoutes(routes) {
44
+ return () => {
45
+ routes.add([SAAS_ROUTE_CONFIG]);
46
+ };
47
+ }
48
+ function initializeSaasRoutes(routes) {
49
+ const configure = configureRoutes(routes);
50
+ configure();
51
+ }
52
+ var SAAS_ROUTE_PROVIDERS = {
53
+ /** Configure function factory */
54
+ useFactory: configureRoutes,
55
+ /** Dependencies required by the factory */
56
+ deps: ["RoutesService"]
57
+ };
58
+
1
59
  // src/constants/routes.ts
2
60
  var SAAS_ROUTES = {
3
61
  routes: [
@@ -30,12 +88,45 @@ var eSaasComponents = {
30
88
  Tenants: "Saas.TenantsComponent"
31
89
  };
32
90
 
33
- // src/enums/route-names.ts
34
- var eSaasRouteNames = {
35
- Administration: "AbpUiNavigation::Menu:Administration",
36
- Saas: "Saas::Menu:Saas",
37
- Tenants: "Saas::Tenants",
38
- Editions: "Saas::Editions"
91
+ // src/guards/extensions.guard.ts
92
+ import { useState, useEffect } from "react";
93
+ async function saasExtensionsGuard() {
94
+ return Promise.resolve(true);
95
+ }
96
+ function useSaasExtensionsGuard() {
97
+ const [isLoaded, setIsLoaded] = useState(false);
98
+ const [loading, setLoading] = useState(true);
99
+ useEffect(() => {
100
+ let cancelled = false;
101
+ const checkExtensions = async () => {
102
+ try {
103
+ const result = await saasExtensionsGuard();
104
+ if (!cancelled) {
105
+ setIsLoaded(result);
106
+ setLoading(false);
107
+ }
108
+ } catch {
109
+ if (!cancelled) {
110
+ setIsLoaded(false);
111
+ setLoading(false);
112
+ }
113
+ }
114
+ };
115
+ checkExtensions();
116
+ return () => {
117
+ cancelled = true;
118
+ };
119
+ }, []);
120
+ return { isLoaded, loading };
121
+ }
122
+ var SaasExtensionsGuard = class {
123
+ /**
124
+ * Check if the route can be activated
125
+ * @returns Promise<boolean> - True if navigation should proceed
126
+ */
127
+ async canActivate() {
128
+ return saasExtensionsGuard();
129
+ }
39
130
  };
40
131
 
41
132
  // src/services/saas.service.ts
@@ -417,23 +508,203 @@ var SaasStateService = class {
417
508
  }
418
509
  };
419
510
 
511
+ // src/tokens/extensions.token.ts
512
+ var DEFAULT_EDITIONS_ENTITY_ACTIONS = [
513
+ {
514
+ text: "AbpUi::Edit",
515
+ permission: "Saas.Editions.Update",
516
+ icon: "fa fa-edit"
517
+ },
518
+ {
519
+ text: "Saas::Permission:ManageFeatures",
520
+ permission: "Saas.Editions.ManageFeatures",
521
+ icon: "fa fa-cog"
522
+ },
523
+ {
524
+ text: "AbpUi::Delete",
525
+ permission: "Saas.Editions.Delete",
526
+ icon: "fa fa-trash"
527
+ }
528
+ ];
529
+ var DEFAULT_TENANTS_ENTITY_ACTIONS = [
530
+ {
531
+ text: "AbpUi::Edit",
532
+ permission: "Saas.Tenants.Update",
533
+ icon: "fa fa-edit"
534
+ },
535
+ {
536
+ text: "Saas::Permission:ManageFeatures",
537
+ permission: "Saas.Tenants.ManageFeatures",
538
+ icon: "fa fa-cog"
539
+ },
540
+ {
541
+ text: "Saas::ConnectionStrings",
542
+ permission: "Saas.Tenants.ManageConnectionStrings",
543
+ icon: "fa fa-database"
544
+ },
545
+ {
546
+ text: "AbpUi::Delete",
547
+ permission: "Saas.Tenants.Delete",
548
+ icon: "fa fa-trash"
549
+ }
550
+ ];
551
+ var DEFAULT_SAAS_ENTITY_ACTIONS = {
552
+ [eSaasComponents.Editions]: DEFAULT_EDITIONS_ENTITY_ACTIONS,
553
+ [eSaasComponents.Tenants]: DEFAULT_TENANTS_ENTITY_ACTIONS
554
+ };
555
+ var DEFAULT_EDITIONS_TOOLBAR_ACTIONS = [
556
+ {
557
+ text: "Saas::NewEdition",
558
+ permission: "Saas.Editions.Create",
559
+ icon: "fa fa-plus"
560
+ }
561
+ ];
562
+ var DEFAULT_TENANTS_TOOLBAR_ACTIONS = [
563
+ {
564
+ text: "Saas::NewTenant",
565
+ permission: "Saas.Tenants.Create",
566
+ icon: "fa fa-plus"
567
+ }
568
+ ];
569
+ var DEFAULT_SAAS_TOOLBAR_ACTIONS = {
570
+ [eSaasComponents.Editions]: DEFAULT_EDITIONS_TOOLBAR_ACTIONS,
571
+ [eSaasComponents.Tenants]: DEFAULT_TENANTS_TOOLBAR_ACTIONS
572
+ };
573
+ var DEFAULT_EDITIONS_ENTITY_PROPS = [
574
+ {
575
+ name: "displayName",
576
+ displayName: "Saas::EditionName",
577
+ sortable: true
578
+ }
579
+ ];
580
+ var DEFAULT_TENANTS_ENTITY_PROPS = [
581
+ {
582
+ name: "name",
583
+ displayName: "Saas::TenantName",
584
+ sortable: true
585
+ },
586
+ {
587
+ name: "editionName",
588
+ displayName: "Saas::EditionName",
589
+ sortable: false
590
+ }
591
+ ];
592
+ var DEFAULT_SAAS_ENTITY_PROPS = {
593
+ [eSaasComponents.Editions]: DEFAULT_EDITIONS_ENTITY_PROPS,
594
+ [eSaasComponents.Tenants]: DEFAULT_TENANTS_ENTITY_PROPS
595
+ };
596
+ var DEFAULT_EDITIONS_CREATE_FORM_PROPS = [
597
+ {
598
+ name: "displayName",
599
+ displayName: "Saas::EditionName",
600
+ type: "string",
601
+ validators: [
602
+ { type: "required", message: "Saas::EditionNameIsRequired" },
603
+ { type: "maxLength", value: 256 }
604
+ ]
605
+ }
606
+ ];
607
+ var DEFAULT_TENANTS_CREATE_FORM_PROPS = [
608
+ {
609
+ name: "name",
610
+ displayName: "Saas::TenantName",
611
+ type: "string",
612
+ validators: [
613
+ { type: "required", message: "Saas::TenantNameIsRequired" },
614
+ { type: "maxLength", value: 256 }
615
+ ]
616
+ },
617
+ {
618
+ name: "editionId",
619
+ displayName: "Saas::Edition",
620
+ type: "select",
621
+ options: []
622
+ },
623
+ {
624
+ name: "adminEmailAddress",
625
+ displayName: "Saas::AdminEmailAddress",
626
+ type: "string",
627
+ validators: [
628
+ { type: "required", message: "Saas::AdminEmailAddressIsRequired" },
629
+ { type: "email" }
630
+ ]
631
+ },
632
+ {
633
+ name: "adminPassword",
634
+ displayName: "Saas::AdminPassword",
635
+ type: "string",
636
+ validators: [{ type: "required", message: "Saas::AdminPasswordIsRequired" }]
637
+ }
638
+ ];
639
+ var DEFAULT_SAAS_CREATE_FORM_PROPS = {
640
+ [eSaasComponents.Editions]: DEFAULT_EDITIONS_CREATE_FORM_PROPS,
641
+ [eSaasComponents.Tenants]: DEFAULT_TENANTS_CREATE_FORM_PROPS
642
+ };
643
+ var DEFAULT_EDITIONS_EDIT_FORM_PROPS = [
644
+ {
645
+ name: "displayName",
646
+ displayName: "Saas::EditionName",
647
+ type: "string",
648
+ validators: [
649
+ { type: "required", message: "Saas::EditionNameIsRequired" },
650
+ { type: "maxLength", value: 256 }
651
+ ]
652
+ }
653
+ ];
654
+ var DEFAULT_TENANTS_EDIT_FORM_PROPS = [
655
+ {
656
+ name: "name",
657
+ displayName: "Saas::TenantName",
658
+ type: "string",
659
+ validators: [
660
+ { type: "required", message: "Saas::TenantNameIsRequired" },
661
+ { type: "maxLength", value: 256 }
662
+ ]
663
+ },
664
+ {
665
+ name: "editionId",
666
+ displayName: "Saas::Edition",
667
+ type: "select",
668
+ options: []
669
+ }
670
+ ];
671
+ var DEFAULT_SAAS_EDIT_FORM_PROPS = {
672
+ [eSaasComponents.Editions]: DEFAULT_EDITIONS_EDIT_FORM_PROPS,
673
+ [eSaasComponents.Tenants]: DEFAULT_TENANTS_EDIT_FORM_PROPS
674
+ };
675
+ var SAAS_ENTITY_ACTION_CONTRIBUTORS = /* @__PURE__ */ Symbol(
676
+ "SAAS_ENTITY_ACTION_CONTRIBUTORS"
677
+ );
678
+ var SAAS_TOOLBAR_ACTION_CONTRIBUTORS = /* @__PURE__ */ Symbol(
679
+ "SAAS_TOOLBAR_ACTION_CONTRIBUTORS"
680
+ );
681
+ var SAAS_ENTITY_PROP_CONTRIBUTORS = /* @__PURE__ */ Symbol(
682
+ "SAAS_ENTITY_PROP_CONTRIBUTORS"
683
+ );
684
+ var SAAS_CREATE_FORM_PROP_CONTRIBUTORS = /* @__PURE__ */ Symbol(
685
+ "SAAS_CREATE_FORM_PROP_CONTRIBUTORS"
686
+ );
687
+ var SAAS_EDIT_FORM_PROP_CONTRIBUTORS = /* @__PURE__ */ Symbol(
688
+ "SAAS_EDIT_FORM_PROP_CONTRIBUTORS"
689
+ );
690
+
420
691
  // src/hooks/useTenants.ts
421
- import { useState, useCallback, useMemo } from "react";
692
+ import { useState as useState2, useCallback, useMemo } from "react";
422
693
  import { useRestService } from "@abpjs/core";
423
694
  function useTenants() {
424
695
  const restService = useRestService();
425
696
  const service = useMemo(() => new SaasService(restService), [restService]);
426
- const [tenants, setTenants] = useState([]);
427
- const [totalCount, setTotalCount] = useState(0);
428
- const [selectedTenant, setSelectedTenant] = useState(null);
429
- const [isLoading, setIsLoading] = useState(false);
430
- const [error, setError] = useState(null);
431
- const [sortKey, setSortKey] = useState("name");
432
- const [sortOrder, setSortOrder] = useState("");
433
- const [defaultConnectionString, setDefaultConnectionString] = useState("");
434
- const [useSharedDatabase, setUseSharedDatabase] = useState(true);
435
- const [visibleFeatures, setVisibleFeatures] = useState(false);
436
- const [featuresProviderKey, setFeaturesProviderKey] = useState("");
697
+ const [tenants, setTenants] = useState2([]);
698
+ const [totalCount, setTotalCount] = useState2(0);
699
+ const [selectedTenant, setSelectedTenant] = useState2(null);
700
+ const [isLoading, setIsLoading] = useState2(false);
701
+ const [error, setError] = useState2(null);
702
+ const [sortKey, setSortKey] = useState2("name");
703
+ const [sortOrder, setSortOrder] = useState2("");
704
+ const [defaultConnectionString, setDefaultConnectionString] = useState2("");
705
+ const [useSharedDatabase, setUseSharedDatabase] = useState2(true);
706
+ const [visibleFeatures, setVisibleFeatures] = useState2(false);
707
+ const [featuresProviderKey, setFeaturesProviderKey] = useState2("");
437
708
  const fetchTenants = useCallback(
438
709
  async (params) => {
439
710
  setIsLoading(true);
@@ -629,21 +900,21 @@ function useTenants() {
629
900
  }
630
901
 
631
902
  // src/hooks/useEditions.ts
632
- import { useState as useState2, useCallback as useCallback2, useMemo as useMemo2 } from "react";
903
+ import { useState as useState3, useCallback as useCallback2, useMemo as useMemo2 } from "react";
633
904
  import { useRestService as useRestService2 } from "@abpjs/core";
634
905
  function useEditions() {
635
906
  const restService = useRestService2();
636
907
  const service = useMemo2(() => new SaasService(restService), [restService]);
637
- const [editions, setEditions] = useState2([]);
638
- const [totalCount, setTotalCount] = useState2(0);
639
- const [selectedEdition, setSelectedEdition] = useState2(null);
640
- const [isLoading, setIsLoading] = useState2(false);
641
- const [error, setError] = useState2(null);
642
- const [sortKey, setSortKey] = useState2("displayName");
643
- const [sortOrder, setSortOrder] = useState2("");
644
- const [usageStatistics, setUsageStatistics] = useState2({});
645
- const [visibleFeatures, setVisibleFeatures] = useState2(false);
646
- const [featuresProviderKey, setFeaturesProviderKey] = useState2("");
908
+ const [editions, setEditions] = useState3([]);
909
+ const [totalCount, setTotalCount] = useState3(0);
910
+ const [selectedEdition, setSelectedEdition] = useState3(null);
911
+ const [isLoading, setIsLoading] = useState3(false);
912
+ const [error, setError] = useState3(null);
913
+ const [sortKey, setSortKey] = useState3("displayName");
914
+ const [sortOrder, setSortOrder] = useState3("");
915
+ const [usageStatistics, setUsageStatistics] = useState3({});
916
+ const [visibleFeatures, setVisibleFeatures] = useState3(false);
917
+ const [featuresProviderKey, setFeaturesProviderKey] = useState3("");
647
918
  const fetchEditions = useCallback2(
648
919
  async (params) => {
649
920
  setIsLoading(true);
@@ -796,9 +1067,9 @@ function useEditions() {
796
1067
  }
797
1068
 
798
1069
  // src/components/Tenants/TenantsComponent.tsx
799
- import { useEffect, useState as useState3, useCallback as useCallback3 } from "react";
1070
+ import { useEffect as useEffect2, useState as useState4, useCallback as useCallback3 } from "react";
800
1071
  import { useLocalization } from "@abpjs/core";
801
- import { Modal, Button, FormField, useConfirmation, Toaster } from "@abpjs/theme-shared";
1072
+ import { Modal, Button, FormField, useConfirmation, Confirmation } from "@abpjs/theme-shared";
802
1073
  import {
803
1074
  Box,
804
1075
  Flex,
@@ -835,19 +1106,19 @@ function TenantsComponent({
835
1106
  setSelectedTenant
836
1107
  } = useTenants();
837
1108
  const { editions, fetchEditions } = useEditions();
838
- const [modalType, setModalType] = useState3(null);
839
- const [modalVisible, setModalVisible] = useState3(false);
840
- const [modalBusy, setModalBusy] = useState3(false);
841
- const [page, setPage] = useState3(0);
1109
+ const [modalType, setModalType] = useState4(null);
1110
+ const [modalVisible, setModalVisible] = useState4(false);
1111
+ const [modalBusy, setModalBusy] = useState4(false);
1112
+ const [page, setPage] = useState4(0);
842
1113
  const pageSize = 10;
843
- const [filter, setFilter] = useState3("");
844
- const [tenantName, setTenantName] = useState3("");
845
- const [tenantEditionId, setTenantEditionId] = useState3("");
846
- const [adminEmailAddress, setAdminEmailAddress] = useState3("");
847
- const [adminPassword, setAdminPassword] = useState3("");
848
- const [connStringUseShared, setConnStringUseShared] = useState3(true);
849
- const [connString, setConnString] = useState3("");
850
- useEffect(() => {
1114
+ const [filter, setFilter] = useState4("");
1115
+ const [tenantName, setTenantName] = useState4("");
1116
+ const [tenantEditionId, setTenantEditionId] = useState4("");
1117
+ const [adminEmailAddress, setAdminEmailAddress] = useState4("");
1118
+ const [adminPassword, setAdminPassword] = useState4("");
1119
+ const [connStringUseShared, setConnStringUseShared] = useState4(true);
1120
+ const [connString, setConnString] = useState4("");
1121
+ useEffect2(() => {
851
1122
  fetchTenants({
852
1123
  skipCount: page * pageSize,
853
1124
  maxResultCount: pageSize,
@@ -855,7 +1126,7 @@ function TenantsComponent({
855
1126
  getEditionNames: true
856
1127
  });
857
1128
  }, [page, pageSize, fetchTenants]);
858
- useEffect(() => {
1129
+ useEffect2(() => {
859
1130
  fetchEditions();
860
1131
  }, [fetchEditions]);
861
1132
  const handleSearch = useCallback3(() => {
@@ -907,7 +1178,7 @@ function TenantsComponent({
907
1178
  t("Saas::TenantDeletionConfirmationMessage").replace("{0}", tenant.name),
908
1179
  t("Saas::AreYouSure")
909
1180
  );
910
- if (status === Toaster.Status.confirm) {
1181
+ if (status === Confirmation.Status.confirm) {
911
1182
  const result = await deleteTenant(tenant.id);
912
1183
  if (result.success) {
913
1184
  onTenantDeleted?.(tenant.id);
@@ -1189,9 +1460,9 @@ function TenantsComponent({
1189
1460
  }
1190
1461
 
1191
1462
  // src/components/Editions/EditionsComponent.tsx
1192
- import { useEffect as useEffect2, useState as useState4, useCallback as useCallback4 } from "react";
1463
+ import { useEffect as useEffect3, useState as useState5, useCallback as useCallback4 } from "react";
1193
1464
  import { useLocalization as useLocalization2 } from "@abpjs/core";
1194
- import { Modal as Modal2, Button as Button2, FormField as FormField2, useConfirmation as useConfirmation2, Toaster as Toaster2 } from "@abpjs/theme-shared";
1465
+ import { Modal as Modal2, Button as Button2, FormField as FormField2, useConfirmation as useConfirmation2, Confirmation as Confirmation2 } from "@abpjs/theme-shared";
1195
1466
  import {
1196
1467
  Box as Box2,
1197
1468
  Flex as Flex2,
@@ -1223,13 +1494,13 @@ function EditionsComponent({
1223
1494
  deleteEdition,
1224
1495
  setSelectedEdition
1225
1496
  } = useEditions();
1226
- const [modalVisible, setModalVisible] = useState4(false);
1227
- const [modalBusy, setModalBusy] = useState4(false);
1228
- const [page, setPage] = useState4(0);
1497
+ const [modalVisible, setModalVisible] = useState5(false);
1498
+ const [modalBusy, setModalBusy] = useState5(false);
1499
+ const [page, setPage] = useState5(0);
1229
1500
  const pageSize = 10;
1230
- const [filter, setFilter] = useState4("");
1231
- const [displayName, setDisplayName] = useState4("");
1232
- useEffect2(() => {
1501
+ const [filter, setFilter] = useState5("");
1502
+ const [displayName, setDisplayName] = useState5("");
1503
+ useEffect3(() => {
1233
1504
  fetchEditions({
1234
1505
  skipCount: page * pageSize,
1235
1506
  maxResultCount: pageSize,
@@ -1265,7 +1536,7 @@ function EditionsComponent({
1265
1536
  t("Saas::EditionDeletionConfirmationMessage").replace("{0}", edition.displayName),
1266
1537
  t("Saas::AreYouSure")
1267
1538
  );
1268
- if (status === Toaster2.Status.confirm) {
1539
+ if (status === Confirmation2.Status.confirm) {
1269
1540
  const result = await deleteEdition(edition.id);
1270
1541
  if (result.success) {
1271
1542
  onEditionDeleted?.(edition.id);
@@ -1446,13 +1717,41 @@ function EditionsComponent({
1446
1717
  ] });
1447
1718
  }
1448
1719
  export {
1720
+ DEFAULT_EDITIONS_CREATE_FORM_PROPS,
1721
+ DEFAULT_EDITIONS_EDIT_FORM_PROPS,
1722
+ DEFAULT_EDITIONS_ENTITY_ACTIONS,
1723
+ DEFAULT_EDITIONS_ENTITY_PROPS,
1724
+ DEFAULT_EDITIONS_TOOLBAR_ACTIONS,
1725
+ DEFAULT_SAAS_CREATE_FORM_PROPS,
1726
+ DEFAULT_SAAS_EDIT_FORM_PROPS,
1727
+ DEFAULT_SAAS_ENTITY_ACTIONS,
1728
+ DEFAULT_SAAS_ENTITY_PROPS,
1729
+ DEFAULT_SAAS_TOOLBAR_ACTIONS,
1730
+ DEFAULT_TENANTS_CREATE_FORM_PROPS,
1731
+ DEFAULT_TENANTS_EDIT_FORM_PROPS,
1732
+ DEFAULT_TENANTS_ENTITY_ACTIONS,
1733
+ DEFAULT_TENANTS_ENTITY_PROPS,
1734
+ DEFAULT_TENANTS_TOOLBAR_ACTIONS,
1449
1735
  EditionsComponent,
1736
+ SAAS_CREATE_FORM_PROP_CONTRIBUTORS,
1737
+ SAAS_EDIT_FORM_PROP_CONTRIBUTORS,
1738
+ SAAS_ENTITY_ACTION_CONTRIBUTORS,
1739
+ SAAS_ENTITY_PROP_CONTRIBUTORS,
1450
1740
  SAAS_ROUTES,
1741
+ SAAS_ROUTE_CONFIG,
1742
+ SAAS_ROUTE_PROVIDERS,
1743
+ SAAS_TOOLBAR_ACTION_CONTRIBUTORS,
1744
+ SaasExtensionsGuard,
1451
1745
  SaasService,
1452
1746
  SaasStateService,
1453
1747
  TenantsComponent,
1748
+ configureRoutes,
1454
1749
  eSaasComponents,
1750
+ eSaasPolicyNames,
1455
1751
  eSaasRouteNames,
1752
+ initializeSaasRoutes,
1753
+ saasExtensionsGuard,
1456
1754
  useEditions,
1755
+ useSaasExtensionsGuard,
1457
1756
  useTenants
1458
1757
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abpjs/saas",
3
- "version": "2.7.0",
3
+ "version": "3.0.0",
4
4
  "description": "ABP Framework SaaS components for React - translated from @volo/abp.ng.saas",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -27,12 +27,12 @@
27
27
  "dependencies": {
28
28
  "@chakra-ui/react": "^3.2.0",
29
29
  "@emotion/react": "^11.11.0",
30
- "@abpjs/core": "2.7.0",
31
- "@abpjs/feature-management": "2.7.0",
32
- "@abpjs/theme-shared": "2.7.0"
30
+ "@abpjs/core": "3.0.0",
31
+ "@abpjs/feature-management": "3.0.0",
32
+ "@abpjs/theme-shared": "3.0.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@volo/abp.ng.saas": "2.7.0",
35
+ "@volo/abp.ng.saas": "3.0.0",
36
36
  "@testing-library/jest-dom": "^6.9.1",
37
37
  "@testing-library/react": "^14.0.0",
38
38
  "@testing-library/user-event": "^14.6.1",