openxiangda 1.0.89 → 1.0.91

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.
@@ -32,6 +32,7 @@ var react_exports = {};
32
32
  __export(react_exports, {
33
33
  AuthClientError: () => AuthClientError,
34
34
  LoginPage: () => LoginPage,
35
+ OpenXiangdaPageProvider: () => OpenXiangdaPageProvider,
35
36
  OpenXiangdaProvider: () => OpenXiangdaProvider,
36
37
  PageProvider: () => PageProvider,
37
38
  PermissionBoundary: () => PermissionBoundary,
@@ -2547,6 +2548,187 @@ var createBoundFetch = (fetchImpl) => {
2547
2548
  return ((input, init) => baseFetch.call(globalThis, input, init));
2548
2549
  };
2549
2550
 
2551
+ // packages/sdk/src/runtime/host/browserHost.ts
2552
+ var trimTrailingSlash = (value) => value.replace(/\/+$/, "");
2553
+ var getDefaultServicePrefix = () => typeof window !== "undefined" ? trimTrailingSlash(window.__OPENXIANGDA_SERVICE_PREFIX__ || "/service") : "/service";
2554
+ var joinServicePath = (servicePrefix, path) => {
2555
+ if (/^https?:\/\//i.test(path)) return path;
2556
+ const normalizedPrefix = trimTrailingSlash(servicePrefix || "/service");
2557
+ if (path.startsWith(normalizedPrefix)) return path;
2558
+ return `${normalizedPrefix}${path.startsWith("/") ? path : `/${path}`}`;
2559
+ };
2560
+ var appendQuery = (url, query) => {
2561
+ if (!query) return url;
2562
+ return `${url}${url.includes("?") ? "&" : "?"}${query}`;
2563
+ };
2564
+ var normalizeMethod2 = (method) => {
2565
+ const value = String(method || "get").toUpperCase();
2566
+ return ["GET", "POST", "PUT", "DELETE", "PATCH"].includes(value) ? value : "GET";
2567
+ };
2568
+ var normalizeEnvelopeCode2 = (value, fallback) => {
2569
+ if (value === void 0 || value === null || value === "") return fallback;
2570
+ const normalized = Number(value);
2571
+ return Number.isFinite(normalized) ? normalized : String(value);
2572
+ };
2573
+ var isSuccessCode2 = (value) => {
2574
+ if (value === void 0 || value === null || value === "") return true;
2575
+ const normalized = Number(value);
2576
+ return Number.isFinite(normalized) ? normalized === 0 || normalized >= 200 && normalized < 300 : false;
2577
+ };
2578
+ var parseJsonResponse = async (response) => {
2579
+ const payload = await response.json().catch(() => null);
2580
+ if (!response.ok) {
2581
+ const message2 = payload && typeof payload === "object" ? payload.message || payload.error || response.statusText : response.statusText;
2582
+ throw new Error(message2 || "\u8BF7\u6C42\u5931\u8D25");
2583
+ }
2584
+ if (payload && typeof payload === "object" && "code" in payload) {
2585
+ const code = normalizeEnvelopeCode2(payload.code, response.status);
2586
+ return {
2587
+ code,
2588
+ success: payload.success !== false && isSuccessCode2(code),
2589
+ message: payload.message,
2590
+ result: payload.result ?? payload.data ?? null,
2591
+ data: payload.data,
2592
+ raw: payload
2593
+ };
2594
+ }
2595
+ return {
2596
+ code: response.status,
2597
+ success: response.ok,
2598
+ message: response.statusText,
2599
+ result: payload,
2600
+ data: payload,
2601
+ raw: payload
2602
+ };
2603
+ };
2604
+ var createBrowserPageBridge = (options = {}) => {
2605
+ const servicePrefix = options.servicePrefix || getDefaultServicePrefix();
2606
+ const fetchImpl = createBoundFetch(options.fetchImpl);
2607
+ const request = async (payload) => {
2608
+ if (!payload?.path) {
2609
+ throw new Error("transport.request \u9700\u8981 path");
2610
+ }
2611
+ const url = appendQuery(joinServicePath(servicePrefix, payload.path), payload.query);
2612
+ const headers = new Headers(payload.headers);
2613
+ let body;
2614
+ if (payload.body !== void 0) {
2615
+ if (payload.body instanceof FormData) {
2616
+ body = payload.body;
2617
+ } else {
2618
+ headers.set("Content-Type", headers.get("Content-Type") || "application/json");
2619
+ body = JSON.stringify(payload.body);
2620
+ }
2621
+ }
2622
+ const response = await fetchImpl(url, {
2623
+ method: normalizeMethod2(payload.method),
2624
+ headers,
2625
+ body,
2626
+ credentials: "include"
2627
+ });
2628
+ return parseJsonResponse(response);
2629
+ };
2630
+ const download = async (payload) => {
2631
+ if (!payload?.path) {
2632
+ throw new Error("transport.download \u9700\u8981 path");
2633
+ }
2634
+ const url = appendQuery(joinServicePath(servicePrefix, payload.path), payload.query);
2635
+ const headers = new Headers(payload.headers);
2636
+ let body;
2637
+ if (payload.body !== void 0) {
2638
+ if (payload.body instanceof FormData) {
2639
+ body = payload.body;
2640
+ } else {
2641
+ headers.set("Content-Type", headers.get("Content-Type") || "application/json");
2642
+ body = JSON.stringify(payload.body);
2643
+ }
2644
+ }
2645
+ const response = await fetchImpl(url, {
2646
+ method: normalizeMethod2(payload.method),
2647
+ headers,
2648
+ body,
2649
+ credentials: "include"
2650
+ });
2651
+ if (!response.ok) {
2652
+ throw new Error(response.statusText || "\u4E0B\u8F7D\u5931\u8D25");
2653
+ }
2654
+ return {
2655
+ blob: await response.blob(),
2656
+ contentType: response.headers.get("content-type") || void 0,
2657
+ fileName: response.headers.get("content-disposition") || void 0,
2658
+ headers: Object.fromEntries(response.headers.entries())
2659
+ };
2660
+ };
2661
+ return {
2662
+ invoke: async (method, payload) => {
2663
+ if (method === "transport.request") return await request(payload);
2664
+ if (method === "transport.download") return await download(payload);
2665
+ throw new Error(`\u4E0D\u652F\u6301\u7684 bridge \u65B9\u6CD5: ${method}`);
2666
+ }
2667
+ };
2668
+ };
2669
+ var createBrowserPageContext = (bootstrap, options = {}) => {
2670
+ const route = {
2671
+ pathname: options.route?.pathname || (typeof window !== "undefined" ? window.location.pathname : ""),
2672
+ fullPath: options.route?.fullPath || (typeof window !== "undefined" ? `${window.location.pathname}${window.location.search}${window.location.hash}` : ""),
2673
+ params: options.route?.params || {},
2674
+ query: options.route?.query || {},
2675
+ hash: options.route?.hash || (typeof window !== "undefined" ? window.location.hash : "")
2676
+ };
2677
+ return {
2678
+ protocolVersion: bootstrap.asset?.protocolVersion || "1.0",
2679
+ app: bootstrap.app,
2680
+ page: {
2681
+ ...bootstrap.page,
2682
+ version: bootstrap.asset?.version || bootstrap.page.version,
2683
+ buildId: bootstrap.asset?.buildId || bootstrap.page.buildId
2684
+ },
2685
+ user: bootstrap.user,
2686
+ route,
2687
+ env: bootstrap.env || {},
2688
+ permissions: {
2689
+ canView: bootstrap.permissions?.canView !== false,
2690
+ hasFullAccess: bootstrap.permissions?.hasFullAccess === true,
2691
+ ...bootstrap.permissions || {}
2692
+ },
2693
+ capabilities: Array.from(
2694
+ /* @__PURE__ */ new Set([
2695
+ "navigation",
2696
+ "ui.message",
2697
+ "ui.modal",
2698
+ "transport.request",
2699
+ "transport.download",
2700
+ ...bootstrap.sdk?.supportedBridgeMethods || []
2701
+ ])
2702
+ ),
2703
+ ui: {
2704
+ message: {
2705
+ success: (text) => options.message?.success?.(text),
2706
+ error: (text) => options.message?.error?.(text),
2707
+ warning: (text) => options.message?.warning?.(text),
2708
+ info: (text) => options.message?.info?.(text),
2709
+ loading: (text) => options.message?.loading?.(text) || (() => void 0)
2710
+ },
2711
+ modal: {
2712
+ confirm: (input) => options.modal?.confirm?.(input) || Promise.resolve(false)
2713
+ }
2714
+ },
2715
+ navigation: {
2716
+ pushPage: (pageKey, query) => options.navigation?.pushPage?.(pageKey, query),
2717
+ replacePage: (pageKey, query) => options.navigation?.replacePage?.(pageKey, query),
2718
+ pushRoute: (routeValue, query) => options.navigation?.pushRoute?.(routeValue, query),
2719
+ replaceRoute: (routeValue, query) => options.navigation?.replaceRoute?.(routeValue, query),
2720
+ updateQuery: (query) => options.navigation?.updateQuery?.(query),
2721
+ setHash: (hash) => options.navigation?.setHash?.(hash),
2722
+ back: () => options.navigation?.back?.()
2723
+ },
2724
+ bridge: createBrowserPageBridge(options),
2725
+ sdk: {
2726
+ ...bootstrap.sdk,
2727
+ supportedBridgeMethods: ["transport.request", "transport.download"]
2728
+ }
2729
+ };
2730
+ };
2731
+
2550
2732
  // packages/sdk/src/runtime/react/auth.tsx
2551
2733
  var import_react7 = require("react");
2552
2734
  var import_antd2 = require("antd");
@@ -2585,7 +2767,7 @@ var createAuthClient = ({
2585
2767
  const payload = await readPayload(response);
2586
2768
  const code = getRecordValue(payload, "code");
2587
2769
  const success = getRecordValue(payload, "success");
2588
- if (!response.ok || success === false || !isSuccessCode2(code)) {
2770
+ if (!response.ok || success === false || !isSuccessCode3(code)) {
2589
2771
  throw new AuthClientError(
2590
2772
  String(getRecordValue(payload, "message") || `Auth request failed: ${response.status}`),
2591
2773
  { status: response.status, code, payload }
@@ -2638,7 +2820,7 @@ var getRecordValue = (value, key) => {
2638
2820
  if (!value || typeof value !== "object") return void 0;
2639
2821
  return value[key];
2640
2822
  };
2641
- var isSuccessCode2 = (code) => {
2823
+ var isSuccessCode3 = (code) => {
2642
2824
  if (code === void 0 || code === null || code === "") return true;
2643
2825
  const normalized = Number(code);
2644
2826
  return Number.isFinite(normalized) ? normalized === 0 || normalized >= 200 && normalized < 300 : false;
@@ -3180,9 +3362,12 @@ var OpenXiangdaProvider = ({
3180
3362
  [appType]
3181
3363
  );
3182
3364
  const [accessToken, setAccessTokenState] = (0, import_react8.useState)(null);
3365
+ const accessTokenRef = (0, import_react8.useRef)(null);
3183
3366
  const setAccessToken = (0, import_react8.useCallback)(
3184
3367
  (nextAccessToken) => {
3185
- setAccessTokenState(nextAccessToken || null);
3368
+ const normalizedAccessToken = nextAccessToken || null;
3369
+ accessTokenRef.current = normalizedAccessToken;
3370
+ setAccessTokenState(normalizedAccessToken);
3186
3371
  },
3187
3372
  []
3188
3373
  );
@@ -3208,7 +3393,7 @@ var OpenXiangdaProvider = ({
3208
3393
  return;
3209
3394
  }
3210
3395
  setState((prev) => ({ ...prev, loading: true, error: null }));
3211
- const requestFetch = options.accessToken !== void 0 ? createAuthorizedFetch(resolvedFetch, options.accessToken || null) : authorizedFetch;
3396
+ const requestFetch = options.accessToken !== void 0 ? createAuthorizedFetch(resolvedFetch, options.accessToken || null) : createAuthorizedFetch(resolvedFetch, accessTokenRef.current);
3212
3397
  try {
3213
3398
  const response = await requestFetch(
3214
3399
  buildServiceUrl2(
@@ -3242,7 +3427,7 @@ var OpenXiangdaProvider = ({
3242
3427
  error: normalizeRuntimeError(error)
3243
3428
  });
3244
3429
  }
3245
- }, [authorizedFetch, resolvedAppType, resolvedFetch, servicePrefix]);
3430
+ }, [resolvedAppType, resolvedFetch, servicePrefix]);
3246
3431
  (0, import_react8.useEffect)(() => {
3247
3432
  void reload();
3248
3433
  }, [reload]);
@@ -3252,10 +3437,11 @@ var OpenXiangdaProvider = ({
3252
3437
  appType: resolvedAppType,
3253
3438
  servicePrefix,
3254
3439
  fetchImpl: authorizedFetch,
3440
+ baseFetchImpl: resolvedFetch,
3255
3441
  reload,
3256
3442
  setAccessToken
3257
3443
  }),
3258
- [authorizedFetch, reload, resolvedAppType, servicePrefix, state]
3444
+ [authorizedFetch, reload, resolvedAppType, resolvedFetch, servicePrefix, state]
3259
3445
  );
3260
3446
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(OpenXiangdaRuntimeContext.Provider, { value, children });
3261
3447
  };
@@ -3267,6 +3453,96 @@ var useOpenXiangda = () => {
3267
3453
  return context;
3268
3454
  };
3269
3455
  var useRuntimeBootstrap = () => useOpenXiangda();
3456
+ var OpenXiangdaPageProvider = ({
3457
+ children,
3458
+ page,
3459
+ route,
3460
+ env,
3461
+ message: message2,
3462
+ modal,
3463
+ navigation
3464
+ }) => {
3465
+ const runtime = useOpenXiangda();
3466
+ const context = (0, import_react8.useMemo)(() => {
3467
+ const bootstrap = runtime.data;
3468
+ const app = toRuntimeRecord(bootstrap?.app);
3469
+ const user = toRuntimeRecord(bootstrap?.user);
3470
+ const permissions = bootstrap?.permissions;
3471
+ const tenantId = toStringValue(getRecordValue2(app, "tenantId")) || toStringValue(getRecordValue2(user, "tenantId")) || toStringValue(getRecordValue2(app, "tenantCode")) || "";
3472
+ const appType = runtime.appType || bootstrap?.appType || toStringValue(getRecordValue2(app, "appType"));
3473
+ const routeInfo = buildBrowserRouteInfo(route);
3474
+ return createBrowserPageContext(
3475
+ {
3476
+ app: {
3477
+ ...app,
3478
+ appType,
3479
+ tenantId
3480
+ },
3481
+ page: {
3482
+ id: routeInfo.pathname || "react-spa",
3483
+ code: routeInfo.pathname || "react-spa",
3484
+ name: "OpenXiangda React SPA",
3485
+ type: "react-spa",
3486
+ rendererType: "react-spa",
3487
+ routeKey: routeInfo.pathname || "react-spa",
3488
+ status: "ACTIVE",
3489
+ props: {},
3490
+ route: {},
3491
+ dataSources: [],
3492
+ capabilities: {},
3493
+ buildId: toStringValue(
3494
+ getRecordValue2(bootstrap?.runtime, "activeBuildId")
3495
+ ),
3496
+ ...page
3497
+ },
3498
+ user: {
3499
+ ...user,
3500
+ id: toStringValue(getRecordValue2(user, "id")) || (user.isGuest ? "guest" : "current"),
3501
+ username: toStringValue(getRecordValue2(user, "username")) || toStringValue(getRecordValue2(user, "name")) || (user.isGuest ? "guest" : "current"),
3502
+ tenantId,
3503
+ isGuest: user.isGuest === true || user.userType === "guest" || Boolean(getRecordValue2(user, "publicAccess")),
3504
+ userType: user.userType === "guest" || user.isGuest === true ? "guest" : "normal"
3505
+ },
3506
+ env: {
3507
+ appType,
3508
+ servicePrefix: runtime.servicePrefix,
3509
+ runtimeMode: bootstrap?.runtime?.mode || "react-spa",
3510
+ ...env || {}
3511
+ },
3512
+ permissions: {
3513
+ canView: runtime.error?.type !== "forbidden",
3514
+ hasFullAccess: permissions?.hasFullAccess === true,
3515
+ ...permissions || {}
3516
+ },
3517
+ sdk: {
3518
+ packageName: "openxiangda",
3519
+ supportedBridgeMethods: ["transport.request", "transport.download"]
3520
+ }
3521
+ },
3522
+ {
3523
+ servicePrefix: runtime.servicePrefix,
3524
+ fetchImpl: runtime.fetchImpl,
3525
+ route: routeInfo,
3526
+ message: message2,
3527
+ modal,
3528
+ navigation
3529
+ }
3530
+ );
3531
+ }, [
3532
+ env,
3533
+ message2,
3534
+ modal,
3535
+ navigation,
3536
+ page,
3537
+ route,
3538
+ runtime.appType,
3539
+ runtime.data,
3540
+ runtime.error?.type,
3541
+ runtime.fetchImpl,
3542
+ runtime.servicePrefix
3543
+ ]);
3544
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PageProvider, { context, children });
3545
+ };
3270
3546
  var useAppMenus = () => {
3271
3547
  const runtime = useOpenXiangda();
3272
3548
  return {
@@ -3644,7 +3920,40 @@ var getRecordValue2 = (value, key) => {
3644
3920
  if (!value || typeof value !== "object") return void 0;
3645
3921
  return value[key];
3646
3922
  };
3647
- var isSuccessCode3 = (code) => {
3923
+ var toRuntimeRecord = (value) => {
3924
+ return value && typeof value === "object" ? { ...value } : {};
3925
+ };
3926
+ var toStringValue = (value) => {
3927
+ if (value === void 0 || value === null) return "";
3928
+ return String(value);
3929
+ };
3930
+ var parseBrowserQuery = () => {
3931
+ if (typeof window === "undefined") return {};
3932
+ const query = {};
3933
+ const params = new URLSearchParams(window.location.search);
3934
+ params.forEach((value, key) => {
3935
+ const currentValue = query[key];
3936
+ if (currentValue === void 0) {
3937
+ query[key] = value;
3938
+ return;
3939
+ }
3940
+ query[key] = Array.isArray(currentValue) ? [...currentValue, value] : [currentValue, value];
3941
+ });
3942
+ return query;
3943
+ };
3944
+ var buildBrowserRouteInfo = (route) => {
3945
+ const pathname = route?.pathname || (typeof window !== "undefined" ? window.location.pathname : "");
3946
+ const search = typeof window !== "undefined" ? window.location.search : "";
3947
+ const hash = route?.hash || (typeof window !== "undefined" ? window.location.hash : "");
3948
+ return {
3949
+ pathname,
3950
+ fullPath: route?.fullPath || (typeof window !== "undefined" ? `${pathname}${search}${hash}` : pathname),
3951
+ params: route?.params || {},
3952
+ query: route?.query || parseBrowserQuery(),
3953
+ hash
3954
+ };
3955
+ };
3956
+ var isSuccessCode4 = (code) => {
3648
3957
  if (code === void 0 || code === null || code === "") return true;
3649
3958
  const normalized = Number(code);
3650
3959
  return Number.isFinite(normalized) ? normalized === 0 || normalized >= 200 && normalized < 300 : false;
@@ -3652,7 +3961,7 @@ var isSuccessCode3 = (code) => {
3652
3961
  var isRuntimeEnvelopeFailure = (response, payload) => {
3653
3962
  const code = getRecordValue2(payload, "code");
3654
3963
  const success = getRecordValue2(payload, "success");
3655
- return !response.ok || success === false || !isSuccessCode3(code);
3964
+ return !response.ok || success === false || !isSuccessCode4(code);
3656
3965
  };
3657
3966
  var isServerErrorCode = (code) => {
3658
3967
  const normalized = Number(code);
@@ -3722,7 +4031,7 @@ var createPublicAccessClient = ({
3722
4031
  const payload = await readPayload2(response);
3723
4032
  const code = getRecordValue3(payload, "code");
3724
4033
  const success = getRecordValue3(payload, "success");
3725
- if (!response.ok || success === false || !isSuccessCode4(code)) {
4034
+ if (!response.ok || success === false || !isSuccessCode5(code)) {
3726
4035
  throw new PublicAccessClientError(
3727
4036
  String(
3728
4037
  getRecordValue3(payload, "message") || `Public access session failed: ${response.status}`
@@ -3760,7 +4069,7 @@ var getRecordValue3 = (value, key) => {
3760
4069
  if (!value || typeof value !== "object") return void 0;
3761
4070
  return value[key];
3762
4071
  };
3763
- var isSuccessCode4 = (code) => {
4072
+ var isSuccessCode5 = (code) => {
3764
4073
  if (code === void 0 || code === null || code === "") return true;
3765
4074
  const normalized = Number(code);
3766
4075
  return Number.isFinite(normalized) ? normalized === 0 || normalized >= 200 && normalized < 300 : false;
@@ -3794,14 +4103,14 @@ var usePublicAccess = (options = {}) => {
3794
4103
  const {
3795
4104
  appType: runtimeAppType,
3796
4105
  servicePrefix: runtimeServicePrefix,
3797
- fetchImpl: runtimeFetchImpl,
4106
+ baseFetchImpl: runtimeBaseFetchImpl,
3798
4107
  reload: reloadRuntime,
3799
4108
  setAccessToken
3800
4109
  } = runtime;
3801
4110
  const {
3802
4111
  appType = runtimeAppType,
3803
4112
  servicePrefix = runtimeServicePrefix,
3804
- fetchImpl = runtimeFetchImpl,
4113
+ fetchImpl = runtimeBaseFetchImpl,
3805
4114
  autoStart = true,
3806
4115
  ...sessionInput
3807
4116
  } = options;