@lark-apaas/client-toolkit 1.2.17-alpha.1 → 1.2.17-alpha.2
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/lib/antd-table.d.ts +2 -2
- package/lib/apis/aily-chat.d.ts +2 -0
- package/lib/apis/aily-chat.js +2 -0
- package/lib/apis/components/ActiveLink.d.ts +26 -0
- package/lib/apis/components/ActiveLink.js +66 -0
- package/lib/apis/hooks/useScrollReveal.d.ts +1 -0
- package/lib/apis/hooks/useScrollReveal.js +1 -0
- package/lib/apis/utils/getEnv.d.ts +1 -0
- package/lib/apis/utils/getEnv.js +2 -0
- package/lib/apis/utils/scopedStorage.d.ts +1 -0
- package/lib/apis/utils/scopedStorage.js +2 -0
- package/lib/auth.d.ts +1 -0
- package/lib/auth.js +2 -0
- package/lib/components/AppContainer/IframeBridge.d.ts +0 -1
- package/lib/components/AppContainer/IframeBridge.js +1 -20
- package/lib/components/AppContainer/api-proxy/core.js +2 -1
- package/lib/components/AppContainer/index.d.ts +9 -2
- package/lib/components/AppContainer/index.js +14 -70
- package/lib/components/AppContainer/utils/childApi.js +1 -0
- package/lib/components/AppContainer/utils/tea.js +1 -1
- package/lib/components/ErrorRender/index.js +5 -11
- package/lib/components/User/UserSelect.js +1 -13
- package/lib/components/theme/index.d.ts +0 -1
- package/lib/components/theme/index.js +0 -1
- package/lib/components/theme/util.d.ts +0 -2
- package/lib/components/theme/util.js +0 -108
- package/lib/components/ui/toast.d.ts +2 -0
- package/lib/components/ui/toast.js +53 -0
- package/lib/hooks/index.d.ts +1 -0
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/useScrollReveal.d.ts +61 -0
- package/lib/hooks/useScrollReveal.js +37 -0
- package/lib/index.js +5 -1
- package/lib/integrations/dataloom.js +4 -2
- package/lib/integrations/services/types.d.ts +1 -0
- package/lib/logger/batch-logger.js +3 -2
- package/lib/logger/intercept-global-error.js +16 -14
- package/lib/logger/log-types.d.ts +4 -4
- package/lib/logger/log-types.js +1 -1
- package/lib/logger/selected-logs.js +1 -2
- package/lib/runtime/axios.d.ts +5 -0
- package/lib/runtime/axios.js +2 -0
- package/lib/runtime/dayjs.d.ts +5 -0
- package/lib/runtime/dayjs.js +2 -0
- package/lib/runtime/iframe-bridge.d.ts +11 -0
- package/lib/runtime/iframe-bridge.js +29 -0
- package/lib/runtime/index.d.ts +24 -0
- package/lib/runtime/index.js +17 -0
- package/lib/runtime/observable.d.ts +5 -0
- package/lib/runtime/observable.js +2 -0
- package/lib/runtime/react-devtools-hook.d.ts +19 -0
- package/lib/runtime/react-devtools-hook.js +20 -0
- package/lib/runtime/server-log.d.ts +5 -0
- package/lib/runtime/server-log.js +41 -0
- package/lib/runtime/styles.d.ts +5 -0
- package/lib/runtime/styles.js +1 -0
- package/lib/theme-layer.css +2 -1
- package/lib/utils/axiosConfig.js +25 -3
- package/lib/utils/getParentOrigin.js +12 -2
- package/lib/utils/hmr-api.d.ts +39 -0
- package/lib/utils/hmr-api.js +36 -0
- package/lib/utils/module-hot.d.ts +9 -5
- package/lib/utils/module-hot.js +9 -10
- package/lib/utils/requestManager.js +1 -3
- package/lib/utils/scopedStorage.d.ts +5 -0
- package/lib/utils/scopedStorage.js +46 -0
- package/package.json +2 -2
- package/lib/components/AppContainer/utils/listenHot.d.ts +0 -1
- package/lib/components/AppContainer/utils/listenHot.js +0 -57
- package/lib/components/theme/ui-config.d.ts +0 -1
- package/lib/components/theme/ui-config.js +0 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Options for useScrollReveal hook
|
|
4
|
+
*/
|
|
5
|
+
export interface UseScrollRevealOptions<T extends HTMLElement = HTMLElement> {
|
|
6
|
+
/** Ref to the container element to scope the query (default: document.body) */
|
|
7
|
+
containerRef?: RefObject<T | null>;
|
|
8
|
+
/** IntersectionObserver threshold - element visibility percentage to trigger (default: 0.1) */
|
|
9
|
+
threshold?: number;
|
|
10
|
+
/** IntersectionObserver rootMargin - margin around root (default: '0px 0px -50px 0px') */
|
|
11
|
+
rootMargin?: string;
|
|
12
|
+
/** CSS class to add when element becomes visible (default: 'visible') */
|
|
13
|
+
visibleClass?: string;
|
|
14
|
+
/** CSS selector for elements to observe (default: '.scroll-reveal') */
|
|
15
|
+
selector?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook to enable scroll reveal animations using IntersectionObserver.
|
|
19
|
+
*
|
|
20
|
+
* Observes elements with the specified selector and adds a visibility class
|
|
21
|
+
* when they enter the viewport.
|
|
22
|
+
*
|
|
23
|
+
* @param options - Configuration options
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Usage without parameters (queries entire document.body)
|
|
28
|
+
* import { useScrollReveal } from '@lark-apaas/client-toolkit/hooks/useScrollReveal';
|
|
29
|
+
*
|
|
30
|
+
* function MyComponent() {
|
|
31
|
+
* useScrollReveal();
|
|
32
|
+
*
|
|
33
|
+
* return <div className="scroll-reveal">I will fade in on scroll!</div>;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Usage with container ref
|
|
40
|
+
* import { useRef } from 'react';
|
|
41
|
+
* import { useScrollReveal } from '@lark-apaas/client-toolkit/hooks/useScrollReveal';
|
|
42
|
+
*
|
|
43
|
+
* function MyComponent() {
|
|
44
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
45
|
+
* useScrollReveal({ containerRef });
|
|
46
|
+
*
|
|
47
|
+
* return (
|
|
48
|
+
* <div ref={containerRef}>
|
|
49
|
+
* <div className="scroll-reveal">I will fade in on scroll!</div>
|
|
50
|
+
* </div>
|
|
51
|
+
* );
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* // Usage with custom options
|
|
58
|
+
* useScrollReveal({ threshold: 0.2, visibleClass: 'animate-in' });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function useScrollReveal<T extends HTMLElement = HTMLElement>(options?: UseScrollRevealOptions<T>): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
const DEFAULT_OPTIONS = {
|
|
3
|
+
threshold: 0.1,
|
|
4
|
+
rootMargin: '0px 0px -50px 0px',
|
|
5
|
+
visibleClass: 'visible',
|
|
6
|
+
selector: '.scroll-reveal'
|
|
7
|
+
};
|
|
8
|
+
function useScrollReveal(options) {
|
|
9
|
+
const { containerRef, threshold, rootMargin, visibleClass, selector } = {
|
|
10
|
+
...DEFAULT_OPTIONS,
|
|
11
|
+
...options
|
|
12
|
+
};
|
|
13
|
+
useEffect(()=>{
|
|
14
|
+
const container = containerRef?.current ?? document.body;
|
|
15
|
+
if (!container) return;
|
|
16
|
+
const observer = new IntersectionObserver((entries)=>{
|
|
17
|
+
entries.forEach((entry)=>{
|
|
18
|
+
if (entry.isIntersecting) entry.target.classList.add(visibleClass);
|
|
19
|
+
});
|
|
20
|
+
}, {
|
|
21
|
+
threshold,
|
|
22
|
+
rootMargin
|
|
23
|
+
});
|
|
24
|
+
const elements = container.querySelectorAll(selector);
|
|
25
|
+
elements.forEach((el)=>observer.observe(el));
|
|
26
|
+
return ()=>{
|
|
27
|
+
observer.disconnect();
|
|
28
|
+
};
|
|
29
|
+
}, [
|
|
30
|
+
containerRef,
|
|
31
|
+
threshold,
|
|
32
|
+
rootMargin,
|
|
33
|
+
visibleClass,
|
|
34
|
+
selector
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
export { useScrollReveal };
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createClient } from "@lark-apaas/client-capability";
|
|
2
2
|
import { normalizeBasePath } from "./utils/utils.js";
|
|
3
3
|
import { logger } from "./logger/index.js";
|
|
4
|
+
import { showToast } from "./components/ui/toast.js";
|
|
4
5
|
import { version } from "../package.json";
|
|
5
6
|
const capabilityClient = createClient({
|
|
6
7
|
baseURL: normalizeBasePath(process.env.CLIENT_BASE_PATH),
|
|
@@ -9,7 +10,10 @@ const capabilityClient = createClient({
|
|
|
9
10
|
'X-Suda-Csrf-Token': window.csrfToken ?? ''
|
|
10
11
|
}
|
|
11
12
|
},
|
|
12
|
-
logger: logger
|
|
13
|
+
logger: logger,
|
|
14
|
+
onRateLimitError: ()=>{
|
|
15
|
+
showToast('应用额度已耗尽,请联系应用开发者');
|
|
16
|
+
}
|
|
13
17
|
});
|
|
14
18
|
const src = {
|
|
15
19
|
version: version
|
|
@@ -3,8 +3,10 @@ import { createClient } from "@data-loom/js";
|
|
|
3
3
|
import { getAppId } from "../utils/getAppId.js";
|
|
4
4
|
import { getInitialInfo } from "../utils/getInitialInfo.js";
|
|
5
5
|
const createDataLoomClient = (url, pat)=>{
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const { baseUrl, workspace } = url ? splitWorkspaceUrl(url) : {
|
|
7
|
+
baseUrl: '',
|
|
8
|
+
workspace: ''
|
|
9
|
+
};
|
|
8
10
|
const appId = getAppId(window.location.pathname);
|
|
9
11
|
return createClient(baseUrl, pat, workspace, {
|
|
10
12
|
global: {
|
|
@@ -4,9 +4,9 @@ class BatchLogger {
|
|
|
4
4
|
flushTimer = null;
|
|
5
5
|
isProcessing = false;
|
|
6
6
|
originConsole;
|
|
7
|
-
constructor(
|
|
7
|
+
constructor(console1, config){
|
|
8
8
|
this.originConsole = {
|
|
9
|
-
...
|
|
9
|
+
...console1
|
|
10
10
|
};
|
|
11
11
|
const { userId = '', tenantId = '', appId = '' } = window || {};
|
|
12
12
|
this.config = {
|
|
@@ -131,4 +131,5 @@ function destroyBatchLogger() {
|
|
|
131
131
|
defaultBatchLogger = null;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
+
if ('production' !== process.env.NODE_ENV && 'undefined' != typeof window) defaultBatchLogger = new BatchLogger(console);
|
|
134
135
|
export { BatchLogger, batchLogInfo, destroyBatchLogger, getBatchLogger, initBatchLogger };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getHmrApi } from "../utils/hmr-api.js";
|
|
2
2
|
import { submitPostMessage, submitSlardarEvent } from "../utils/postMessage.js";
|
|
3
3
|
import { levelSchema } from "./log-types.js";
|
|
4
4
|
import { logger } from "./logger.js";
|
|
@@ -63,26 +63,28 @@ function processDevServerLog(log) {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
function listenModuleHmr() {
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
const hmr = getHmrApi();
|
|
67
|
+
if (hmr) {
|
|
68
|
+
hmr.onSuccess(()=>{
|
|
69
|
+
submitPostMessage({
|
|
70
|
+
type: 'DevServerMessage',
|
|
71
|
+
data: {
|
|
72
|
+
type: 'devServer-status',
|
|
73
|
+
status: 'hmr-apply-success'
|
|
74
|
+
}
|
|
75
|
+
});
|
|
74
76
|
});
|
|
75
|
-
|
|
76
|
-
console.warn('hmr apply failed',
|
|
77
|
+
hmr.onError((error)=>{
|
|
78
|
+
console.warn('hmr apply failed', error);
|
|
77
79
|
submitSlardarEvent({
|
|
78
80
|
name: 'sandbox-devServer',
|
|
79
81
|
categories: {
|
|
80
82
|
type: 'hmr-apply-failed',
|
|
81
|
-
|
|
83
|
+
error: String(error)
|
|
82
84
|
}
|
|
83
85
|
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
86
88
|
}
|
|
87
89
|
function interceptErrors() {
|
|
88
90
|
window.addEventListener('error', (event)=>{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import z from 'zod';
|
|
2
2
|
export declare const networkRequestLogSchema: z.ZodObject<{
|
|
3
3
|
method: z.ZodString;
|
|
4
|
-
status: z.
|
|
4
|
+
status: z.ZodNumber;
|
|
5
5
|
statusText: z.ZodString;
|
|
6
6
|
path: z.ZodString;
|
|
7
7
|
requestData: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -27,11 +27,11 @@ export declare const logStackFrameSchema: z.ZodObject<{
|
|
|
27
27
|
columnNumber: z.ZodNumber;
|
|
28
28
|
}, z.core.$strip>;
|
|
29
29
|
export declare const levelSchema: z.ZodEnum<{
|
|
30
|
+
error: "error";
|
|
30
31
|
success: "success";
|
|
31
32
|
debug: "debug";
|
|
32
33
|
info: "info";
|
|
33
34
|
warn: "warn";
|
|
34
|
-
error: "error";
|
|
35
35
|
}>;
|
|
36
36
|
export declare const logMeta: z.ZodObject<{
|
|
37
37
|
stacktrace: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -52,11 +52,11 @@ export declare const logMeta: z.ZodObject<{
|
|
|
52
52
|
export declare const selectedLogSchema: z.ZodObject<{
|
|
53
53
|
type: z.ZodLiteral<"typedLogV2">;
|
|
54
54
|
level: z.ZodEnum<{
|
|
55
|
+
error: "error";
|
|
55
56
|
success: "success";
|
|
56
57
|
debug: "debug";
|
|
57
58
|
info: "info";
|
|
58
59
|
warn: "warn";
|
|
59
|
-
error: "error";
|
|
60
60
|
}>;
|
|
61
61
|
id: z.ZodString;
|
|
62
62
|
args: z.ZodArray<z.ZodUnknown>;
|
|
@@ -80,11 +80,11 @@ export declare const selectedLogSchema: z.ZodObject<{
|
|
|
80
80
|
export type LogLevel = z.infer<typeof levelSchema>;
|
|
81
81
|
export declare const logWithMetaSchema: z.ZodObject<{
|
|
82
82
|
level: z.ZodEnum<{
|
|
83
|
+
error: "error";
|
|
83
84
|
success: "success";
|
|
84
85
|
debug: "debug";
|
|
85
86
|
info: "info";
|
|
86
87
|
warn: "warn";
|
|
87
|
-
error: "error";
|
|
88
88
|
}>;
|
|
89
89
|
args: z.ZodArray<z.ZodUnknown>;
|
|
90
90
|
meta: z.ZodOptional<z.ZodObject<{
|
package/lib/logger/log-types.js
CHANGED
|
@@ -2,7 +2,7 @@ import { SourceMapConsumer as external_source_map_SourceMapConsumer } from "sour
|
|
|
2
2
|
import "../utils/utils.js";
|
|
3
3
|
import { mappingText } from "./source-map-mappings-wasm.js";
|
|
4
4
|
import stacktrace_js from "stacktrace-js";
|
|
5
|
-
import { batchLogInfo
|
|
5
|
+
import { batchLogInfo } from "./batch-logger.js";
|
|
6
6
|
function hexToBuffer(hexString) {
|
|
7
7
|
const hex = hexString.replace(/\s/g, '').toUpperCase();
|
|
8
8
|
if (!/^[0-9A-F]+$/.test(hex)) throw new Error('Invalid hex string');
|
|
@@ -213,7 +213,6 @@ const typedLogInterceptor = (logger)=>({
|
|
|
213
213
|
});
|
|
214
214
|
}
|
|
215
215
|
});
|
|
216
|
-
'production' !== process.env.NODE_ENV && initBatchLogger(console);
|
|
217
216
|
const interceptors = 'production' !== process.env.NODE_ENV ? [
|
|
218
217
|
typedLogInterceptor
|
|
219
218
|
] : [];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { connectToParent } from "penpal";
|
|
2
|
+
import { resolveParentOrigin, submitPostMessage } from "../utils/postMessage.js";
|
|
3
|
+
import { batchLogInfo } from "../logger/batch-logger.js";
|
|
4
|
+
import { childApi } from "../components/AppContainer/utils/childApi.js";
|
|
5
|
+
async function connectParent() {
|
|
6
|
+
submitPostMessage({
|
|
7
|
+
type: 'PreviewReady',
|
|
8
|
+
data: {}
|
|
9
|
+
});
|
|
10
|
+
batchLogInfo('info', JSON.stringify({
|
|
11
|
+
type: 'PreviewReady',
|
|
12
|
+
timestamp: Date.now(),
|
|
13
|
+
url: window.location.href
|
|
14
|
+
}));
|
|
15
|
+
const parentOrigin = resolveParentOrigin();
|
|
16
|
+
if (!parentOrigin) return;
|
|
17
|
+
const connection = connectToParent({
|
|
18
|
+
parentOrigin,
|
|
19
|
+
methods: {
|
|
20
|
+
...childApi
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
await connection.promise;
|
|
24
|
+
}
|
|
25
|
+
function initIframeBridge() {
|
|
26
|
+
if (window.parent === window) return;
|
|
27
|
+
connectParent();
|
|
28
|
+
}
|
|
29
|
+
export { initIframeBridge };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client Toolkit Runtime
|
|
3
|
+
*
|
|
4
|
+
* 全局初始化逻辑,通过 rspack-plugin 自动注入到用户入口之前
|
|
5
|
+
* 无论用户是否使用 AppContainer,这些基础能力始终可用
|
|
6
|
+
*
|
|
7
|
+
* 执行顺序:
|
|
8
|
+
* 1. 全局样式
|
|
9
|
+
* 2. Dayjs 插件注册
|
|
10
|
+
* 3. Axios 配置
|
|
11
|
+
* 4. 可观测初始化
|
|
12
|
+
* 5. Server Log SSE (开发环境)
|
|
13
|
+
*
|
|
14
|
+
* 兼容性说明:
|
|
15
|
+
* - 使用 __FULLSTACK_RUNTIME_INITIALIZED__ 标志位防止重复初始化
|
|
16
|
+
* - 旧版 AppContainer 和新版 runtime 可以共存
|
|
17
|
+
*/
|
|
18
|
+
import './react-devtools-hook';
|
|
19
|
+
import './styles';
|
|
20
|
+
declare global {
|
|
21
|
+
interface Window {
|
|
22
|
+
__FULLSTACK_RUNTIME_INITIALIZED__?: boolean;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "./react-devtools-hook.js";
|
|
2
|
+
import "./styles.js";
|
|
3
|
+
import { registerDayjsPlugins } from "./dayjs.js";
|
|
4
|
+
import { initAxiosConfig } from "./axios.js";
|
|
5
|
+
import { initObservable } from "./observable.js";
|
|
6
|
+
import { initServerLog } from "./server-log.js";
|
|
7
|
+
import { initIframeBridge } from "./iframe-bridge.js";
|
|
8
|
+
if (!window.__FULLSTACK_RUNTIME_INITIALIZED__) {
|
|
9
|
+
window.__FULLSTACK_RUNTIME_INITIALIZED__ = true;
|
|
10
|
+
registerDayjsPlugins();
|
|
11
|
+
initAxiosConfig();
|
|
12
|
+
initObservable();
|
|
13
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
14
|
+
initServerLog();
|
|
15
|
+
initIframeBridge();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inject minimal __REACT_DEVTOOLS_GLOBAL_HOOK__ before React loads.
|
|
3
|
+
* React checks for this hook during module initialization and registers its
|
|
4
|
+
* renderer via hook.inject(). This gives us access to renderer.overrideProps()
|
|
5
|
+
* for live component prop modification in the inspector.
|
|
6
|
+
*
|
|
7
|
+
* Must execute before React's module-level code runs.
|
|
8
|
+
*
|
|
9
|
+
* When react-refresh-runtime runs first (as an rspack runtime module),
|
|
10
|
+
* it may create __REACT_DEVTOOLS_GLOBAL_HOOK__ with an inject() that
|
|
11
|
+
* doesn't populate the renderers Map. We patch the existing hook to
|
|
12
|
+
* ensure renderers are always tracked.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
__REACT_DEVTOOLS_GLOBAL_HOOK__?: any;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
if ('undefined' != typeof window && 'production' !== process.env.NODE_ENV) if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
|
|
2
|
+
const hook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
3
|
+
if (!(hook.renderers instanceof Map)) hook.renderers = new Map();
|
|
4
|
+
const originalInject = 'function' == typeof hook.inject ? hook.inject.bind(hook) : null;
|
|
5
|
+
hook.inject = function(renderer) {
|
|
6
|
+
const id = originalInject ? originalInject(renderer) : hook.renderers.size + 1;
|
|
7
|
+
if (null != id && !hook.renderers.has(id)) hook.renderers.set(id, renderer);
|
|
8
|
+
return id;
|
|
9
|
+
};
|
|
10
|
+
} else window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
|
|
11
|
+
renderers: new Map(),
|
|
12
|
+
supportsFiber: true,
|
|
13
|
+
inject (renderer) {
|
|
14
|
+
const id = this.renderers.size + 1;
|
|
15
|
+
this.renderers.set(id, renderer);
|
|
16
|
+
return id;
|
|
17
|
+
},
|
|
18
|
+
onCommitFiberRoot () {},
|
|
19
|
+
onCommitFiberUnmount () {}
|
|
20
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ServerLogSSEClient } from "../server-log/index.js";
|
|
2
|
+
let client = null;
|
|
3
|
+
function initServerLog() {
|
|
4
|
+
if (window.parent === window) return;
|
|
5
|
+
try {
|
|
6
|
+
const backendUrl = window.location.origin;
|
|
7
|
+
client = new ServerLogSSEClient({
|
|
8
|
+
serverUrl: backendUrl,
|
|
9
|
+
sseEndpoint: '/dev/logs/server-logs/stream',
|
|
10
|
+
debug: true
|
|
11
|
+
});
|
|
12
|
+
client.start();
|
|
13
|
+
console.log('[Runtime] Server log SSE client started');
|
|
14
|
+
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
15
|
+
window.addEventListener('beforeunload', cleanup);
|
|
16
|
+
window.addEventListener('unload', cleanup);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error('[Runtime] Failed to start server log SSE client:', error);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function handleVisibilityChange() {
|
|
22
|
+
if (!client) return;
|
|
23
|
+
if (document.hidden) {
|
|
24
|
+
client.pause();
|
|
25
|
+
console.log('[Runtime] Tab hidden, SSE paused');
|
|
26
|
+
} else {
|
|
27
|
+
client.resume();
|
|
28
|
+
console.log('[Runtime] Tab visible, SSE resumed');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function cleanup() {
|
|
32
|
+
if (client) {
|
|
33
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
34
|
+
window.removeEventListener('beforeunload', cleanup);
|
|
35
|
+
window.removeEventListener('unload', cleanup);
|
|
36
|
+
client.stop();
|
|
37
|
+
client = null;
|
|
38
|
+
console.log('[Runtime] Server log SSE client stopped');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export { initServerLog };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "../index.css";
|
package/lib/theme-layer.css
CHANGED
package/lib/utils/axiosConfig.js
CHANGED
|
@@ -54,7 +54,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
54
54
|
logTraceID
|
|
55
55
|
};
|
|
56
56
|
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
57
|
-
logger.
|
|
57
|
+
logger.log({
|
|
58
58
|
level: ok,
|
|
59
59
|
args: [
|
|
60
60
|
parts.join(''),
|
|
@@ -110,7 +110,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
110
110
|
const stacktrace = await requestStacktraceMap.get(requestUUID);
|
|
111
111
|
const logMeta = {};
|
|
112
112
|
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
113
|
-
logger.
|
|
113
|
+
logger.log({
|
|
114
114
|
level: 'error',
|
|
115
115
|
args: [
|
|
116
116
|
parts.join(''),
|
|
@@ -120,7 +120,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
120
120
|
});
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
|
-
logger.
|
|
123
|
+
logger.log({
|
|
124
124
|
level: 'error',
|
|
125
125
|
args: [
|
|
126
126
|
'请求失败:无响应对象或配置信息'
|
|
@@ -234,8 +234,30 @@ function initAxiosConfig(axiosInstance) {
|
|
|
234
234
|
config._startTime = config._startTime || Date.now();
|
|
235
235
|
const csrfToken = window.csrfToken;
|
|
236
236
|
if (csrfToken) config.headers['X-Suda-Csrf-Token'] = csrfToken;
|
|
237
|
+
if ('undefined' != typeof window && window.location?.pathname) config.headers['X-Page-Route'] = window.location.pathname;
|
|
237
238
|
return config;
|
|
238
239
|
}, (error)=>Promise.reject(error));
|
|
240
|
+
instance.interceptors.response.use((response)=>response, (error)=>{
|
|
241
|
+
try {
|
|
242
|
+
if (error.response?.status === 403) {
|
|
243
|
+
const method = (error.config?.method || 'GET').toUpperCase();
|
|
244
|
+
const url = (error.config?.url || '').split('?')[0];
|
|
245
|
+
logger.log({
|
|
246
|
+
level: 'warn',
|
|
247
|
+
args: [
|
|
248
|
+
`请求被拒绝(403):${method} ${url}`,
|
|
249
|
+
{
|
|
250
|
+
状态码: 403,
|
|
251
|
+
返回数据: error.response.data
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
meta: {}
|
|
255
|
+
});
|
|
256
|
+
return error.response;
|
|
257
|
+
}
|
|
258
|
+
} catch (e) {}
|
|
259
|
+
return Promise.reject(error);
|
|
260
|
+
});
|
|
239
261
|
'production' !== process.env.NODE_ENV && instance.interceptors.response.use((response)=>{
|
|
240
262
|
logResponse('success', response);
|
|
241
263
|
return response;
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
function getEnv() {
|
|
2
|
+
switch(globalThis.ENVIRONMENT){
|
|
3
|
+
case 'staging':
|
|
4
|
+
return 'BOE';
|
|
5
|
+
case 'gray':
|
|
6
|
+
return 'PRE';
|
|
7
|
+
case 'online':
|
|
8
|
+
return 'ONLINE';
|
|
9
|
+
default:
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
2
12
|
const { origin } = window.location;
|
|
3
|
-
if (origin.includes('feishuapp.cn') || origin.includes('miaoda.feishuapp.net')) return 'ONLINE';
|
|
4
|
-
if (origin.includes('fsapp.kundou.cn') || origin.includes('miaoda-pre.feishuapp.net')) return 'PRE';
|
|
13
|
+
if (origin.includes('feishuapp.cn') || origin.includes('miaoda.feishuapp.net') || origin.includes('aiforce.cloud') || origin.includes('aiforce.run')) return 'ONLINE';
|
|
14
|
+
if (origin.includes('fsapp.kundou.cn') || origin.includes('miaoda-pre.feishuapp.net') || origin.includes('aiforce-pre.bytedance.net') || origin.includes('aiforce-pre-preview.bytedance.net') || origin.includes('aiforce-pre.cloud') || origin.includes('aiforce-pre.run')) return 'PRE';
|
|
5
15
|
return 'BOE';
|
|
6
16
|
}
|
|
7
17
|
export { getEnv };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一 HMR API
|
|
3
|
+
*
|
|
4
|
+
* 提供统一的 HMR 成功/失败回调接口,屏蔽 Webpack 和 Vite 的差异。
|
|
5
|
+
*
|
|
6
|
+
* - Webpack/Rspack: 通过 import.meta.webpackHot 或 module.hot
|
|
7
|
+
* - Vite: 通过 error-overlay 注入的 window.__VITE_HMR__
|
|
8
|
+
*
|
|
9
|
+
* @see docs/RFC_HMR_API.md
|
|
10
|
+
*/
|
|
11
|
+
export interface HmrApi {
|
|
12
|
+
/**
|
|
13
|
+
* 注册 HMR 成功回调
|
|
14
|
+
* @param callback 成功回调函数
|
|
15
|
+
* @returns cleanup 函数,用于取消注册
|
|
16
|
+
*/
|
|
17
|
+
onSuccess(callback: () => void): () => void;
|
|
18
|
+
/**
|
|
19
|
+
* 注册 HMR 失败回调
|
|
20
|
+
* @param callback 失败回调函数,参数为错误信息
|
|
21
|
+
* @returns cleanup 函数,用于取消注册
|
|
22
|
+
*/
|
|
23
|
+
onError(callback: (error: unknown) => void): () => void;
|
|
24
|
+
}
|
|
25
|
+
declare global {
|
|
26
|
+
interface Window {
|
|
27
|
+
__VITE_HMR__?: HmrApi;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 获取 HMR API 实例
|
|
32
|
+
*
|
|
33
|
+
* 自动检测当前构建工具(Webpack/Vite)并返回对应实现:
|
|
34
|
+
* - Webpack/Rspack: 使用内置适配器
|
|
35
|
+
* - Vite: 使用 error-overlay 注入的 window.__VITE_HMR__
|
|
36
|
+
*
|
|
37
|
+
* @returns HmrApi 实例,如果不在开发环境或不支持 HMR 则返回 null
|
|
38
|
+
*/
|
|
39
|
+
export declare function getHmrApi(): HmrApi | null;
|