@lark-apaas/coding-templates 0.1.43-alpha.0 → 0.1.43-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/package.json +1 -1
- package/template-apex/README.md +1 -1
- package/template-vite-react/.spark/meta.json.example +8 -0
- package/template-vite-react/.spark-project +18 -0
- package/template-vite-react/client/src/hooks/use-mobile.ts +4 -3
- package/template-vite-react/package.json +1 -0
- package/template-vite-react/scripts/mock-health.cjs +32 -0
- package/template-vite-react/vite.config.ts +52 -0
- package/template-apex/client/src/lib/utils.ts +0 -6
- package/template-vite-react/client/src/lib/utils.ts +0 -6
package/package.json
CHANGED
package/template-apex/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
- UI 组件: shadcn/ui `import { Button } from "@/components/ui/button";`
|
|
10
10
|
- 图标: lucide-react `import { SearchIcon } from "lucide-react";`
|
|
11
11
|
- 图表: echarts-for-react `import ReactECharts from "echarts-for-react";`
|
|
12
|
-
- 动画:
|
|
12
|
+
- 动画: framer-motion `import { motion } from "framer-motion";`
|
|
13
13
|
- 路由: react-router-dom `import { Link, useNavigate } from "react-router-dom";`
|
|
14
14
|
- 校验: zod `import { z } from "zod";`
|
|
15
15
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
run = ["npm", "run", "dev"]
|
|
2
|
+
lint = ["npm", "run", "lint"]
|
|
3
|
+
hidden = [".config", ".git", "scripts", "node_modules", "dist", ".spark", ".agent", ".agents", "tmp", ".spark_project", ".playwright-cli"]
|
|
4
|
+
|
|
5
|
+
[deployment]
|
|
6
|
+
build = ["npm", "run", "build"]
|
|
7
|
+
|
|
8
|
+
[files]
|
|
9
|
+
[files.restrict]
|
|
10
|
+
pathPatterns = ["package.json", ".spark-project", ".spark/meta.json", ".gitignore"]
|
|
11
|
+
[files.hidden]
|
|
12
|
+
pathPatterns = [".config", ".git", "scripts", "node_modules", "dist", ".spark", ".agent", ".agents", "tmp", ".spark_project", ".playwright-cli"]
|
|
13
|
+
|
|
14
|
+
[sandbox]
|
|
15
|
+
# 临时兼容老沙箱硬编码探测的 3000 / 8001 端口。
|
|
16
|
+
# 这两个端口由 scripts/mock-health.cjs 占位,Vite dev server 实际监听 CLIENT_DEV_PORT(默认 8080)。
|
|
17
|
+
# 沙箱链路切到新协议后,可改回 [8080],并删掉 mock-health.cjs。
|
|
18
|
+
healthCheck = [8001, 3000]
|
|
@@ -3,7 +3,9 @@ import * as React from "react"
|
|
|
3
3
|
const MOBILE_BREAKPOINT = 768
|
|
4
4
|
|
|
5
5
|
export function useIsMobile() {
|
|
6
|
-
const [isMobile, setIsMobile] = React.useState<boolean
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean>(() =>
|
|
7
|
+
typeof window !== "undefined" && window.innerWidth < MOBILE_BREAKPOINT,
|
|
8
|
+
)
|
|
7
9
|
|
|
8
10
|
React.useEffect(() => {
|
|
9
11
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
@@ -11,9 +13,8 @@ export function useIsMobile() {
|
|
|
11
13
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
12
14
|
}
|
|
13
15
|
mql.addEventListener("change", onChange)
|
|
14
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
15
16
|
return () => mql.removeEventListener("change", onChange)
|
|
16
17
|
}, [])
|
|
17
18
|
|
|
18
|
-
return
|
|
19
|
+
return isMobile
|
|
19
20
|
}
|
|
@@ -10,6 +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
14
|
"build": "bash scripts/build.sh",
|
|
14
15
|
"typecheck": "tsc -p tsconfig.app.json",
|
|
15
16
|
"lint": "concurrently npm:typecheck npm:lint:eslint",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 沙箱预览态健康检查兜底:在 3000 端口起 HTTP listener。
|
|
4
|
+
*
|
|
5
|
+
* 老沙箱硬编码探测 3000 + 8001 判定"应用启动了"。jsPage 没有真实 Node server,
|
|
6
|
+
* 8001 由 Vite dev server 真正占(预览流量也走 8001),3000 没有任何业务进程,
|
|
7
|
+
* 只能 mock 一个 listener 让健康检查过。
|
|
8
|
+
*
|
|
9
|
+
* 等沙箱链路切到新协议(读 .spark-project [sandbox].healthCheck)后可删除。
|
|
10
|
+
*/
|
|
11
|
+
const http = require('node:http');
|
|
12
|
+
|
|
13
|
+
const PORTS = [3000];
|
|
14
|
+
|
|
15
|
+
for (const port of PORTS) {
|
|
16
|
+
const server = http.createServer((_req, res) => {
|
|
17
|
+
res.writeHead(200, { 'content-type': 'text/plain' });
|
|
18
|
+
res.end('ok');
|
|
19
|
+
});
|
|
20
|
+
server.on('error', (err) => {
|
|
21
|
+
console.error(`[mock-health] :${port} listen error:`, err.message);
|
|
22
|
+
if (err.code === 'EADDRINUSE') {
|
|
23
|
+
// 端口已被占说明业务已起来,mock 退场即可
|
|
24
|
+
console.warn(`[mock-health] :${port} 已被占用,跳过 mock`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
process.exitCode = 1;
|
|
28
|
+
});
|
|
29
|
+
server.listen(port, '0.0.0.0', () => {
|
|
30
|
+
console.log(`[mock-health] listening on :${port}`);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from 'http'
|
|
2
3
|
import { defineConfig } from '@lark-apaas/coding-vite-preset'
|
|
4
|
+
import type { Plugin, ViteDevServer } from 'vite'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* dev 模式 base-path normalize 中间件
|
|
8
|
+
*
|
|
9
|
+
* 沙箱预览网关把流量原样转给 vite(保留 /app/:appId 前缀)。浏览器首次访问的
|
|
10
|
+
* URL 形如 `/app/app_xxx?sso_token=...`,pathname 缺末尾 /。
|
|
11
|
+
*
|
|
12
|
+
* vite 8 的 baseMiddleware 对"缺末尾 /"的请求不再像 vite 5 那样自动 301,
|
|
13
|
+
* 而是直接返回 404 警告页 "The server is configured with a public base URL..."。
|
|
14
|
+
*
|
|
15
|
+
* 这里做 internal rewrite(不发 301,避免跟沙箱网关形成 round-trip 死循环):
|
|
16
|
+
* 在 vite 内置 baseMiddleware **之前** unshift 一个中间件,把 req.url 改写
|
|
17
|
+
* 成带尾 /,下游 baseMiddleware 继续 strip base → SPA fallback。
|
|
18
|
+
* 浏览器全程不感知 redirect,地址栏可保留缺尾 / 形态(BrowserRouter basename
|
|
19
|
+
* 处理路由)。
|
|
20
|
+
*
|
|
21
|
+
* 必须 stack.unshift 而非 server.middlewares.use(...),否则会排到内置
|
|
22
|
+
* baseMiddleware 之后失效。
|
|
23
|
+
*
|
|
24
|
+
* TODO: 这段已同步到 @lark-apaas/coding-vite-preset,待该包发布并被本模板
|
|
25
|
+
* 依赖升级拉到后,可以删除此 plugin。保留是为了让现存沙箱(用着老 preset
|
|
26
|
+
* 的应用)也能立即生效。
|
|
27
|
+
*/
|
|
28
|
+
const baseNormalizePlugin: Plugin = {
|
|
29
|
+
name: 'base-path-normalize',
|
|
30
|
+
configureServer(server: ViteDevServer) {
|
|
31
|
+
const base = (process.env.CLIENT_BASE_PATH || '').replace(/\/+$/, '')
|
|
32
|
+
if (!base) return
|
|
33
|
+
const stack = (
|
|
34
|
+
server.middlewares as unknown as {
|
|
35
|
+
stack: Array<{ route: string; handle: unknown }>
|
|
36
|
+
}
|
|
37
|
+
).stack
|
|
38
|
+
if (!Array.isArray(stack)) return
|
|
39
|
+
stack.unshift({
|
|
40
|
+
route: '',
|
|
41
|
+
handle: (req: IncomingMessage, _res: ServerResponse, next: () => void) => {
|
|
42
|
+
const url = req.url || ''
|
|
43
|
+
const qIdx = url.indexOf('?')
|
|
44
|
+
const pathname = qIdx >= 0 ? url.slice(0, qIdx) : url
|
|
45
|
+
const search = qIdx >= 0 ? url.slice(qIdx) : ''
|
|
46
|
+
if (pathname === base) {
|
|
47
|
+
req.url = base + '/' + search
|
|
48
|
+
}
|
|
49
|
+
next()
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
},
|
|
53
|
+
}
|
|
3
54
|
|
|
4
55
|
export default defineConfig({
|
|
5
56
|
root: path.resolve(__dirname, 'client'),
|
|
@@ -9,4 +60,5 @@ export default defineConfig({
|
|
|
9
60
|
'@shared': path.resolve(__dirname, 'shared'),
|
|
10
61
|
},
|
|
11
62
|
},
|
|
63
|
+
plugins: [baseNormalizePlugin],
|
|
12
64
|
})
|