@pactor-app/app 1.18.0 → 1.20.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.js CHANGED
@@ -878,14 +878,623 @@ function EmbeddedPage({
878
878
  }
879
879
  return /* @__PURE__ */ jsx5(I18nContextProvider2, { value: i18n, children: /* @__PURE__ */ jsx5(InteractionProvider2, { bridge: assembly.uiBridge, children: content }) });
880
880
  }
881
+
882
+ // src/sitemap/actions.ts
883
+ var defaultSitemapActions = {
884
+ "app.reload": (action) => {
885
+ const to = action.params?.["to"];
886
+ if (typeof window !== "undefined") {
887
+ window.location.assign(typeof to === "string" && to !== "" ? to : "/");
888
+ }
889
+ return { ok: true };
890
+ },
891
+ "service.call": async (action, ctx) => {
892
+ const name = action.params?.["service"];
893
+ if (typeof name !== "string" || name === "") {
894
+ return {
895
+ ok: false,
896
+ error: new Error("[@pactor-app/app] service.call \u7F3A\u5C11 params.service")
897
+ };
898
+ }
899
+ const handler = ctx.context.services.get(name);
900
+ if (!handler) {
901
+ return {
902
+ ok: false,
903
+ error: new Error(`[@pactor-app/app] service \u672A\u6CE8\u518C: ${name}`)
904
+ };
905
+ }
906
+ try {
907
+ const callParams = action.params?.["params"];
908
+ const data = await handler(
909
+ typeof callParams === "object" && callParams !== null ? callParams : {}
910
+ );
911
+ return { ok: true, data };
912
+ } catch (cause) {
913
+ return {
914
+ ok: false,
915
+ error: cause instanceof Error ? cause : new Error(String(cause))
916
+ };
917
+ }
918
+ }
919
+ };
920
+
921
+ // src/sitemap/SitemapApp.tsx
922
+ import { MenuRegistry as MenuRegistry2 } from "@pactor-app/router";
923
+ import { Menu } from "@pactor-app/ui/components";
924
+ import {
925
+ createContext,
926
+ use,
927
+ useEffect as useEffect4,
928
+ useMemo as useMemo2,
929
+ useState as useState4
930
+ } from "react";
931
+
932
+ // src/sitemap/browser-route.ts
933
+ import { useCallback, useMemo, useSyncExternalStore } from "react";
934
+ var NAV_EVENT = "pactor:sitemap-navigate";
935
+ function readLocation() {
936
+ return `${window.location.pathname}${window.location.search}`;
937
+ }
938
+ function subscribe(callback) {
939
+ window.addEventListener("popstate", callback);
940
+ window.addEventListener(NAV_EVENT, callback);
941
+ return () => {
942
+ window.removeEventListener("popstate", callback);
943
+ window.removeEventListener(NAV_EVENT, callback);
944
+ };
945
+ }
946
+ function useBrowserRoute() {
947
+ const location = useSyncExternalStore(
948
+ subscribe,
949
+ readLocation,
950
+ // SSR 快照:服务端无 window,宿主应注入 pathname / navigate
951
+ () => "/"
952
+ );
953
+ const navigate = useCallback((to) => {
954
+ window.history.pushState(null, "", to);
955
+ window.dispatchEvent(new Event(NAV_EVENT));
956
+ }, []);
957
+ return useMemo(() => {
958
+ const qIndex = location.indexOf("?");
959
+ return {
960
+ pathname: qIndex >= 0 ? location.slice(0, qIndex) : location,
961
+ query: Object.fromEntries(
962
+ new URLSearchParams(qIndex >= 0 ? location.slice(qIndex + 1) : "")
963
+ ),
964
+ navigate
965
+ };
966
+ }, [location, navigate]);
967
+ }
968
+
969
+ // src/sitemap/http.ts
970
+ function createHttpHooks(options = {}) {
971
+ const { proxyPrefix } = options;
972
+ const envelope = options.envelope ?? true;
973
+ return {
974
+ request(config) {
975
+ let url = config.url;
976
+ if (proxyPrefix !== void 0 && /^https?:\/\//.test(url) && typeof window !== "undefined" && !url.startsWith(window.location.origin)) {
977
+ const target = new URL(url);
978
+ url = `${proxyPrefix}${target.pathname}${target.search}`;
979
+ }
980
+ const extra = typeof options.headers === "function" ? options.headers() : options.headers;
981
+ return {
982
+ ...config,
983
+ url,
984
+ headers: { ...config.headers, ...extra }
985
+ };
986
+ },
987
+ response(data) {
988
+ if (!envelope) {
989
+ return data;
990
+ }
991
+ if (typeof data === "object" && data !== null && "code" in data && "data" in data) {
992
+ const wrapped = data;
993
+ if (wrapped.code !== 0) {
994
+ throw new Error(wrapped.message ?? `\u4E1A\u52A1\u9519\u8BEF\u7801 ${wrapped.code}`);
995
+ }
996
+ return wrapped.data;
997
+ }
998
+ return data;
999
+ }
1000
+ };
1001
+ }
1002
+ function withHttpHooks(fetcher, hooks) {
1003
+ if (hooks === void 0) {
1004
+ return fetcher;
1005
+ }
1006
+ return (async (input, init) => {
1007
+ let url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1008
+ let requestInit = init;
1009
+ if (hooks.request !== void 0) {
1010
+ const config = await hooks.request({
1011
+ method: init?.method ?? "GET",
1012
+ url,
1013
+ headers: headersToRecord(init?.headers),
1014
+ body: init?.body ?? void 0
1015
+ });
1016
+ url = config.url;
1017
+ requestInit = {
1018
+ ...init,
1019
+ method: config.method ?? init?.method ?? "GET",
1020
+ headers: config.headers,
1021
+ body: config.body === void 0 ? init?.body ?? null : config.body
1022
+ };
1023
+ }
1024
+ const res = await fetcher(url, requestInit);
1025
+ if (hooks.response === void 0 || !res.ok) {
1026
+ return res;
1027
+ }
1028
+ const data = await hooks.response(await res.json());
1029
+ return new Response(JSON.stringify(data), {
1030
+ status: res.status,
1031
+ statusText: res.statusText,
1032
+ headers: res.headers
1033
+ });
1034
+ });
1035
+ }
1036
+ function headersToRecord(headers) {
1037
+ if (headers === void 0) {
1038
+ return void 0;
1039
+ }
1040
+ if (headers instanceof Headers) {
1041
+ return Object.fromEntries(headers.entries());
1042
+ }
1043
+ if (Array.isArray(headers)) {
1044
+ return Object.fromEntries(headers);
1045
+ }
1046
+ return { ...headers };
1047
+ }
1048
+
1049
+ // src/sitemap/url.ts
1050
+ function resolveUrl(url, baseUrl) {
1051
+ if (baseUrl === void 0 || baseUrl === "" || /^(https?:)?\/\//i.test(url)) {
1052
+ return url;
1053
+ }
1054
+ return `${baseUrl.replace(/\/+$/, "")}/${url.replace(/^\/+/, "")}`;
1055
+ }
1056
+
1057
+ // src/sitemap/fetch.ts
1058
+ async function fetchSitemap(sources, options = {}) {
1059
+ const fetcher = withHttpHooks(options.fetcher ?? fetch, options.httpHooks);
1060
+ const responses = await Promise.all(
1061
+ sources.map(async (url) => {
1062
+ const res = await fetcher(resolveUrl(url, options.baseUrl), {
1063
+ cache: "no-store",
1064
+ // 跨源 cookie 会话(服务端开通 CORS + Allow-Credentials 时生效;
1065
+ // 同源行为不变)
1066
+ credentials: "include"
1067
+ });
1068
+ if (!res.ok) {
1069
+ throw new Error(`[@pactor-app/app] sitemap \u6E90 ${url} \u8BF7\u6C42\u5931\u8D25\uFF1AHTTP ${res.status}`);
1070
+ }
1071
+ return await res.json();
1072
+ })
1073
+ );
1074
+ if (responses.length === 0) {
1075
+ throw new Error("[@pactor-app/app] sources \u4E3A\u7A7A\uFF1A\u8BF7\u914D\u7F6E\u81F3\u5C11\u4E00\u4E2A sitemap \u63A5\u53E3 URL");
1076
+ }
1077
+ const [first, ...rest] = responses;
1078
+ const merged = {
1079
+ ...first,
1080
+ layouts: { ...first.layouts },
1081
+ pages: [...first.pages],
1082
+ menus: [...first.menus]
1083
+ };
1084
+ for (const source of rest) {
1085
+ mergeById(merged.pages, source.pages, "pages");
1086
+ mergeById(merged.menus, source.menus, "menus");
1087
+ for (const [name, layout] of Object.entries(source.layouts ?? {})) {
1088
+ if (merged.layouts[name] !== void 0) {
1089
+ console.warn(`[@pactor-app/app] sitemap layouts \u952E\u51B2\u7A81\uFF1A${name}\uFF0C\u540E\u6E90\u8986\u76D6\u524D\u6E90`);
1090
+ }
1091
+ merged.layouts[name] = layout;
1092
+ }
1093
+ }
1094
+ return merged;
1095
+ }
1096
+ function mergeById(target, incoming, label) {
1097
+ for (const item of incoming) {
1098
+ const index = target.findIndex(
1099
+ (t) => t.id === item.id || item.path !== void 0 && t.path === item.path
1100
+ );
1101
+ if (index >= 0) {
1102
+ console.warn(`[@pactor-app/app] sitemap ${label} \u51B2\u7A81\uFF1A${item.id}\uFF0C\u540E\u6E90\u8986\u76D6\u524D\u6E90`);
1103
+ target[index] = item;
1104
+ } else {
1105
+ target.push(item);
1106
+ }
1107
+ }
1108
+ }
1109
+
1110
+ // src/sitemap/loader.ts
1111
+ var defaultPageEndpoint = (pageId) => `/api/pages/${pageId}`;
1112
+ function createSitemapLoader(sitemap, options = {}) {
1113
+ const pageEndpoint = options.pageEndpoint ?? defaultPageEndpoint;
1114
+ const sessionService = options.sessionService ?? "session.context";
1115
+ const fetcher = withHttpHooks(options.fetcher ?? fetch, options.httpHooks);
1116
+ const pageById = new Map(sitemap.pages.map((p) => [p.id, p]));
1117
+ const cache = /* @__PURE__ */ new Map();
1118
+ return {
1119
+ async loadPage(pageId) {
1120
+ const entry = pageById.get(pageId);
1121
+ const version = entry?.version ?? 1;
1122
+ const cacheKey = `${pageId}@${version}`;
1123
+ const hit = cache.get(cacheKey);
1124
+ if (hit) {
1125
+ return hit;
1126
+ }
1127
+ let resource;
1128
+ if (entry?.pageDsl !== void 0) {
1129
+ resource = {
1130
+ id: pageId,
1131
+ resourceType: "page",
1132
+ version,
1133
+ dslVersion: entry.pageDsl.dsl ?? "1.0",
1134
+ schema: entry.pageDsl
1135
+ };
1136
+ } else {
1137
+ const res = await fetcher(resolveUrl(pageEndpoint(pageId), options.baseUrl), {
1138
+ cache: "no-store",
1139
+ credentials: "include"
1140
+ });
1141
+ if (!res.ok) {
1142
+ throw new Error(
1143
+ `[@pactor-app/app] \u9875\u9762 ${pageId} \u52A0\u8F7D\u5931\u8D25\uFF1AHTTP ${res.status}`
1144
+ );
1145
+ }
1146
+ resource = await res.json();
1147
+ }
1148
+ if (typeof resource.schema === "object" && resource.schema !== null) {
1149
+ const schema = resource.schema;
1150
+ schema.dataSources = {
1151
+ session: { type: "service", service: sessionService, autoLoad: true },
1152
+ ...schema.dataSources
1153
+ };
1154
+ }
1155
+ cache.set(cacheKey, resource);
1156
+ return resource;
1157
+ },
1158
+ async loadFragment(fragmentId) {
1159
+ throw new Error(`[@pactor-app/app] \u672A\u5B9E\u73B0\u7684 fragment \u52A0\u8F7D\uFF1A${fragmentId}`);
1160
+ },
1161
+ async loadBootstrap() {
1162
+ return sitemap;
1163
+ }
1164
+ };
1165
+ }
1166
+
1167
+ // src/sitemap/merge.ts
1168
+ function mergeSitemapMenus(sitemap) {
1169
+ const pageById = new Map(sitemap.pages.map((p) => [p.id, p]));
1170
+ const walk = (items) => items.map((item) => {
1171
+ const page = item.pageId !== void 0 ? pageById.get(item.pageId) : void 0;
1172
+ const merged = {
1173
+ ...item,
1174
+ path: item.path ?? page?.path,
1175
+ title: item.title ?? page?.title ?? item.id
1176
+ };
1177
+ if (item.children !== void 0) {
1178
+ merged.children = walk(item.children);
1179
+ }
1180
+ return merged;
1181
+ });
1182
+ return walk(sitemap.menus ?? []);
1183
+ }
1184
+ function toSitemapNavItems(menuTree) {
1185
+ return menuTree.map((item) => ({
1186
+ key: item.path ?? item.id,
1187
+ label: item.title,
1188
+ icon: item.icon,
1189
+ disabled: item.disabled,
1190
+ children: item.children !== void 0 ? toSitemapNavItems(item.children) : void 0
1191
+ }));
1192
+ }
1193
+
1194
+ // src/sitemap/route.ts
1195
+ function resolveSitemapRoute(sitemap, registry, pathname) {
1196
+ const match = registry.findByPath(pathname);
1197
+ const menu = match?.menu ?? null;
1198
+ if (match === null || menu === null || menu.pageId === void 0) {
1199
+ return { menu, route: null };
1200
+ }
1201
+ const layoutName = menu.layout ?? sitemap.layout ?? Object.keys(sitemap.layouts)[0] ?? "";
1202
+ const highlightId = menu.activeMenu ?? menu.id;
1203
+ const highlightItem = registry.findById(highlightId);
1204
+ return {
1205
+ menu,
1206
+ route: {
1207
+ pageId: menu.pageId,
1208
+ layoutName,
1209
+ highlightKey: highlightItem?.path ?? highlightId,
1210
+ params: match.params
1211
+ }
1212
+ };
1213
+ }
1214
+ var defaultSitemapGuard = ({
1215
+ sitemap,
1216
+ pathname,
1217
+ menu
1218
+ }) => {
1219
+ const loginPath = sitemap.auth?.loginPath ?? "/login";
1220
+ if (sitemap.user === void 0 && pathname !== loginPath && (menu === null || menu.public !== true)) {
1221
+ return { allow: false, redirectTo: loginPath };
1222
+ }
1223
+ return { allow: true };
1224
+ };
1225
+
1226
+ // src/sitemap/session.ts
1227
+ function createSitemapSessionServices(session, serviceName = "session.context") {
1228
+ return {
1229
+ [serviceName]: () => Promise.resolve(session)
1230
+ };
1231
+ }
1232
+
1233
+ // src/sitemap/SitemapApp.tsx
1234
+ import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
1235
+ var OutletContext = createContext(null);
1236
+ function PageOutlet() {
1237
+ return use(OutletContext);
1238
+ }
1239
+ var NavHighlightContext = createContext("");
1240
+ function SitemapMenu({
1241
+ items,
1242
+ collapsible,
1243
+ onSelect
1244
+ }) {
1245
+ const highlight = use(NavHighlightContext);
1246
+ return /* @__PURE__ */ jsx6(
1247
+ Menu,
1248
+ {
1249
+ items,
1250
+ collapsible,
1251
+ selectedKey: highlight,
1252
+ onSelect
1253
+ }
1254
+ );
1255
+ }
1256
+ function SitemapApp(props) {
1257
+ const { sources, fetcher, baseUrl } = props;
1258
+ const browserRoute = useBrowserRoute();
1259
+ const pathname = props.pathname ?? browserRoute.pathname;
1260
+ const query = props.query ?? browserRoute.query;
1261
+ const navigate = props.navigate ?? browserRoute.navigate;
1262
+ const [state, setState] = useState4({ status: "loading" });
1263
+ useEffect4(() => {
1264
+ let cancelled = false;
1265
+ setState({ status: "loading" });
1266
+ fetchSitemap(sources, {
1267
+ fetcher,
1268
+ baseUrl,
1269
+ httpHooks: props.httpAdapter
1270
+ }).then((sitemap2) => {
1271
+ if (!cancelled) {
1272
+ setState({ status: "ready", sitemap: sitemap2 });
1273
+ }
1274
+ }).catch((error) => {
1275
+ if (!cancelled) {
1276
+ setState({
1277
+ status: "error",
1278
+ error: error instanceof Error ? error : new Error(String(error))
1279
+ });
1280
+ }
1281
+ });
1282
+ return () => {
1283
+ cancelled = true;
1284
+ };
1285
+ }, [fetcher, baseUrl, props.httpAdapter, JSON.stringify(sources)]);
1286
+ const registry = useMemo2(
1287
+ () => state.status === "ready" ? new MenuRegistry2(mergeSitemapMenus(state.sitemap)) : null,
1288
+ [state]
1289
+ );
1290
+ const resolution = useMemo2(
1291
+ () => state.status === "ready" && registry !== null ? resolveSitemapRoute(state.sitemap, registry, pathname) : null,
1292
+ [state, registry, pathname]
1293
+ );
1294
+ const sitemap = state.status === "ready" ? state.sitemap : null;
1295
+ const guard = props.guard ?? defaultSitemapGuard;
1296
+ const decision = useMemo2(
1297
+ () => sitemap !== null && resolution !== null ? guard({ sitemap, pathname, menu: resolution.menu }) : { allow: true },
1298
+ [sitemap, resolution, guard, pathname]
1299
+ );
1300
+ useEffect4(() => {
1301
+ if (!decision.allow) {
1302
+ navigate(decision.redirectTo);
1303
+ }
1304
+ }, [decision, navigate]);
1305
+ if (state.status === "loading") {
1306
+ return /* @__PURE__ */ jsx6(Centered, { children: props.loading ?? "\u52A0\u8F7D\u4E2D\u2026" });
1307
+ }
1308
+ if (state.status === "error") {
1309
+ return props.renderError !== void 0 ? /* @__PURE__ */ jsx6(Fragment, { children: props.renderError(state.error) }) : /* @__PURE__ */ jsxs3(Centered, { children: [
1310
+ "sitemap \u52A0\u8F7D\u5931\u8D25\uFF1A",
1311
+ state.error.message
1312
+ ] });
1313
+ }
1314
+ if (sitemap === null || registry === null || resolution === null) {
1315
+ return null;
1316
+ }
1317
+ if (!decision.allow) {
1318
+ return /* @__PURE__ */ jsx6(Centered, { children: "\u91CD\u5B9A\u5411\u2026" });
1319
+ }
1320
+ if (resolution.route === null) {
1321
+ return props.renderNotFound !== void 0 ? /* @__PURE__ */ jsx6(Fragment, { children: props.renderNotFound(pathname) }) : /* @__PURE__ */ jsxs3(Centered, { children: [
1322
+ "\u9875\u9762\u4E0D\u5B58\u5728\uFF08",
1323
+ pathname,
1324
+ "\uFF09"
1325
+ ] });
1326
+ }
1327
+ const { pageId, layoutName, highlightKey, params } = resolution.route;
1328
+ return (
1329
+ // key 只随布局名变化:切换导航(同布局)时布局常驻,
1330
+ // 仅 PageOutlet 内的页面随路由重建
1331
+ /* @__PURE__ */ jsx6(NavHighlightContext.Provider, { value: highlightKey, children: /* @__PURE__ */ jsx6(
1332
+ SitemapLayout,
1333
+ {
1334
+ sitemap,
1335
+ registry,
1336
+ pageId,
1337
+ layoutName,
1338
+ pathname,
1339
+ query,
1340
+ navigate,
1341
+ routeParams: params,
1342
+ props
1343
+ },
1344
+ layoutName
1345
+ ) })
1346
+ );
1347
+ }
1348
+ function SitemapLayout({
1349
+ sitemap,
1350
+ registry,
1351
+ pageId,
1352
+ layoutName,
1353
+ pathname,
1354
+ query,
1355
+ navigate: hostNavigate,
1356
+ routeParams,
1357
+ props
1358
+ }) {
1359
+ const sessionService = props.sessionService ?? "session.context";
1360
+ const session = useMemo2(
1361
+ () => ({
1362
+ user: sitemap.user,
1363
+ app: { name: "Pactor App", ...sitemap.app },
1364
+ menus: toSitemapNavItems(registry.tree())
1365
+ }),
1366
+ [sitemap, registry]
1367
+ );
1368
+ const navigate = useMemo2(
1369
+ () => (to) => {
1370
+ if (/^https?:\/\//.test(to)) {
1371
+ window.open(to, "_blank", "noopener");
1372
+ } else {
1373
+ hostNavigate(to);
1374
+ }
1375
+ },
1376
+ [hostNavigate]
1377
+ );
1378
+ const loader = useMemo2(
1379
+ () => createSitemapLoader(sitemap, {
1380
+ pageEndpoint: props.pageEndpoint,
1381
+ fetcher: props.fetcher,
1382
+ sessionService,
1383
+ baseUrl: props.baseUrl,
1384
+ httpHooks: props.httpAdapter
1385
+ }),
1386
+ [
1387
+ sitemap,
1388
+ props.pageEndpoint,
1389
+ props.fetcher,
1390
+ props.baseUrl,
1391
+ props.httpAdapter,
1392
+ sessionService
1393
+ ]
1394
+ );
1395
+ const services = useMemo2(
1396
+ () => ({
1397
+ ...createSitemapSessionServices(session, sessionService),
1398
+ ...props.services
1399
+ }),
1400
+ [session, sessionService, props.services]
1401
+ );
1402
+ const actions = useMemo2(
1403
+ () => ({ ...defaultSitemapActions, ...props.actions }),
1404
+ [props.actions]
1405
+ );
1406
+ const layoutDsl = sitemap.layouts[layoutName];
1407
+ const layoutPage = useMemo2(() => {
1408
+ if (layoutDsl === void 0) {
1409
+ return null;
1410
+ }
1411
+ return {
1412
+ dsl: layoutDsl.dsl,
1413
+ page: { id: `layout:${layoutName}`, title: layoutName },
1414
+ dataSources: {
1415
+ session: { type: "service", service: sessionService, autoLoad: true }
1416
+ },
1417
+ body: layoutDsl.body
1418
+ };
1419
+ }, [layoutDsl, layoutName, sessionService]);
1420
+ if (layoutDsl === void 0 || layoutPage === null) {
1421
+ return /* @__PURE__ */ jsxs3(Centered, { children: [
1422
+ "\u5E03\u5C40\u672A\u5B9A\u4E49\uFF1A",
1423
+ layoutName
1424
+ ] });
1425
+ }
1426
+ return /* @__PURE__ */ jsx6(
1427
+ OutletContext.Provider,
1428
+ {
1429
+ value: (
1430
+ // 页面实例:key 随 pageId + pathname 变化(route 参数变化需重建,
1431
+ // PactorPage 的 route prop 不参与运行时重建)——布局保持挂载
1432
+ /* @__PURE__ */ jsx6(
1433
+ PactorPage,
1434
+ {
1435
+ pageId,
1436
+ route: { params: routeParams, query },
1437
+ loader,
1438
+ services,
1439
+ actions,
1440
+ permissions: sitemap.permissions ?? [],
1441
+ navigate,
1442
+ httpAdapter: props.httpAdapter,
1443
+ components: props.components
1444
+ },
1445
+ `${pageId}@${pathname}`
1446
+ )
1447
+ ),
1448
+ children: /* @__PURE__ */ jsx6(
1449
+ PactorPage,
1450
+ {
1451
+ pageDsl: layoutPage,
1452
+ services,
1453
+ actions,
1454
+ navigate,
1455
+ httpAdapter: props.httpAdapter,
1456
+ components: { PageOutlet, SitemapMenu, ...props.components }
1457
+ }
1458
+ )
1459
+ }
1460
+ );
1461
+ }
1462
+ function Centered({ children }) {
1463
+ return /* @__PURE__ */ jsx6(
1464
+ "div",
1465
+ {
1466
+ style: {
1467
+ minHeight: "60vh",
1468
+ display: "flex",
1469
+ flexDirection: "column",
1470
+ alignItems: "center",
1471
+ justifyContent: "center",
1472
+ gap: 8,
1473
+ color: "var(--muted-foreground, #6b7280)"
1474
+ },
1475
+ children
1476
+ }
1477
+ );
1478
+ }
881
1479
  export {
882
1480
  Application,
883
1481
  DslPageLoader,
884
1482
  PactorPage,
885
1483
  PageErrorBoundary,
886
1484
  ReactRouterBinding,
1485
+ SitemapApp,
1486
+ createHttpHooks,
887
1487
  createPactorApplication,
888
1488
  createPactorPage,
889
1489
  createRuntimeHttpAdapter,
1490
+ createSitemapLoader,
1491
+ createSitemapSessionServices,
1492
+ defaultSitemapActions,
1493
+ defaultSitemapGuard,
1494
+ fetchSitemap,
1495
+ mergeSitemapMenus,
1496
+ resolveSitemapRoute,
1497
+ toSitemapNavItems,
1498
+ withHttpHooks,
890
1499
  wrapHttpAdapter
891
1500
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pactor-app/app",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "description": "Pactor application: one-stop composition layer (createPactorApplication) wiring loader, bootstrap, registries, router, layout, interaction and page runtimes",
5
5
  "keywords": [
6
6
  "pactor",
@@ -46,14 +46,14 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@pactor-app/core": "1.18.0",
50
- "@pactor-app/resource": "1.18.0",
51
- "@pactor-app/expression": "1.18.0",
52
- "@pactor-app/permission": "1.18.0",
53
- "@pactor-app/router": "1.18.0",
54
- "@pactor-app/schema": "1.18.0",
55
- "@pactor-app/ui": "1.18.0",
56
- "@pactor-app/runtime": "1.18.0"
49
+ "@pactor-app/core": "1.20.0",
50
+ "@pactor-app/permission": "1.20.0",
51
+ "@pactor-app/resource": "1.20.0",
52
+ "@pactor-app/schema": "1.20.0",
53
+ "@pactor-app/runtime": "1.20.0",
54
+ "@pactor-app/ui": "1.20.0",
55
+ "@pactor-app/expression": "1.20.0",
56
+ "@pactor-app/router": "1.20.0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "react": ">=18",