@lark-apaas/client-toolkit 1.2.7 → 1.2.8-alpha.1

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.
@@ -1,3 +1,2 @@
1
1
  import React from 'react';
2
- import './utils/listenHot';
3
2
  export default function IframeBridge(): React.JSX.Element;
@@ -1,12 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef } from "react";
3
3
  import { useLocation, useNavigate } from "react-router-dom";
4
- import { connectToParent } from "penpal";
5
4
  import { useUpdatingRef } from "../../hooks/useUpdatingRef.js";
6
- import { resolveParentOrigin, submitPostMessage } from "../../utils/postMessage.js";
7
- import { childApi } from "./utils/childApi.js";
8
- import { batchLogInfo } from "../../logger/batch-logger.js";
9
- import "./utils/listenHot.js";
5
+ import { submitPostMessage } from "../../utils/postMessage.js";
10
6
  var IframeBridge_RouteMessageType = /*#__PURE__*/ function(RouteMessageType) {
11
7
  RouteMessageType["RouteChange"] = "RouteChange";
12
8
  RouteMessageType["RouteBack"] = "RouteBack";
@@ -16,27 +12,6 @@ var IframeBridge_RouteMessageType = /*#__PURE__*/ function(RouteMessageType) {
16
12
  function isRouteMessageType(type) {
17
13
  return Object.values(IframeBridge_RouteMessageType).includes(type);
18
14
  }
19
- async function connectParent() {
20
- submitPostMessage({
21
- type: 'PreviewReady',
22
- data: {}
23
- });
24
- batchLogInfo('info', JSON.stringify({
25
- type: 'PreviewReady',
26
- timestamp: Date.now(),
27
- url: window.location.href
28
- }));
29
- const parentOrigin = resolveParentOrigin();
30
- if (!parentOrigin) return;
31
- const connection = connectToParent({
32
- parentOrigin,
33
- methods: {
34
- ...childApi
35
- }
36
- });
37
- await connection.promise;
38
- }
39
- 'production' !== process.env.NODE_ENV && connectParent();
40
15
  function IframeBridge() {
41
16
  const location = useLocation();
42
17
  const navigate = useNavigate();
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { IBaseThemeProviderProps } from '../theme';
3
- import '../../index.css';
3
+ import '../../runtime';
4
4
  interface IBaseAuthProviderProps {
5
5
  enableAuth?: boolean;
6
6
  }
@@ -1,5 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from "react";
2
+ import { useEffect, useState } from "react";
3
3
  import { ConfigProvider } from "antd";
4
4
  import { MiaodaInspector } from "@lark-apaas/miaoda-inspector";
5
5
  import zh_CN from "antd/locale/zh_CN";
@@ -8,21 +8,14 @@ import { defaultUIConfig } from "../theme/ui-config.js";
8
8
  import { Toaster } from "./sonner.js";
9
9
  import { PageHoc } from "./PageHoc.js";
10
10
  import { findValueByPixel, generateTailwindRadiusToken, themeColorTokenMap, themeMetaOptions } from "../theme/index.js";
11
- import { registerDayjsPlugins } from "./dayjsPlugins.js";
12
- import "../../index.css";
13
- import { initAxiosConfig } from "../../utils/axiosConfig.js";
14
11
  import { reportTeaEvent } from "./utils/tea.js";
15
12
  import { useAppInfo } from "../../hooks/index.js";
16
13
  import { TrackKey } from "../../types/tea.js";
17
14
  import safety from "./safety.js";
18
15
  import { getAppId } from "../../utils/getAppId.js";
19
- import { ServerLogSSEClient } from "../../server-log/index.js";
20
16
  import QueryProvider from "../QueryProvider/index.js";
21
- import { initObservable } from "./utils/observable.js";
22
17
  import { AuthProvider } from "@lark-apaas/auth-sdk";
23
- registerDayjsPlugins();
24
- initAxiosConfig();
25
- initObservable();
18
+ import "../../runtime/index.js";
26
19
  const isMiaodaPreview = window.IS_MIAODA_PREVIEW;
27
20
  const readCssVarColor = (varName, fallback)=>{
28
21
  try {
@@ -36,7 +29,6 @@ const readCssVarColor = (varName, fallback)=>{
36
29
  const App = (props)=>{
37
30
  const { themeMeta = {}, enableAuth } = props;
38
31
  useAppInfo();
39
- const serverLogClientRef = useRef(null);
40
32
  const { rem } = findValueByPixel(themeMetaOptions.themeRadius, themeMeta.borderRadius) || {
41
33
  rem: '0.625'
42
34
  };
@@ -48,40 +40,6 @@ const App = (props)=>{
48
40
  borderRadius: radiusToken
49
41
  }
50
42
  };
51
- useEffect(()=>{
52
- if ('production' !== process.env.NODE_ENV && window.parent !== window) {
53
- try {
54
- const backendUrl = window.location.origin;
55
- serverLogClientRef.current = new ServerLogSSEClient({
56
- serverUrl: backendUrl,
57
- sseEndpoint: '/dev/logs/server-logs/stream',
58
- debug: true
59
- });
60
- serverLogClientRef.current.start();
61
- console.log('[AppContainer] Server log SSE client started');
62
- } catch (error) {
63
- console.error('[AppContainer] Failed to start server log SSE client:', error);
64
- }
65
- const handleVisibilityChange = ()=>{
66
- if (!serverLogClientRef.current) return;
67
- if (document.hidden) {
68
- serverLogClientRef.current.pause();
69
- console.log('[AppContainer] Tab hidden, SSE paused');
70
- } else {
71
- serverLogClientRef.current.resume();
72
- console.log('[AppContainer] Tab visible, SSE resumed');
73
- }
74
- };
75
- document.addEventListener('visibilitychange', handleVisibilityChange);
76
- return ()=>{
77
- document.removeEventListener('visibilitychange', handleVisibilityChange);
78
- if (serverLogClientRef.current) {
79
- serverLogClientRef.current.stop();
80
- console.log('[AppContainer] Server log SSE client stopped');
81
- }
82
- };
83
- }
84
- }, []);
85
43
  useEffect(()=>{
86
44
  if (isMiaodaPreview) fetch(`${location.origin}/ai/api/feida_preview/csrf`).then(()=>{
87
45
  setTimeout(()=>{
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Axios 配置初始化
3
+ * 从原有的 axiosConfig.ts 迁移
4
+ */
5
+ export { initAxiosConfig } from '../utils/axiosConfig';
@@ -0,0 +1,2 @@
1
+ import { initAxiosConfig } from "../utils/axiosConfig.js";
2
+ export { initAxiosConfig };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Dayjs 插件注册
3
+ * 从原有的 dayjsPlugins.ts 迁移
4
+ */
5
+ export { registerDayjsPlugins } from '../components/AppContainer/dayjsPlugins';
@@ -0,0 +1,2 @@
1
+ import { registerDayjsPlugins } from "../components/AppContainer/dayjsPlugins.js";
2
+ export { registerDayjsPlugins };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Iframe Bridge Runtime
3
+ *
4
+ * 开发环境下的 iframe 通信初始化:
5
+ * - connectParent - 通过 penpal 连接父页面,建立双向通信
6
+ */
7
+ /**
8
+ * 初始化 iframe bridge(仅开发环境)
9
+ * - 连接父页面
10
+ */
11
+ export declare function initIframeBridge(): void;
@@ -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,23 @@
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 './styles';
19
+ declare global {
20
+ interface Window {
21
+ __FULLSTACK_RUNTIME_INITIALIZED__?: boolean;
22
+ }
23
+ }
@@ -0,0 +1,16 @@
1
+ import "./styles.js";
2
+ import { registerDayjsPlugins } from "./dayjs.js";
3
+ import { initAxiosConfig } from "./axios.js";
4
+ import { initObservable } from "./observable.js";
5
+ import { initServerLog } from "./server-log.js";
6
+ import { initIframeBridge } from "./iframe-bridge.js";
7
+ if (!window.__FULLSTACK_RUNTIME_INITIALIZED__) {
8
+ window.__FULLSTACK_RUNTIME_INITIALIZED__ = true;
9
+ registerDayjsPlugins();
10
+ initAxiosConfig();
11
+ initObservable();
12
+ if ('production' !== process.env.NODE_ENV) {
13
+ initServerLog();
14
+ initIframeBridge();
15
+ }
16
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 可观测初始化
3
+ * 从原有的 observable.ts 迁移
4
+ */
5
+ export { initObservable } from '../components/AppContainer/utils/observable';
@@ -0,0 +1,2 @@
1
+ import { initObservable } from "../components/AppContainer/utils/observable.js";
2
+ export { initObservable };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 初始化 Server Log SSE 客户端
3
+ * 仅在开发环境且在 iframe 中时启用
4
+ */
5
+ export declare function initServerLog(): void;
@@ -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,5 @@
1
+ /**
2
+ * 全局样式导入
3
+ * 在 runtime 中最先执行,确保样式优先加载
4
+ */
5
+ import '../index.css';
@@ -0,0 +1 @@
1
+ import "../index.css";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/client-toolkit",
3
- "version": "1.2.7",
3
+ "version": "1.2.8-alpha.1",
4
4
  "types": "./lib/index.d.ts",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -15,6 +15,11 @@
15
15
  "require": "./lib/index.js",
16
16
  "types": "./lib/index.d.ts"
17
17
  },
18
+ "./runtime": {
19
+ "import": "./lib/runtime/index.js",
20
+ "require": "./lib/runtime/index.js",
21
+ "types": "./lib/runtime/index.d.ts"
22
+ },
18
23
  "./antd-table": {
19
24
  "import": "./lib/antd-table.js",
20
25
  "require": "./lib/antd-table.js",
@@ -110,7 +115,6 @@
110
115
  "lodash": "^4.17.21",
111
116
  "network-idle": "^0.2.0",
112
117
  "penpal": "^6.2.2",
113
- "sockjs-client": "^1.6.1",
114
118
  "sonner": "~2.0.0",
115
119
  "source-map": "^0.7.6",
116
120
  "stacktrace-js": "^2.0.2",
@@ -143,7 +147,6 @@
143
147
  "@types/node": "^22.10.2",
144
148
  "@types/react": "^18.3.23",
145
149
  "@types/react-dom": "^18.3.7",
146
- "@types/sockjs-client": "^1",
147
150
  "antd": "^5.26.6",
148
151
  "eslint": "^8.57.0",
149
152
  "jsdom": "^26.1.0",
@@ -1 +0,0 @@
1
- export declare function connectDevServer(): WebSocket;
@@ -1,79 +0,0 @@
1
- import sockjs_client from "sockjs-client";
2
- import { submitPostMessage, submitSlardarEvent } from "../../../utils/postMessage.js";
3
- import { batchLogInfo } from "../../../logger/batch-logger.js";
4
- import { getWsPath } from "../../../utils/utils.js";
5
- let hotInited = false;
6
- function handleDevServerMessage(msg) {
7
- if ('hash' === msg.type) {
8
- if (!hotInited) {
9
- hotInited = true;
10
- return;
11
- }
12
- submitPostMessage({
13
- type: 'HmrMessage',
14
- msg: {
15
- type: 'hot'
16
- },
17
- data: null
18
- });
19
- batchLogInfo('info', JSON.stringify({
20
- type: 'HmrMessage',
21
- subType: 'hot',
22
- timestamp: Date.now(),
23
- hash: msg.data
24
- }));
25
- } else if ('errors' === msg.type) {
26
- submitPostMessage({
27
- type: 'HmrMessage',
28
- msg: {
29
- type: 'errors',
30
- data: JSON.stringify(msg.data)
31
- },
32
- data: null
33
- });
34
- batchLogInfo('info', JSON.stringify({
35
- type: 'HmrMessage',
36
- subType: 'errors',
37
- timestamp: Date.now(),
38
- errorCount: msg.data?.length
39
- }));
40
- } else if ('hmr-timing' === msg.type) {
41
- const { duration, fileCount, fileTotalSize } = msg.data;
42
- submitSlardarEvent({
43
- name: 'runTiming',
44
- metrics: {
45
- duration
46
- },
47
- categories: {
48
- type: 'sandbox-hmr-timing',
49
- fileCount,
50
- fileTotalSize
51
- }
52
- });
53
- batchLogInfo('info', JSON.stringify({
54
- type: 'HmrMessage',
55
- subType: 'hmr-timing',
56
- timestamp: Date.now(),
57
- duration,
58
- fileCount,
59
- fileTotalSize
60
- }));
61
- }
62
- }
63
- function connectDevServer() {
64
- const sockUrl = getWsPath();
65
- const sock = new sockjs_client(sockUrl);
66
- sock.onopen = ()=>console.log('✅ connect DevServer SockJS');
67
- sock.onmessage = (event)=>{
68
- try {
69
- const msg = JSON.parse(event.data);
70
- console.log('hmr 消息:', msg);
71
- handleDevServerMessage(msg);
72
- } catch (err) {
73
- console.error('解析 hmr 消息失败:', event.data);
74
- }
75
- };
76
- return sock;
77
- }
78
- 'production' !== process.env.NODE_ENV && connectDevServer();
79
- export { connectDevServer };