@lark-apaas/coding-templates 0.1.43-alpha.5 → 0.1.43-alpha.7

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-templates",
3
- "version": "0.1.43-alpha.5",
3
+ "version": "0.1.43-alpha.7",
4
4
  "description": "OpenClaw project templates for mclaw CLI",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -0,0 +1,8 @@
1
+ {
2
+ "appId": "app_xxxxxxxxxxxxxx",
3
+ "template": "vite-react",
4
+ "version": "0.1.0",
5
+ "archType": 2,
6
+ "features": ["client"],
7
+ "appUrl": "https://bytedance.aiforce.cloud/app/app_xxxxxxxxxxxxxx"
8
+ }
@@ -10,7 +10,7 @@
10
10
  ]
11
11
  },
12
12
  "scripts": {
13
- "dev": "concurrently -k -n vite,health 'vite --port 8001 --host 0.0.0.0' 'node scripts/mock-health.cjs'",
13
+ "dev": "node scripts/dev.cjs",
14
14
  "build": "bash scripts/build.sh",
15
15
  "typecheck": "tsc -p tsconfig.app.json",
16
16
  "lint": "npm run typecheck && npm run lint:eslint",
@@ -44,7 +44,7 @@
44
44
  "@radix-ui/react-toggle": "^1.1.9",
45
45
  "@radix-ui/react-toggle-group": "^1.1.10",
46
46
  "@radix-ui/react-tooltip": "^1.1.18",
47
- "@lark-apaas/client-toolkit-lite": "1.1.7-alpha.7",
47
+ "@lark-apaas/client-toolkit-lite": "1.1.7-alpha.9",
48
48
  "@formkit/auto-animate": "^0.9.0",
49
49
  "@gsap/react": "^2.1.2",
50
50
  "framer-motion": "^12.38.0",
@@ -62,6 +62,7 @@
62
62
  "react": "^19.2.4",
63
63
  "react-day-picker": "^9.14.0",
64
64
  "react-dom": "^19.2.4",
65
+ "react-error-boundary": "^6.0.0",
65
66
  "react-hook-form": "^7.72.0",
66
67
  "react-resizable-panels": "^4.7.6",
67
68
  "react-router-dom": "^7.13.2",
@@ -79,7 +80,7 @@
79
80
  "@types/react": "^19",
80
81
  "@types/react-dom": "^19",
81
82
  "@lark-apaas/coding-presets": "^1.0.0",
82
- "@lark-apaas/coding-vite-preset": "1.0.7-alpha.3",
83
+ "@lark-apaas/coding-vite-preset": "1.0.7-alpha.5",
83
84
  "concurrently": "^9",
84
85
  "eslint": "^9",
85
86
  "eslint-plugin-react-hooks": "^7",
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * jsPage 模板 dev launcher。
4
+ *
5
+ * 跟全栈 dev.js 对齐:每个子进程的 stdout/stderr 经 readline 逐行拼上
6
+ * 时间戳 + [name] 前缀,同时写到 logs/<name>.std.log(沙箱外壳 dev-logs
7
+ * middleware 监听的标准路径)和当前 stdout。
8
+ *
9
+ * jsPage 只需要 client(vite) + health 两个进程,没有 server。
10
+ * 端口约定(保持跟 .spark_project healthCheck 一致):
11
+ * - vite → 8001(CLIENT_DEV_PORT 可覆盖)
12
+ * - mock-health → 3000(占位,老沙箱探针兼容用)
13
+ *
14
+ * Ctrl+C / SIGTERM 时 kill 整个进程组。
15
+ */
16
+ 'use strict';
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const readline = require('readline');
21
+ const { spawn } = require('child_process');
22
+
23
+ const ROOT = path.resolve(__dirname, '..');
24
+ process.chdir(ROOT);
25
+
26
+ const LOG_DIR = process.env.LOG_DIR || 'logs';
27
+ const CLIENT_DEV_PORT = process.env.CLIENT_DEV_PORT || '8001';
28
+
29
+ fs.mkdirSync(LOG_DIR, { recursive: true });
30
+
31
+ function timestamp() {
32
+ const now = new Date();
33
+ const pad = (n) => String(n).padStart(2, '0');
34
+ return (
35
+ `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ` +
36
+ `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
37
+ );
38
+ }
39
+
40
+ const managed = [];
41
+
42
+ function startProcess({ name, command, args, logFileName }) {
43
+ const logFd = logFileName
44
+ ? fs.openSync(path.join(LOG_DIR, logFileName), 'a')
45
+ : null;
46
+
47
+ const child = spawn(command, args, {
48
+ stdio: ['ignore', 'pipe', 'pipe'],
49
+ shell: false,
50
+ cwd: ROOT,
51
+ env: process.env,
52
+ detached: true,
53
+ });
54
+
55
+ const pipeLines = (stream) => {
56
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
57
+ rl.on('line', (line) => {
58
+ const msg = `[${timestamp()}] [${name}] ${line}\n`;
59
+ try { process.stdout.write(msg); } catch {}
60
+ if (logFd != null) {
61
+ try { fs.writeSync(logFd, msg); } catch {}
62
+ }
63
+ });
64
+ };
65
+ pipeLines(child.stdout);
66
+ pipeLines(child.stderr);
67
+
68
+ managed.push({ name, child });
69
+ return child;
70
+ }
71
+
72
+ startProcess({
73
+ name: 'client',
74
+ command: 'npx',
75
+ args: ['vite', '--port', CLIENT_DEV_PORT, '--host', '0.0.0.0'],
76
+ logFileName: 'client.std.log',
77
+ });
78
+
79
+ startProcess({
80
+ name: 'health',
81
+ command: 'node',
82
+ args: ['scripts/mock-health.cjs'],
83
+ // health 进程不单独写 log,透传到 stdout 就够
84
+ });
85
+
86
+ let stopping = false;
87
+ function cleanup(signal) {
88
+ if (stopping) return;
89
+ stopping = true;
90
+ for (const { child } of managed) {
91
+ if (!child.pid) continue;
92
+ try { process.kill(-child.pid, signal || 'SIGTERM'); } catch {}
93
+ }
94
+ setTimeout(() => {
95
+ for (const { child } of managed) {
96
+ if (!child.pid) continue;
97
+ try { process.kill(-child.pid, 'SIGKILL'); } catch {}
98
+ }
99
+ process.exit(0);
100
+ }, 2000);
101
+ }
102
+
103
+ process.on('SIGINT', () => cleanup('SIGTERM'));
104
+ process.on('SIGTERM', () => cleanup('SIGTERM'));
105
+
106
+ // 任意子进程退出就触发整体 cleanup,避免半残留
107
+ Promise.race(
108
+ managed.map(({ child }) => new Promise((r) => child.on('exit', r)))
109
+ ).then(() => cleanup('SIGTERM'));
@@ -1,7 +1,8 @@
1
1
  import { StrictMode } from "react";
2
2
  import { createRoot } from "react-dom/client";
3
3
  import { BrowserRouter } from "react-router-dom";
4
- import { AppContainer } from "@lark-apaas/client-toolkit-lite";
4
+ import { ErrorBoundary } from "react-error-boundary";
5
+ import { AppContainer, ErrorRender } from "@lark-apaas/client-toolkit-lite";
5
6
  import App from "./app";
6
7
  import "./index.css";
7
8
 
@@ -9,7 +10,13 @@ createRoot(document.getElementById("root")!).render(
9
10
  <StrictMode>
10
11
  <BrowserRouter basename={process.env.CLIENT_BASE_PATH || "/"}>
11
12
  <AppContainer>
12
- <App />
13
+ <ErrorBoundary
14
+ fallbackRender={({ error, resetErrorBoundary }) => (
15
+ <ErrorRender error={error} resetErrorBoundary={resetErrorBoundary} />
16
+ )}
17
+ >
18
+ <App />
19
+ </ErrorBoundary>
13
20
  </AppContainer>
14
21
  </BrowserRouter>
15
22
  </StrictMode>,