openxiangda 1.0.61 → 1.0.63
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/package.json +1 -1
- package/packages/sdk/dist/components/index.cjs +3 -3
- package/packages/sdk/dist/components/index.cjs.map +1 -1
- package/packages/sdk/dist/components/index.mjs +3 -3
- package/packages/sdk/dist/components/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/index.cjs +279 -16
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.d.mts +1 -1
- package/packages/sdk/dist/runtime/index.d.ts +1 -1
- package/packages/sdk/dist/runtime/index.mjs +279 -16
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/react.cjs +277 -13
- package/packages/sdk/dist/runtime/react.cjs.map +1 -1
- package/packages/sdk/dist/runtime/react.d.mts +60 -7
- package/packages/sdk/dist/runtime/react.d.ts +60 -7
- package/packages/sdk/dist/runtime/react.mjs +277 -13
- package/packages/sdk/dist/runtime/react.mjs.map +1 -1
- package/templates/openxiangda-react-spa/src/app/router.tsx +12 -1
- package/templates/openxiangda-react-spa/src/layouts/AdminShell.tsx +374 -96
- package/templates/openxiangda-react-spa/src/layouts/PublicShell.tsx +25 -3
- package/templates/openxiangda-react-spa/src/layouts/UserShell.tsx +101 -22
- package/templates/openxiangda-react-spa/src/pages/admin/RuntimeWorkspacePage.tsx +203 -41
- package/templates/openxiangda-react-spa/src/pages/defaults/DataRoutePage.tsx +80 -11
- package/templates/openxiangda-react-spa/src/pages/defaults/FilePreviewRoutePage.tsx +67 -14
- package/templates/openxiangda-react-spa/src/pages/defaults/FormRoutePage.tsx +153 -30
- package/templates/openxiangda-react-spa/src/pages/portal/UserPortalPage.tsx +53 -14
- package/templates/openxiangda-react-spa/src/pages/public/PublicHomePage.tsx +46 -6
- package/templates/openxiangda-react-spa/src/pages/states/NotFoundPage.tsx +26 -11
- package/templates/openxiangda-react-spa/src/shared/mac-admin.tsx +332 -0
- package/templates/openxiangda-react-spa/src/styles/index.css +42 -4
- package/templates/openxiangda-react-spa/tailwind.config.cjs +8 -0
- package/templates/openxiangda-react-spa/vite.config.ts +31 -0
|
@@ -22,10 +22,12 @@ var openxiangdaProvider_exports = {};
|
|
|
22
22
|
__export(openxiangdaProvider_exports, {
|
|
23
23
|
OpenXiangdaProvider: () => OpenXiangdaProvider,
|
|
24
24
|
PermissionBoundary: () => PermissionBoundary,
|
|
25
|
+
RuntimeHttpError: () => RuntimeHttpError,
|
|
25
26
|
useAppMenus: () => useAppMenus,
|
|
26
27
|
useCanAccessRoute: () => useCanAccessRoute,
|
|
27
28
|
useOpenXiangda: () => useOpenXiangda,
|
|
28
29
|
usePermission: () => usePermission,
|
|
30
|
+
useRuntimeAuth: () => useRuntimeAuth,
|
|
29
31
|
useRuntimeBootstrap: () => useRuntimeBootstrap
|
|
30
32
|
});
|
|
31
33
|
module.exports = __toCommonJS(openxiangdaProvider_exports);
|
|
@@ -39,6 +41,16 @@ var createBoundFetch = (fetchImpl) => {
|
|
|
39
41
|
|
|
40
42
|
// packages/sdk/src/runtime/react/openxiangdaProvider.tsx
|
|
41
43
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
44
|
+
var RuntimeHttpError = class extends Error {
|
|
45
|
+
constructor(snapshot) {
|
|
46
|
+
super(snapshot.message);
|
|
47
|
+
this.name = "RuntimeHttpError";
|
|
48
|
+
this.type = snapshot.type;
|
|
49
|
+
this.status = snapshot.status;
|
|
50
|
+
this.code = snapshot.code;
|
|
51
|
+
this.payload = snapshot.payload;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
42
54
|
var OpenXiangdaRuntimeContext = (0, import_react.createContext)(null);
|
|
43
55
|
var OpenXiangdaProvider = ({
|
|
44
56
|
appType,
|
|
@@ -61,7 +73,10 @@ var OpenXiangdaProvider = ({
|
|
|
61
73
|
setState({
|
|
62
74
|
data: null,
|
|
63
75
|
loading: false,
|
|
64
|
-
error:
|
|
76
|
+
error: createRuntimeError({
|
|
77
|
+
message: "appType \u4E0D\u80FD\u4E3A\u7A7A",
|
|
78
|
+
type: "unknown"
|
|
79
|
+
})
|
|
65
80
|
});
|
|
66
81
|
return;
|
|
67
82
|
}
|
|
@@ -79,9 +94,13 @@ var OpenXiangdaProvider = ({
|
|
|
79
94
|
headers: { accept: "application/json" }
|
|
80
95
|
}
|
|
81
96
|
);
|
|
82
|
-
const payload = await response
|
|
97
|
+
const payload = await readJsonPayload(response);
|
|
83
98
|
if (!response.ok || payload?.code >= 400) {
|
|
84
|
-
throw
|
|
99
|
+
throw createRuntimeHttpError(
|
|
100
|
+
response,
|
|
101
|
+
payload,
|
|
102
|
+
payload?.message || `Runtime bootstrap failed: ${response.status}`
|
|
103
|
+
);
|
|
85
104
|
}
|
|
86
105
|
setState({
|
|
87
106
|
data: payload?.data || null,
|
|
@@ -92,7 +111,7 @@ var OpenXiangdaProvider = ({
|
|
|
92
111
|
setState({
|
|
93
112
|
data: null,
|
|
94
113
|
loading: false,
|
|
95
|
-
error:
|
|
114
|
+
error: normalizeRuntimeError(error)
|
|
96
115
|
});
|
|
97
116
|
}
|
|
98
117
|
}, [resolvedAppType, resolvedFetch, servicePrefix]);
|
|
@@ -148,6 +167,23 @@ var useCanAccessRoute = (input) => {
|
|
|
148
167
|
setState((prev) => ({ ...prev, loading: runtime.loading }));
|
|
149
168
|
return;
|
|
150
169
|
}
|
|
170
|
+
if (runtime.error && !runtime.data) {
|
|
171
|
+
const snapshot = toRuntimeErrorSnapshot(runtime.error);
|
|
172
|
+
setState({
|
|
173
|
+
data: {
|
|
174
|
+
appType: runtime.appType,
|
|
175
|
+
canAccess: false,
|
|
176
|
+
status: snapshot.status,
|
|
177
|
+
code: snapshot.code,
|
|
178
|
+
message: snapshot.message,
|
|
179
|
+
errorType: snapshot.type,
|
|
180
|
+
payload: snapshot.payload
|
|
181
|
+
},
|
|
182
|
+
loading: false,
|
|
183
|
+
error: runtime.error
|
|
184
|
+
});
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
151
187
|
if (permissions?.hasFullAccess) {
|
|
152
188
|
setState({
|
|
153
189
|
data: { appType: runtime.appType, canAccess: true, permissions },
|
|
@@ -175,15 +211,33 @@ var useCanAccessRoute = (input) => {
|
|
|
175
211
|
body: JSON.stringify(input)
|
|
176
212
|
}
|
|
177
213
|
);
|
|
178
|
-
const payload = await response
|
|
214
|
+
const payload = await readJsonPayload(response);
|
|
215
|
+
const code = payload?.code ?? response.status;
|
|
216
|
+
const canAccess = Boolean(payload?.data?.canAccess);
|
|
217
|
+
const errorType = canAccess ? void 0 : classifyRuntimeError(response.status, code);
|
|
218
|
+
const data = {
|
|
219
|
+
...payload?.data || {
|
|
220
|
+
appType: runtime.appType,
|
|
221
|
+
canAccess: false
|
|
222
|
+
},
|
|
223
|
+
appType: payload?.data?.appType || runtime.appType,
|
|
224
|
+
canAccess,
|
|
225
|
+
status: response.status,
|
|
226
|
+
code,
|
|
227
|
+
message: payload?.message,
|
|
228
|
+
errorType,
|
|
229
|
+
payload
|
|
230
|
+
};
|
|
179
231
|
if (!disposed) {
|
|
232
|
+
const shouldTreatAsError = !response.ok || typeof code === "number" && code >= 500;
|
|
180
233
|
setState({
|
|
181
|
-
data
|
|
182
|
-
appType: runtime.appType,
|
|
183
|
-
canAccess: false
|
|
184
|
-
},
|
|
234
|
+
data,
|
|
185
235
|
loading: false,
|
|
186
|
-
error:
|
|
236
|
+
error: shouldTreatAsError ? createRuntimeHttpError(
|
|
237
|
+
response,
|
|
238
|
+
payload,
|
|
239
|
+
payload?.message || `Route check failed: ${response.status}`
|
|
240
|
+
) : null
|
|
187
241
|
});
|
|
188
242
|
}
|
|
189
243
|
} catch (error) {
|
|
@@ -191,7 +245,7 @@ var useCanAccessRoute = (input) => {
|
|
|
191
245
|
setState({
|
|
192
246
|
data: null,
|
|
193
247
|
loading: false,
|
|
194
|
-
error:
|
|
248
|
+
error: normalizeRuntimeError(error)
|
|
195
249
|
});
|
|
196
250
|
}
|
|
197
251
|
}
|
|
@@ -223,16 +277,226 @@ var PermissionBoundary = ({
|
|
|
223
277
|
menuCode,
|
|
224
278
|
path
|
|
225
279
|
}) => {
|
|
280
|
+
const runtime = useOpenXiangda();
|
|
226
281
|
const access = useCanAccessRoute({ routeCode, menuCode, path });
|
|
227
|
-
|
|
228
|
-
if (
|
|
282
|
+
const fallbackState = createPermissionFallbackState(access, runtime);
|
|
283
|
+
if (access.loading) {
|
|
284
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderBoundaryFallback(loadingFallback, fallbackState) });
|
|
285
|
+
}
|
|
286
|
+
if (!access.canAccess) {
|
|
287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderBoundaryFallback(fallback, fallbackState) });
|
|
288
|
+
}
|
|
229
289
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
|
|
230
290
|
};
|
|
291
|
+
var useRuntimeAuth = () => {
|
|
292
|
+
const runtime = useOpenXiangda();
|
|
293
|
+
const resolveLoginUrl = (0, import_react.useCallback)(
|
|
294
|
+
async (options = {}) => {
|
|
295
|
+
const redirectUri = options.redirectUri || getCurrentHref();
|
|
296
|
+
const domain = options.domain || getCurrentHostname();
|
|
297
|
+
const appTenantId = getRecordString(runtime.data?.app, "tenantId");
|
|
298
|
+
try {
|
|
299
|
+
const statusUrl = withQuery(
|
|
300
|
+
buildServiceUrl(runtime.servicePrefix, "/api/sso/status"),
|
|
301
|
+
{ domain }
|
|
302
|
+
);
|
|
303
|
+
const statusResponse = await runtime.fetchImpl(statusUrl, {
|
|
304
|
+
credentials: "include",
|
|
305
|
+
headers: { accept: "application/json" }
|
|
306
|
+
});
|
|
307
|
+
const statusPayload = await readJsonPayload(statusResponse);
|
|
308
|
+
const sso = statusPayload?.data || {};
|
|
309
|
+
const enabled = Boolean(sso.enabled);
|
|
310
|
+
const shouldUseSso = Boolean(
|
|
311
|
+
enabled && (sso.forceLogin ?? sso.autoRedirect ?? true)
|
|
312
|
+
);
|
|
313
|
+
if (shouldUseSso) {
|
|
314
|
+
const loginUrlResponse = await runtime.fetchImpl(
|
|
315
|
+
withQuery(buildServiceUrl(runtime.servicePrefix, "/api/sso/login-url"), {
|
|
316
|
+
domain,
|
|
317
|
+
redirectUri,
|
|
318
|
+
...sso.tenantId || appTenantId ? { tenantId: String(sso.tenantId || appTenantId) } : {},
|
|
319
|
+
...sso.protocol ? { protocol: String(sso.protocol) } : {}
|
|
320
|
+
}),
|
|
321
|
+
{
|
|
322
|
+
credentials: "include",
|
|
323
|
+
headers: { accept: "application/json" }
|
|
324
|
+
}
|
|
325
|
+
);
|
|
326
|
+
const loginUrlPayload = await readJsonPayload(loginUrlResponse);
|
|
327
|
+
const loginUrl = loginUrlPayload?.data?.loginUrl || loginUrlPayload?.data?.url || loginUrlPayload?.loginUrl || loginUrlPayload?.url;
|
|
328
|
+
if (loginUrl) return String(loginUrl);
|
|
329
|
+
}
|
|
330
|
+
} catch {
|
|
331
|
+
}
|
|
332
|
+
const configuredLoginUrl = options.loginUrl || getRuntimeEnv("OPENXIANGDA_LOGIN_URL") || getRuntimeEnv("VITE_OPENXIANGDA_LOGIN_URL") || getRuntimeEnv("APP_LOGIN_URL") || getRuntimeEnv("VITE_APP_LOGIN_URL") || getRuntimeEnv("VITE_BATH_AUTH_URL") || getRuntimeEnv("BATH_AUTH_URL");
|
|
333
|
+
if (configuredLoginUrl) {
|
|
334
|
+
return attachCallback(configuredLoginUrl, redirectUri);
|
|
335
|
+
}
|
|
336
|
+
return attachCallback("/login", redirectUri);
|
|
337
|
+
},
|
|
338
|
+
[runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix]
|
|
339
|
+
);
|
|
340
|
+
const redirectToLogin = (0, import_react.useCallback)(
|
|
341
|
+
async (options = {}) => {
|
|
342
|
+
const loginUrl = await resolveLoginUrl(options);
|
|
343
|
+
if (typeof window !== "undefined") {
|
|
344
|
+
if (options.replace === false) {
|
|
345
|
+
window.location.assign(loginUrl);
|
|
346
|
+
} else {
|
|
347
|
+
window.location.replace(loginUrl);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return loginUrl;
|
|
351
|
+
},
|
|
352
|
+
[resolveLoginUrl]
|
|
353
|
+
);
|
|
354
|
+
const logout = (0, import_react.useCallback)(async () => {
|
|
355
|
+
const response = await runtime.fetchImpl(
|
|
356
|
+
buildServiceUrl(runtime.servicePrefix, "/api/auth/logout"),
|
|
357
|
+
{
|
|
358
|
+
method: "POST",
|
|
359
|
+
credentials: "include",
|
|
360
|
+
headers: { accept: "application/json" }
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
const payload = await readJsonPayload(response);
|
|
364
|
+
if (!response.ok || payload?.code >= 400) {
|
|
365
|
+
throw createRuntimeHttpError(
|
|
366
|
+
response,
|
|
367
|
+
payload,
|
|
368
|
+
payload?.message || `Logout failed: ${response.status}`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
return payload;
|
|
372
|
+
}, [runtime.fetchImpl, runtime.servicePrefix]);
|
|
373
|
+
const logoutAndRedirect = (0, import_react.useCallback)(
|
|
374
|
+
async (options = {}) => {
|
|
375
|
+
try {
|
|
376
|
+
await logout();
|
|
377
|
+
} catch (error) {
|
|
378
|
+
if (options.continueOnError === false) throw error;
|
|
379
|
+
}
|
|
380
|
+
return redirectToLogin(options);
|
|
381
|
+
},
|
|
382
|
+
[logout, redirectToLogin]
|
|
383
|
+
);
|
|
384
|
+
return {
|
|
385
|
+
logout,
|
|
386
|
+
logoutAndRedirect,
|
|
387
|
+
redirectToLogin,
|
|
388
|
+
resolveLoginUrl
|
|
389
|
+
};
|
|
390
|
+
};
|
|
231
391
|
var buildServiceUrl = (servicePrefix, path) => {
|
|
232
392
|
const prefix = servicePrefix.endsWith("/") ? servicePrefix.slice(0, -1) : servicePrefix;
|
|
233
393
|
const suffix = path.startsWith("/") ? path : `/${path}`;
|
|
234
394
|
return `${prefix}${suffix}`;
|
|
235
395
|
};
|
|
396
|
+
var readJsonPayload = async (response) => {
|
|
397
|
+
try {
|
|
398
|
+
return await response.json();
|
|
399
|
+
} catch {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
var createRuntimeHttpError = (response, payload, fallbackMessage) => createRuntimeError({
|
|
404
|
+
type: classifyRuntimeError(
|
|
405
|
+
response.status,
|
|
406
|
+
getRecordValue(payload, "code")
|
|
407
|
+
),
|
|
408
|
+
status: response.status,
|
|
409
|
+
code: getRecordValue(payload, "code"),
|
|
410
|
+
message: getRecordValue(payload, "message") || fallbackMessage,
|
|
411
|
+
payload
|
|
412
|
+
});
|
|
413
|
+
var createRuntimeError = (snapshot) => new RuntimeHttpError({
|
|
414
|
+
...snapshot,
|
|
415
|
+
type: snapshot.type || "unknown",
|
|
416
|
+
message: snapshot.message || "Runtime request failed"
|
|
417
|
+
});
|
|
418
|
+
var normalizeRuntimeError = (error) => {
|
|
419
|
+
if (error instanceof RuntimeHttpError) return error;
|
|
420
|
+
if (error instanceof Error) {
|
|
421
|
+
const runtimeError = error;
|
|
422
|
+
runtimeError.type = runtimeError.type || classifyRuntimeError(runtimeError.status, runtimeError.code);
|
|
423
|
+
return runtimeError;
|
|
424
|
+
}
|
|
425
|
+
return createRuntimeError({
|
|
426
|
+
type: "unknown",
|
|
427
|
+
message: String(error)
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
var toRuntimeErrorSnapshot = (error) => ({
|
|
431
|
+
type: error.type || classifyRuntimeError(error.status, error.code),
|
|
432
|
+
status: error.status,
|
|
433
|
+
code: error.code,
|
|
434
|
+
message: error.message || "Runtime request failed",
|
|
435
|
+
payload: error.payload
|
|
436
|
+
});
|
|
437
|
+
var classifyRuntimeError = (status, code) => {
|
|
438
|
+
const normalizedCode = typeof code === "string" ? Number(code) : code;
|
|
439
|
+
if (status === 401 || normalizedCode === 401) return "unauthenticated";
|
|
440
|
+
if (status === 403 || normalizedCode === 403) return "forbidden";
|
|
441
|
+
if (!status && !normalizedCode) return "network";
|
|
442
|
+
return "unknown";
|
|
443
|
+
};
|
|
444
|
+
var createPermissionFallbackState = (access, runtime) => {
|
|
445
|
+
const error = access.error || runtime.error;
|
|
446
|
+
const accessData = access.data;
|
|
447
|
+
const errorType = accessData?.errorType || error?.type || (!access.canAccess ? "forbidden" : "unknown");
|
|
448
|
+
return {
|
|
449
|
+
access,
|
|
450
|
+
runtime,
|
|
451
|
+
error,
|
|
452
|
+
errorType,
|
|
453
|
+
status: accessData?.status || error?.status,
|
|
454
|
+
code: accessData?.code || error?.code,
|
|
455
|
+
message: accessData?.message || error?.message || (errorType === "unauthenticated" ? "\u5F53\u524D\u8D26\u53F7\u5C1A\u672A\u767B\u5F55" : "\u5F53\u524D\u8D26\u53F7\u6CA1\u6709\u8BBF\u95EE\u6743\u9650")
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
var renderBoundaryFallback = (fallback, state) => typeof fallback === "function" ? fallback(state) : fallback;
|
|
459
|
+
var withQuery = (url, params) => {
|
|
460
|
+
const query = new URLSearchParams();
|
|
461
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
462
|
+
if (value === void 0 || value === "") return;
|
|
463
|
+
query.set(key, String(value));
|
|
464
|
+
});
|
|
465
|
+
const serialized = query.toString();
|
|
466
|
+
if (!serialized) return url;
|
|
467
|
+
return `${url}${url.includes("?") ? "&" : "?"}${serialized}`;
|
|
468
|
+
};
|
|
469
|
+
var attachCallback = (loginUrl, callback) => {
|
|
470
|
+
if (!callback) return loginUrl;
|
|
471
|
+
try {
|
|
472
|
+
const base = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
473
|
+
const parsed = new URL(loginUrl, base);
|
|
474
|
+
if (!parsed.searchParams.has("callback") && !parsed.searchParams.has("redirectUri")) {
|
|
475
|
+
parsed.searchParams.set("callback", callback);
|
|
476
|
+
}
|
|
477
|
+
if (loginUrl.startsWith("http://") || loginUrl.startsWith("https://")) {
|
|
478
|
+
return parsed.toString();
|
|
479
|
+
}
|
|
480
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
481
|
+
} catch {
|
|
482
|
+
const separator = loginUrl.includes("?") ? "&" : "?";
|
|
483
|
+
return `${loginUrl}${separator}callback=${encodeURIComponent(callback)}`;
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
var getCurrentHref = () => typeof window === "undefined" ? "" : window.location.href;
|
|
487
|
+
var getCurrentHostname = () => typeof window === "undefined" ? "" : window.location.hostname;
|
|
488
|
+
var getRuntimeEnv = (key) => {
|
|
489
|
+
const env = typeof process !== "undefined" ? process.env : void 0;
|
|
490
|
+
return env?.[key];
|
|
491
|
+
};
|
|
492
|
+
var getRecordValue = (value, key) => {
|
|
493
|
+
if (!value || typeof value !== "object") return void 0;
|
|
494
|
+
return value[key];
|
|
495
|
+
};
|
|
496
|
+
var getRecordString = (value, key) => {
|
|
497
|
+
const result = getRecordValue(value, key);
|
|
498
|
+
return typeof result === "string" ? result : void 0;
|
|
499
|
+
};
|
|
236
500
|
var resolveAppTypeFromLocation = () => {
|
|
237
501
|
if (typeof window === "undefined") return "";
|
|
238
502
|
const segments = window.location.pathname.split("/").filter(Boolean);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/react/openxiangdaProvider.tsx","../../src/runtime/core/fetch.ts"],"sourcesContent":["import React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\"\nimport { createBoundFetch } from \"../core/fetch\"\n\nexport interface RuntimeMenuItem {\n id: string\n name: string\n resourceCode?: string | null\n routeCode?: string | null\n path?: string | null\n type?: string\n formUuid?: string | null\n pageId?: string | null\n parentId?: string | null\n sortOrder?: number\n isHidden?: boolean\n icon?: string | null\n children?: RuntimeMenuItem[]\n [key: string]: unknown\n}\n\nexport interface RuntimePagePermissions {\n appType: string\n hasFullAccess: boolean\n roleCodes: string[]\n roleSource?: string\n menuFormUuids: string[]\n menuCodes: string[]\n routeCodes: string[]\n pathPatterns: string[]\n}\n\nexport interface RuntimeBootstrap {\n appType: string\n app?: Record<string, unknown> | null\n user?: Record<string, unknown> | null\n runtime?: {\n mode?: \"legacy\" | \"react-spa\" | string\n settings?: Record<string, unknown>\n activeReleaseId?: string | null\n activeBuildId?: string | null\n indexUrl?: string | null\n assetBaseUrl?: string | null\n }\n permissions?: RuntimePagePermissions\n menus?: RuntimeMenuItem[]\n servicePrefix?: string\n}\n\nexport interface RouteAccessResult {\n appType: string\n canAccess: boolean\n routeCode?: string\n menuCode?: string\n path?: string\n permissions?: RuntimePagePermissions\n}\n\nexport interface RuntimeRequestState<T> {\n data: T | null\n loading: boolean\n error: Error | null\n}\n\nexport interface OpenXiangdaProviderProps {\n appType?: string\n servicePrefix?: string\n fetchImpl?: typeof fetch\n children: React.ReactNode\n}\n\ninterface OpenXiangdaRuntimeStore extends RuntimeRequestState<RuntimeBootstrap> {\n appType: string\n servicePrefix: string\n fetchImpl: typeof fetch\n reload: () => Promise<void>\n}\n\nconst OpenXiangdaRuntimeContext =\n createContext<OpenXiangdaRuntimeStore | null>(null)\n\nexport const OpenXiangdaProvider: React.FC<OpenXiangdaProviderProps> = ({\n appType,\n servicePrefix = \"/service\",\n fetchImpl,\n children,\n}) => {\n const resolvedFetch = useMemo(() => createBoundFetch(fetchImpl), [fetchImpl])\n const resolvedAppType = useMemo(\n () => appType || resolveAppTypeFromLocation(),\n [appType],\n )\n const [state, setState] = useState<RuntimeRequestState<RuntimeBootstrap>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const reload = useCallback(async () => {\n if (!resolvedAppType) {\n setState({\n data: null,\n loading: false,\n error: new Error(\"appType 不能为空\"),\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await resolvedFetch(\n buildServiceUrl(\n servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n resolvedAppType,\n )}/runtime/bootstrap`,\n ),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await response.json()\n if (!response.ok || payload?.code >= 400) {\n throw new Error(payload?.message || `Runtime bootstrap failed: ${response.status}`)\n }\n setState({\n data: payload?.data || null,\n loading: false,\n error: null,\n })\n } catch (error) {\n setState({\n data: null,\n loading: false,\n error: error instanceof Error ? error : new Error(String(error)),\n })\n }\n }, [resolvedAppType, resolvedFetch, servicePrefix])\n\n useEffect(() => {\n void reload()\n }, [reload])\n\n const value = useMemo<OpenXiangdaRuntimeStore>(\n () => ({\n ...state,\n appType: resolvedAppType,\n servicePrefix,\n fetchImpl: resolvedFetch,\n reload,\n }),\n [reload, resolvedAppType, resolvedFetch, servicePrefix, state],\n )\n\n return (\n <OpenXiangdaRuntimeContext.Provider value={value}>\n {children}\n </OpenXiangdaRuntimeContext.Provider>\n )\n}\n\nexport const useOpenXiangda = () => {\n const context = useContext(OpenXiangdaRuntimeContext)\n if (!context) {\n throw new Error(\"useOpenXiangda must be used inside OpenXiangdaProvider\")\n }\n return context\n}\n\nexport const useRuntimeBootstrap = () => useOpenXiangda()\n\nexport const useAppMenus = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.menus || [],\n }\n}\n\nexport const usePermission = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.permissions || null,\n }\n}\n\nexport interface UseCanAccessRouteInput {\n routeCode?: string\n menuCode?: string\n path?: string\n}\n\nexport const useCanAccessRoute = (input: UseCanAccessRouteInput) => {\n const runtime = useOpenXiangda()\n const [state, setState] = useState<RuntimeRequestState<RouteAccessResult>>({\n data: null,\n loading: true,\n error: null,\n })\n\n useEffect(() => {\n let disposed = false\n const check = async () => {\n const permissions = runtime.data?.permissions\n if (!runtime.appType || runtime.loading) {\n setState(prev => ({ ...prev, loading: runtime.loading }))\n return\n }\n if (permissions?.hasFullAccess) {\n setState({\n data: { appType: runtime.appType, canAccess: true, permissions },\n loading: false,\n error: null,\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await runtime.fetchImpl(\n buildServiceUrl(\n runtime.servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n runtime.appType,\n )}/runtime/routes/check`,\n ),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(input),\n },\n )\n const payload = await response.json()\n if (!disposed) {\n setState({\n data: payload?.data || {\n appType: runtime.appType,\n canAccess: false,\n },\n loading: false,\n error:\n response.ok && payload?.code < 500\n ? null\n : new Error(payload?.message || `Route check failed: ${response.status}`),\n })\n }\n } catch (error) {\n if (!disposed) {\n setState({\n data: null,\n loading: false,\n error: error instanceof Error ? error : new Error(String(error)),\n })\n }\n }\n }\n void check()\n return () => {\n disposed = true\n }\n }, [\n input.menuCode,\n input.path,\n input.routeCode,\n runtime.appType,\n runtime.data?.permissions,\n runtime.fetchImpl,\n runtime.loading,\n runtime.servicePrefix,\n ])\n\n return {\n ...state,\n canAccess: Boolean(state.data?.canAccess),\n }\n}\n\nexport interface PermissionBoundaryProps extends UseCanAccessRouteInput {\n children: React.ReactNode\n fallback?: React.ReactNode\n loadingFallback?: React.ReactNode\n}\n\nexport const PermissionBoundary: React.FC<PermissionBoundaryProps> = ({\n children,\n fallback = null,\n loadingFallback = null,\n routeCode,\n menuCode,\n path,\n}) => {\n const access = useCanAccessRoute({ routeCode, menuCode, path })\n if (access.loading) return <>{loadingFallback}</>\n if (!access.canAccess) return <>{fallback}</>\n return <>{children}</>\n}\n\nconst buildServiceUrl = (servicePrefix: string, path: string) => {\n const prefix = servicePrefix.endsWith(\"/\")\n ? servicePrefix.slice(0, -1)\n : servicePrefix\n const suffix = path.startsWith(\"/\") ? path : `/${path}`\n return `${prefix}${suffix}`\n}\n\nconst resolveAppTypeFromLocation = () => {\n if (typeof window === \"undefined\") return \"\"\n const segments = window.location.pathname.split(\"/\").filter(Boolean)\n const viewIndex = segments[0] === \"view\" ? 1 : 0\n if (segments[viewIndex] === \"submit\") return segments[viewIndex + 1] || \"\"\n if (segments[viewIndex] === \"preview\") return segments[viewIndex + 1] || \"\"\n return segments[viewIndex] || \"\"\n}\n","export const createBoundFetch = (fetchImpl?: typeof fetch): typeof fetch => {\n const baseFetch = fetchImpl || globalThis.fetch;\n return ((input, init) => baseFetch.call(globalThis, input, init)) as typeof fetch;\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/react/openxiangdaProvider.tsx","../../src/runtime/core/fetch.ts"],"sourcesContent":["import React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\"\nimport { createBoundFetch } from \"../core/fetch\"\n\nexport type RuntimeErrorType =\n | \"unauthenticated\"\n | \"forbidden\"\n | \"network\"\n | \"unknown\"\n\nexport type RuntimeRequestError = Error & {\n type?: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n}\n\nexport interface RuntimeErrorSnapshot {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n payload?: unknown\n}\n\nexport class RuntimeHttpError extends Error {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n\n constructor(snapshot: RuntimeErrorSnapshot) {\n super(snapshot.message)\n this.name = \"RuntimeHttpError\"\n this.type = snapshot.type\n this.status = snapshot.status\n this.code = snapshot.code\n this.payload = snapshot.payload\n }\n}\n\nexport interface RuntimeMenuItem {\n id: string\n name: string\n resourceCode?: string | null\n routeCode?: string | null\n path?: string | null\n type?: string\n formUuid?: string | null\n pageId?: string | null\n parentId?: string | null\n sortOrder?: number\n isHidden?: boolean\n icon?: string | null\n children?: RuntimeMenuItem[]\n [key: string]: unknown\n}\n\nexport interface RuntimePagePermissions {\n appType: string\n hasFullAccess: boolean\n roleCodes: string[]\n roleSource?: string\n menuFormUuids: string[]\n menuCodes: string[]\n routeCodes: string[]\n pathPatterns: string[]\n}\n\nexport interface RuntimeBootstrap {\n appType: string\n app?: Record<string, unknown> | null\n user?: Record<string, unknown> | null\n runtime?: {\n mode?: \"legacy\" | \"react-spa\" | string\n settings?: Record<string, unknown>\n activeReleaseId?: string | null\n activeBuildId?: string | null\n indexUrl?: string | null\n assetBaseUrl?: string | null\n }\n permissions?: RuntimePagePermissions\n menus?: RuntimeMenuItem[]\n servicePrefix?: string\n}\n\nexport interface RouteAccessResult {\n appType: string\n canAccess: boolean\n routeCode?: string\n menuCode?: string\n path?: string\n status?: number\n code?: number | string\n message?: string\n errorType?: RuntimeErrorType\n payload?: unknown\n permissions?: RuntimePagePermissions\n}\n\nexport interface RuntimeRequestState<T> {\n data: T | null\n loading: boolean\n error: RuntimeRequestError | null\n}\n\nexport interface OpenXiangdaProviderProps {\n appType?: string\n servicePrefix?: string\n fetchImpl?: typeof fetch\n children: React.ReactNode\n}\n\ninterface OpenXiangdaRuntimeStore extends RuntimeRequestState<RuntimeBootstrap> {\n appType: string\n servicePrefix: string\n fetchImpl: typeof fetch\n reload: () => Promise<void>\n}\n\nconst OpenXiangdaRuntimeContext =\n createContext<OpenXiangdaRuntimeStore | null>(null)\n\nexport const OpenXiangdaProvider: React.FC<OpenXiangdaProviderProps> = ({\n appType,\n servicePrefix = \"/service\",\n fetchImpl,\n children,\n}) => {\n const resolvedFetch = useMemo(() => createBoundFetch(fetchImpl), [fetchImpl])\n const resolvedAppType = useMemo(\n () => appType || resolveAppTypeFromLocation(),\n [appType],\n )\n const [state, setState] = useState<RuntimeRequestState<RuntimeBootstrap>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const reload = useCallback(async () => {\n if (!resolvedAppType) {\n setState({\n data: null,\n loading: false,\n error: createRuntimeError({\n message: \"appType 不能为空\",\n type: \"unknown\",\n }),\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await resolvedFetch(\n buildServiceUrl(\n servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n resolvedAppType,\n )}/runtime/bootstrap`,\n ),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Runtime bootstrap failed: ${response.status}`,\n )\n }\n setState({\n data: payload?.data || null,\n loading: false,\n error: null,\n })\n } catch (error) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }, [resolvedAppType, resolvedFetch, servicePrefix])\n\n useEffect(() => {\n void reload()\n }, [reload])\n\n const value = useMemo<OpenXiangdaRuntimeStore>(\n () => ({\n ...state,\n appType: resolvedAppType,\n servicePrefix,\n fetchImpl: resolvedFetch,\n reload,\n }),\n [reload, resolvedAppType, resolvedFetch, servicePrefix, state],\n )\n\n return (\n <OpenXiangdaRuntimeContext.Provider value={value}>\n {children}\n </OpenXiangdaRuntimeContext.Provider>\n )\n}\n\nexport const useOpenXiangda = () => {\n const context = useContext(OpenXiangdaRuntimeContext)\n if (!context) {\n throw new Error(\"useOpenXiangda must be used inside OpenXiangdaProvider\")\n }\n return context\n}\n\nexport const useRuntimeBootstrap = () => useOpenXiangda()\n\nexport const useAppMenus = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.menus || [],\n }\n}\n\nexport const usePermission = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.permissions || null,\n }\n}\n\nexport interface UseCanAccessRouteInput {\n routeCode?: string\n menuCode?: string\n path?: string\n}\n\nexport const useCanAccessRoute = (input: UseCanAccessRouteInput) => {\n const runtime = useOpenXiangda()\n const [state, setState] = useState<RuntimeRequestState<RouteAccessResult>>({\n data: null,\n loading: true,\n error: null,\n })\n\n useEffect(() => {\n let disposed = false\n const check = async () => {\n const permissions = runtime.data?.permissions\n if (!runtime.appType || runtime.loading) {\n setState(prev => ({ ...prev, loading: runtime.loading }))\n return\n }\n if (runtime.error && !runtime.data) {\n const snapshot = toRuntimeErrorSnapshot(runtime.error)\n setState({\n data: {\n appType: runtime.appType,\n canAccess: false,\n status: snapshot.status,\n code: snapshot.code,\n message: snapshot.message,\n errorType: snapshot.type,\n payload: snapshot.payload,\n },\n loading: false,\n error: runtime.error,\n })\n return\n }\n if (permissions?.hasFullAccess) {\n setState({\n data: { appType: runtime.appType, canAccess: true, permissions },\n loading: false,\n error: null,\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await runtime.fetchImpl(\n buildServiceUrl(\n runtime.servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n runtime.appType,\n )}/runtime/routes/check`,\n ),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(input),\n },\n )\n const payload = await readJsonPayload(response)\n const code = payload?.code ?? response.status\n const canAccess = Boolean(payload?.data?.canAccess)\n const errorType = canAccess\n ? undefined\n : classifyRuntimeError(response.status, code)\n const data: RouteAccessResult = {\n ...(payload?.data || {\n appType: runtime.appType,\n canAccess: false,\n }),\n appType: payload?.data?.appType || runtime.appType,\n canAccess,\n status: response.status,\n code,\n message: payload?.message,\n errorType,\n payload,\n }\n if (!disposed) {\n const shouldTreatAsError =\n !response.ok || (typeof code === \"number\" && code >= 500)\n setState({\n data,\n loading: false,\n error: shouldTreatAsError\n ? createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Route check failed: ${response.status}`,\n )\n : null,\n })\n }\n } catch (error) {\n if (!disposed) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }\n }\n void check()\n return () => {\n disposed = true\n }\n }, [\n input.menuCode,\n input.path,\n input.routeCode,\n runtime.appType,\n runtime.data?.permissions,\n runtime.fetchImpl,\n runtime.loading,\n runtime.servicePrefix,\n ])\n\n return {\n ...state,\n canAccess: Boolean(state.data?.canAccess),\n }\n}\n\nexport interface PermissionBoundaryProps extends UseCanAccessRouteInput {\n children: React.ReactNode\n fallback?: React.ReactNode | PermissionBoundaryFallback\n loadingFallback?: React.ReactNode | PermissionBoundaryFallback\n}\n\nexport interface PermissionBoundaryFallbackState {\n access: ReturnType<typeof useCanAccessRoute>\n runtime: ReturnType<typeof useOpenXiangda>\n error: RuntimeRequestError | null\n errorType: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n}\n\nexport type PermissionBoundaryFallback = (\n state: PermissionBoundaryFallbackState,\n) => React.ReactNode\n\nexport const PermissionBoundary: React.FC<PermissionBoundaryProps> = ({\n children,\n fallback = null,\n loadingFallback = null,\n routeCode,\n menuCode,\n path,\n}) => {\n const runtime = useOpenXiangda()\n const access = useCanAccessRoute({ routeCode, menuCode, path })\n const fallbackState = createPermissionFallbackState(access, runtime)\n if (access.loading) {\n return <>{renderBoundaryFallback(loadingFallback, fallbackState)}</>\n }\n if (!access.canAccess) {\n return <>{renderBoundaryFallback(fallback, fallbackState)}</>\n }\n return <>{children}</>\n}\n\nexport interface RuntimeResolveLoginOptions {\n redirectUri?: string\n loginUrl?: string\n domain?: string\n}\n\nexport interface RuntimeRedirectLoginOptions extends RuntimeResolveLoginOptions {\n replace?: boolean\n}\n\nexport interface RuntimeLogoutOptions extends RuntimeRedirectLoginOptions {\n continueOnError?: boolean\n}\n\nexport const useRuntimeAuth = () => {\n const runtime = useOpenXiangda()\n\n const resolveLoginUrl = useCallback(\n async (options: RuntimeResolveLoginOptions = {}) => {\n const redirectUri = options.redirectUri || getCurrentHref()\n const domain = options.domain || getCurrentHostname()\n const appTenantId = getRecordString(runtime.data?.app, \"tenantId\")\n\n try {\n const statusUrl = withQuery(\n buildServiceUrl(runtime.servicePrefix, \"/api/sso/status\"),\n { domain },\n )\n const statusResponse = await runtime.fetchImpl(statusUrl, {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n })\n const statusPayload = await readJsonPayload(statusResponse)\n const sso = statusPayload?.data || {}\n const enabled = Boolean(sso.enabled)\n const shouldUseSso = Boolean(\n enabled && (sso.forceLogin ?? sso.autoRedirect ?? true),\n )\n if (shouldUseSso) {\n const loginUrlResponse = await runtime.fetchImpl(\n withQuery(buildServiceUrl(runtime.servicePrefix, \"/api/sso/login-url\"), {\n domain,\n redirectUri,\n ...(sso.tenantId || appTenantId\n ? { tenantId: String(sso.tenantId || appTenantId) }\n : {}),\n ...(sso.protocol ? { protocol: String(sso.protocol) } : {}),\n }),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const loginUrlPayload = await readJsonPayload(loginUrlResponse)\n const loginUrl =\n loginUrlPayload?.data?.loginUrl ||\n loginUrlPayload?.data?.url ||\n loginUrlPayload?.loginUrl ||\n loginUrlPayload?.url\n if (loginUrl) return String(loginUrl)\n }\n } catch {\n // Login resolution must always have a local fallback so logged-out\n // users are not stranded behind a permission state.\n }\n\n const configuredLoginUrl =\n options.loginUrl ||\n getRuntimeEnv(\"OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_BATH_AUTH_URL\") ||\n getRuntimeEnv(\"BATH_AUTH_URL\")\n if (configuredLoginUrl) {\n return attachCallback(configuredLoginUrl, redirectUri)\n }\n return attachCallback(\"/login\", redirectUri)\n },\n [runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix],\n )\n\n const redirectToLogin = useCallback(\n async (options: RuntimeRedirectLoginOptions = {}) => {\n const loginUrl = await resolveLoginUrl(options)\n if (typeof window !== \"undefined\") {\n if (options.replace === false) {\n window.location.assign(loginUrl)\n } else {\n window.location.replace(loginUrl)\n }\n }\n return loginUrl\n },\n [resolveLoginUrl],\n )\n\n const logout = useCallback(async () => {\n const response = await runtime.fetchImpl(\n buildServiceUrl(runtime.servicePrefix, \"/api/auth/logout\"),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Logout failed: ${response.status}`,\n )\n }\n return payload\n }, [runtime.fetchImpl, runtime.servicePrefix])\n\n const logoutAndRedirect = useCallback(\n async (options: RuntimeLogoutOptions = {}) => {\n try {\n await logout()\n } catch (error) {\n if (options.continueOnError === false) throw error\n }\n return redirectToLogin(options)\n },\n [logout, redirectToLogin],\n )\n\n return {\n logout,\n logoutAndRedirect,\n redirectToLogin,\n resolveLoginUrl,\n }\n}\n\nconst buildServiceUrl = (servicePrefix: string, path: string) => {\n const prefix = servicePrefix.endsWith(\"/\")\n ? servicePrefix.slice(0, -1)\n : servicePrefix\n const suffix = path.startsWith(\"/\") ? path : `/${path}`\n return `${prefix}${suffix}`\n}\n\nconst readJsonPayload = async (response: Response) => {\n try {\n return await response.json()\n } catch {\n return null\n }\n}\n\nconst createRuntimeHttpError = (\n response: Response,\n payload: unknown,\n fallbackMessage: string,\n): RuntimeRequestError =>\n createRuntimeError({\n type: classifyRuntimeError(\n response.status,\n getRecordValue(payload, \"code\") as number | string | undefined,\n ),\n status: response.status,\n code: getRecordValue(payload, \"code\") as number | string | undefined,\n message:\n (getRecordValue(payload, \"message\") as string | undefined) ||\n fallbackMessage,\n payload,\n })\n\nconst createRuntimeError = (\n snapshot: RuntimeErrorSnapshot,\n): RuntimeRequestError =>\n new RuntimeHttpError({\n ...snapshot,\n type: snapshot.type || \"unknown\",\n message: snapshot.message || \"Runtime request failed\",\n })\n\nconst normalizeRuntimeError = (error: unknown): RuntimeRequestError => {\n if (error instanceof RuntimeHttpError) return error\n if (error instanceof Error) {\n const runtimeError = error as RuntimeRequestError\n runtimeError.type = runtimeError.type || classifyRuntimeError(runtimeError.status, runtimeError.code)\n return runtimeError\n }\n return createRuntimeError({\n type: \"unknown\",\n message: String(error),\n })\n}\n\nconst toRuntimeErrorSnapshot = (\n error: RuntimeRequestError,\n): RuntimeErrorSnapshot => ({\n type: error.type || classifyRuntimeError(error.status, error.code),\n status: error.status,\n code: error.code,\n message: error.message || \"Runtime request failed\",\n payload: error.payload,\n})\n\nconst classifyRuntimeError = (\n status?: number,\n code?: number | string,\n): RuntimeErrorType => {\n const normalizedCode = typeof code === \"string\" ? Number(code) : code\n if (status === 401 || normalizedCode === 401) return \"unauthenticated\"\n if (status === 403 || normalizedCode === 403) return \"forbidden\"\n if (!status && !normalizedCode) return \"network\"\n return \"unknown\"\n}\n\nconst createPermissionFallbackState = (\n access: ReturnType<typeof useCanAccessRoute>,\n runtime: ReturnType<typeof useOpenXiangda>,\n): PermissionBoundaryFallbackState => {\n const error = access.error || runtime.error\n const accessData = access.data\n const errorType =\n accessData?.errorType ||\n error?.type ||\n (!access.canAccess ? \"forbidden\" : \"unknown\")\n return {\n access,\n runtime,\n error,\n errorType,\n status: accessData?.status || error?.status,\n code: accessData?.code || error?.code,\n message:\n accessData?.message ||\n error?.message ||\n (errorType === \"unauthenticated\"\n ? \"当前账号尚未登录\"\n : \"当前账号没有访问权限\"),\n }\n}\n\nconst renderBoundaryFallback = (\n fallback: React.ReactNode | PermissionBoundaryFallback,\n state: PermissionBoundaryFallbackState,\n) => (typeof fallback === \"function\" ? fallback(state) : fallback)\n\nconst withQuery = (\n url: string,\n params: Record<string, string | number | boolean | undefined>,\n) => {\n const query = new URLSearchParams()\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === \"\") return\n query.set(key, String(value))\n })\n const serialized = query.toString()\n if (!serialized) return url\n return `${url}${url.includes(\"?\") ? \"&\" : \"?\"}${serialized}`\n}\n\nconst attachCallback = (loginUrl: string, callback: string) => {\n if (!callback) return loginUrl\n try {\n const base =\n typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\"\n const parsed = new URL(loginUrl, base)\n if (!parsed.searchParams.has(\"callback\") && !parsed.searchParams.has(\"redirectUri\")) {\n parsed.searchParams.set(\"callback\", callback)\n }\n if (loginUrl.startsWith(\"http://\") || loginUrl.startsWith(\"https://\")) {\n return parsed.toString()\n }\n return `${parsed.pathname}${parsed.search}${parsed.hash}`\n } catch {\n const separator = loginUrl.includes(\"?\") ? \"&\" : \"?\"\n return `${loginUrl}${separator}callback=${encodeURIComponent(callback)}`\n }\n}\n\nconst getCurrentHref = () =>\n typeof window === \"undefined\" ? \"\" : window.location.href\n\nconst getCurrentHostname = () =>\n typeof window === \"undefined\" ? \"\" : window.location.hostname\n\nconst getRuntimeEnv = (key: string) => {\n const env =\n typeof process !== \"undefined\"\n ? (process as unknown as { env?: Record<string, string | undefined> }).env\n : undefined\n return env?.[key]\n}\n\nconst getRecordValue = (value: unknown, key: string) => {\n if (!value || typeof value !== \"object\") return undefined\n return (value as Record<string, unknown>)[key]\n}\n\nconst getRecordString = (value: unknown, key: string) => {\n const result = getRecordValue(value, key)\n return typeof result === \"string\" ? result : undefined\n}\n\nconst resolveAppTypeFromLocation = () => {\n if (typeof window === \"undefined\") return \"\"\n const segments = window.location.pathname.split(\"/\").filter(Boolean)\n const viewIndex = segments[0] === \"view\" ? 1 : 0\n if (segments[viewIndex] === \"submit\") return segments[viewIndex + 1] || \"\"\n if (segments[viewIndex] === \"preview\") return segments[viewIndex + 1] || \"\"\n return segments[viewIndex] || \"\"\n}\n","export const createBoundFetch = (fetchImpl?: typeof fetch): typeof fetch => {\n const baseFetch = fetchImpl || globalThis.fetch;\n return ((input, init) => baseFetch.call(globalThis, input, init)) as typeof fetch;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import React__default from 'react';
|
|
2
2
|
|
|
3
|
+
type RuntimeErrorType = "unauthenticated" | "forbidden" | "network" | "unknown";
|
|
4
|
+
type RuntimeRequestError = Error & {
|
|
5
|
+
type?: RuntimeErrorType;
|
|
6
|
+
status?: number;
|
|
7
|
+
code?: number | string;
|
|
8
|
+
payload?: unknown;
|
|
9
|
+
};
|
|
10
|
+
interface RuntimeErrorSnapshot {
|
|
11
|
+
type: RuntimeErrorType;
|
|
12
|
+
status?: number;
|
|
13
|
+
code?: number | string;
|
|
14
|
+
message: string;
|
|
15
|
+
payload?: unknown;
|
|
16
|
+
}
|
|
17
|
+
declare class RuntimeHttpError extends Error {
|
|
18
|
+
type: RuntimeErrorType;
|
|
19
|
+
status?: number;
|
|
20
|
+
code?: number | string;
|
|
21
|
+
payload?: unknown;
|
|
22
|
+
constructor(snapshot: RuntimeErrorSnapshot);
|
|
23
|
+
}
|
|
3
24
|
interface RuntimeMenuItem {
|
|
4
25
|
id: string;
|
|
5
26
|
name: string;
|
|
@@ -48,12 +69,17 @@ interface RouteAccessResult {
|
|
|
48
69
|
routeCode?: string;
|
|
49
70
|
menuCode?: string;
|
|
50
71
|
path?: string;
|
|
72
|
+
status?: number;
|
|
73
|
+
code?: number | string;
|
|
74
|
+
message?: string;
|
|
75
|
+
errorType?: RuntimeErrorType;
|
|
76
|
+
payload?: unknown;
|
|
51
77
|
permissions?: RuntimePagePermissions;
|
|
52
78
|
}
|
|
53
79
|
interface RuntimeRequestState<T> {
|
|
54
80
|
data: T | null;
|
|
55
81
|
loading: boolean;
|
|
56
|
-
error:
|
|
82
|
+
error: RuntimeRequestError | null;
|
|
57
83
|
}
|
|
58
84
|
interface OpenXiangdaProviderProps {
|
|
59
85
|
appType?: string;
|
|
@@ -77,7 +103,7 @@ declare const useAppMenus: () => {
|
|
|
77
103
|
fetchImpl: typeof fetch;
|
|
78
104
|
reload: () => Promise<void>;
|
|
79
105
|
loading: boolean;
|
|
80
|
-
error:
|
|
106
|
+
error: RuntimeRequestError | null;
|
|
81
107
|
};
|
|
82
108
|
declare const usePermission: () => {
|
|
83
109
|
data: RuntimePagePermissions | null;
|
|
@@ -86,7 +112,7 @@ declare const usePermission: () => {
|
|
|
86
112
|
fetchImpl: typeof fetch;
|
|
87
113
|
reload: () => Promise<void>;
|
|
88
114
|
loading: boolean;
|
|
89
|
-
error:
|
|
115
|
+
error: RuntimeRequestError | null;
|
|
90
116
|
};
|
|
91
117
|
interface UseCanAccessRouteInput {
|
|
92
118
|
routeCode?: string;
|
|
@@ -97,13 +123,40 @@ declare const useCanAccessRoute: (input: UseCanAccessRouteInput) => {
|
|
|
97
123
|
canAccess: boolean;
|
|
98
124
|
data: RouteAccessResult | null;
|
|
99
125
|
loading: boolean;
|
|
100
|
-
error:
|
|
126
|
+
error: RuntimeRequestError | null;
|
|
101
127
|
};
|
|
102
128
|
interface PermissionBoundaryProps extends UseCanAccessRouteInput {
|
|
103
129
|
children: React__default.ReactNode;
|
|
104
|
-
fallback?: React__default.ReactNode;
|
|
105
|
-
loadingFallback?: React__default.ReactNode;
|
|
130
|
+
fallback?: React__default.ReactNode | PermissionBoundaryFallback;
|
|
131
|
+
loadingFallback?: React__default.ReactNode | PermissionBoundaryFallback;
|
|
132
|
+
}
|
|
133
|
+
interface PermissionBoundaryFallbackState {
|
|
134
|
+
access: ReturnType<typeof useCanAccessRoute>;
|
|
135
|
+
runtime: ReturnType<typeof useOpenXiangda>;
|
|
136
|
+
error: RuntimeRequestError | null;
|
|
137
|
+
errorType: RuntimeErrorType;
|
|
138
|
+
status?: number;
|
|
139
|
+
code?: number | string;
|
|
140
|
+
message: string;
|
|
106
141
|
}
|
|
142
|
+
type PermissionBoundaryFallback = (state: PermissionBoundaryFallbackState) => React__default.ReactNode;
|
|
107
143
|
declare const PermissionBoundary: React__default.FC<PermissionBoundaryProps>;
|
|
144
|
+
interface RuntimeResolveLoginOptions {
|
|
145
|
+
redirectUri?: string;
|
|
146
|
+
loginUrl?: string;
|
|
147
|
+
domain?: string;
|
|
148
|
+
}
|
|
149
|
+
interface RuntimeRedirectLoginOptions extends RuntimeResolveLoginOptions {
|
|
150
|
+
replace?: boolean;
|
|
151
|
+
}
|
|
152
|
+
interface RuntimeLogoutOptions extends RuntimeRedirectLoginOptions {
|
|
153
|
+
continueOnError?: boolean;
|
|
154
|
+
}
|
|
155
|
+
declare const useRuntimeAuth: () => {
|
|
156
|
+
logout: () => Promise<any>;
|
|
157
|
+
logoutAndRedirect: (options?: RuntimeLogoutOptions) => Promise<string>;
|
|
158
|
+
redirectToLogin: (options?: RuntimeRedirectLoginOptions) => Promise<string>;
|
|
159
|
+
resolveLoginUrl: (options?: RuntimeResolveLoginOptions) => Promise<string>;
|
|
160
|
+
};
|
|
108
161
|
|
|
109
|
-
export { OpenXiangdaProvider, type OpenXiangdaProviderProps, PermissionBoundary, type PermissionBoundaryProps, type RouteAccessResult, type RuntimeBootstrap, type RuntimeMenuItem, type RuntimePagePermissions, type RuntimeRequestState, type UseCanAccessRouteInput, useAppMenus, useCanAccessRoute, useOpenXiangda, usePermission, useRuntimeBootstrap };
|
|
162
|
+
export { OpenXiangdaProvider, type OpenXiangdaProviderProps, PermissionBoundary, type PermissionBoundaryFallback, type PermissionBoundaryFallbackState, type PermissionBoundaryProps, type RouteAccessResult, type RuntimeBootstrap, type RuntimeErrorSnapshot, type RuntimeErrorType, RuntimeHttpError, type RuntimeLogoutOptions, type RuntimeMenuItem, type RuntimePagePermissions, type RuntimeRedirectLoginOptions, type RuntimeRequestError, type RuntimeRequestState, type RuntimeResolveLoginOptions, type UseCanAccessRouteInput, useAppMenus, useCanAccessRoute, useOpenXiangda, usePermission, useRuntimeAuth, useRuntimeBootstrap };
|