@coze-arch/cli 0.0.1-alpha.db1c06 → 0.0.1-alpha.dcc485
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/README.md +1 -0
- package/lib/__templates__/expo/_npmrc +1 -0
- package/lib/__templates__/expo/client/components/Screen.tsx +2 -2
- package/lib/__templates__/expo/client/eslint.config.mjs +7 -0
- package/lib/__templates__/expo/client/scripts/install-missing-deps.js +10 -10
- package/lib/__templates__/expo/eslint-plugins/forbid-emoji/index.js +9 -0
- package/lib/__templates__/expo/eslint-plugins/forbid-emoji/rule.js +112 -0
- package/lib/__templates__/expo/eslint-plugins/forbid-emoji/tech.md +94 -0
- package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/index.js +9 -0
- package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/rule.js +120 -0
- package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/tech.md +58 -0
- package/lib/__templates__/nextjs/AGENTS.md +54 -0
- package/lib/__templates__/nextjs/README.md +5 -0
- package/lib/__templates__/nextjs/eslint.config.mjs +5 -0
- package/lib/__templates__/nextjs/next.config.ts +1 -2
- package/lib/__templates__/nextjs/package.json +2 -5
- package/lib/__templates__/nextjs/pnpm-lock.yaml +1028 -5
- package/lib/__templates__/nextjs/scripts/build.sh +4 -1
- package/lib/__templates__/nextjs/scripts/dev.sh +8 -2
- package/lib/__templates__/nextjs/scripts/start.sh +7 -1
- package/lib/__templates__/nextjs/src/app/layout.tsx +1 -1
- package/lib/__templates__/nextjs/src/app/page.tsx +1 -2
- package/lib/__templates__/nextjs/src/server.ts +35 -0
- package/lib/__templates__/nextjs/tsconfig.json +1 -1
- package/lib/__templates__/nuxt-vue/.coze +12 -0
- package/lib/__templates__/nuxt-vue/AGENTS.md +42 -0
- package/lib/__templates__/nuxt-vue/README.md +73 -0
- package/lib/__templates__/nuxt-vue/_gitignore +24 -0
- package/lib/__templates__/nuxt-vue/_npmrc +23 -0
- package/lib/__templates__/nuxt-vue/app/app.vue +6 -0
- package/lib/__templates__/nuxt-vue/app/pages/index.vue +23 -0
- package/lib/__templates__/nuxt-vue/assets/css/main.css +24 -0
- package/lib/__templates__/nuxt-vue/nuxt.config.ts +116 -0
- package/lib/__templates__/nuxt-vue/package.json +35 -0
- package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +8759 -0
- package/lib/__templates__/nuxt-vue/postcss.config.mjs +8 -0
- package/lib/__templates__/nuxt-vue/public/favicon.ico +0 -0
- package/lib/__templates__/nuxt-vue/public/robots.txt +2 -0
- package/lib/__templates__/nuxt-vue/scripts/build.sh +14 -0
- package/lib/__templates__/nuxt-vue/scripts/dev.sh +39 -0
- package/lib/__templates__/nuxt-vue/scripts/prepare.sh +14 -0
- package/lib/__templates__/nuxt-vue/scripts/start.sh +21 -0
- package/lib/__templates__/nuxt-vue/server/api/hello.ts +10 -0
- package/lib/__templates__/nuxt-vue/server/middleware/logger.ts +10 -0
- package/lib/__templates__/nuxt-vue/server/routes/health.ts +10 -0
- package/lib/__templates__/nuxt-vue/tailwind.config.js +13 -0
- package/lib/__templates__/nuxt-vue/template.config.js +87 -0
- package/lib/__templates__/nuxt-vue/tsconfig.json +18 -0
- package/lib/__templates__/taro/README.md +57 -45
- package/lib/__templates__/taro/config/index.ts +106 -41
- package/lib/__templates__/taro/config/prod.ts +4 -5
- package/lib/__templates__/taro/eslint.config.mjs +62 -6
- package/lib/__templates__/taro/package.json +19 -4
- package/lib/__templates__/taro/patches/@tarojs__plugin-mini-ci@4.1.9.patch +30 -0
- package/lib/__templates__/taro/pnpm-lock.yaml +912 -206
- package/lib/__templates__/taro/src/app.css +140 -36
- package/lib/__templates__/taro/src/components/ui/accordion.tsx +159 -0
- package/lib/__templates__/taro/src/components/ui/alert-dialog.tsx +260 -0
- package/lib/__templates__/taro/src/components/ui/alert.tsx +60 -0
- package/lib/__templates__/taro/src/components/ui/aspect-ratio.tsx +36 -0
- package/lib/__templates__/taro/src/components/ui/avatar.tsx +84 -0
- package/lib/__templates__/taro/src/components/ui/badge.tsx +37 -0
- package/lib/__templates__/taro/src/components/ui/breadcrumb.tsx +117 -0
- package/lib/__templates__/taro/src/components/ui/button-group.tsx +83 -0
- package/lib/__templates__/taro/src/components/ui/button.tsx +67 -0
- package/lib/__templates__/taro/src/components/ui/calendar.tsx +394 -0
- package/lib/__templates__/taro/src/components/ui/card.tsx +108 -0
- package/lib/__templates__/taro/src/components/ui/carousel.tsx +228 -0
- package/lib/__templates__/taro/src/components/ui/checkbox.tsx +58 -0
- package/lib/__templates__/taro/src/components/ui/code-block.tsx +169 -0
- package/lib/__templates__/taro/src/components/ui/collapsible.tsx +71 -0
- package/lib/__templates__/taro/src/components/ui/command.tsx +385 -0
- package/lib/__templates__/taro/src/components/ui/context-menu.tsx +614 -0
- package/lib/__templates__/taro/src/components/ui/dialog.tsx +256 -0
- package/lib/__templates__/taro/src/components/ui/drawer.tsx +192 -0
- package/lib/__templates__/taro/src/components/ui/dropdown-menu.tsx +561 -0
- package/lib/__templates__/taro/src/components/ui/field.tsx +228 -0
- package/lib/__templates__/taro/src/components/ui/hover-card.tsx +282 -0
- package/lib/__templates__/taro/src/components/ui/input-group.tsx +197 -0
- package/lib/__templates__/taro/src/components/ui/input-otp.tsx +136 -0
- package/lib/__templates__/taro/src/components/ui/input.tsx +56 -0
- package/lib/__templates__/taro/src/components/ui/label.tsx +24 -0
- package/lib/__templates__/taro/src/components/ui/menubar.tsx +595 -0
- package/lib/__templates__/taro/src/components/ui/navigation-menu.tsx +264 -0
- package/lib/__templates__/taro/src/components/ui/pagination.tsx +118 -0
- package/lib/__templates__/taro/src/components/ui/popover.tsx +291 -0
- package/lib/__templates__/taro/src/components/ui/portal.tsx +19 -0
- package/lib/__templates__/taro/src/components/ui/progress.tsx +28 -0
- package/lib/__templates__/taro/src/components/ui/radio-group.tsx +64 -0
- package/lib/__templates__/taro/src/components/ui/resizable.tsx +346 -0
- package/lib/__templates__/taro/src/components/ui/scroll-area.tsx +34 -0
- package/lib/__templates__/taro/src/components/ui/select.tsx +438 -0
- package/lib/__templates__/taro/src/components/ui/separator.tsx +30 -0
- package/lib/__templates__/taro/src/components/ui/sheet.tsx +262 -0
- package/lib/__templates__/taro/src/components/ui/skeleton.tsx +17 -0
- package/lib/__templates__/taro/src/components/ui/slider.tsx +203 -0
- package/lib/__templates__/taro/src/components/ui/sonner.tsx +1 -0
- package/lib/__templates__/taro/src/components/ui/switch.tsx +55 -0
- package/lib/__templates__/taro/src/components/ui/table.tsx +142 -0
- package/lib/__templates__/taro/src/components/ui/tabs.tsx +114 -0
- package/lib/__templates__/taro/src/components/ui/textarea.tsx +54 -0
- package/lib/__templates__/taro/src/components/ui/toast.tsx +517 -0
- package/lib/__templates__/taro/src/components/ui/toggle-group.tsx +120 -0
- package/lib/__templates__/taro/src/components/ui/toggle.tsx +77 -0
- package/lib/__templates__/taro/src/components/ui/tooltip.tsx +455 -0
- package/lib/__templates__/taro/src/lib/hooks/use-keyboard-offset.ts +37 -0
- package/lib/__templates__/taro/src/lib/measure.ts +115 -0
- package/lib/__templates__/taro/src/lib/platform.ts +12 -0
- package/lib/__templates__/taro/src/lib/utils.ts +6 -0
- package/lib/__templates__/taro/src/presets/dev-debug.ts +23 -0
- package/lib/__templates__/taro/src/presets/h5-container.tsx +15 -0
- package/lib/__templates__/taro/src/presets/h5-navbar.tsx +97 -30
- package/lib/__templates__/taro/src/presets/h5-styles.ts +192 -5
- package/lib/__templates__/taro/src/presets/index.tsx +4 -4
- package/lib/__templates__/templates.json +32 -0
- package/lib/__templates__/vite/AGENTS.md +41 -0
- package/lib/__templates__/vite/README.md +190 -11
- package/lib/__templates__/vite/_gitignore +1 -0
- package/lib/__templates__/vite/eslint.config.mjs +6 -1
- package/lib/__templates__/vite/package.json +10 -3
- package/lib/__templates__/vite/pnpm-lock.yaml +755 -15
- package/lib/__templates__/vite/scripts/build.sh +4 -1
- package/lib/__templates__/vite/scripts/dev.sh +9 -2
- package/lib/__templates__/vite/scripts/start.sh +9 -3
- package/lib/__templates__/vite/server/routes/index.ts +31 -0
- package/lib/__templates__/vite/server/server.ts +65 -0
- package/lib/__templates__/vite/server/vite.ts +67 -0
- package/lib/__templates__/vite/tsconfig.json +4 -3
- package/lib/__templates__/vite/vite.config.ts +4 -0
- package/lib/cli.js +99 -92
- package/package.json +6 -3
- package/lib/__templates__/taro/src/presets/wx-debug.ts +0 -23
|
@@ -8,7 +8,10 @@ cd "${COZE_WORKSPACE_PATH}"
|
|
|
8
8
|
echo "Installing dependencies..."
|
|
9
9
|
pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
|
|
10
10
|
|
|
11
|
-
echo "Building
|
|
11
|
+
echo "Building frontend with Vite..."
|
|
12
12
|
npx vite build
|
|
13
13
|
|
|
14
|
+
echo "Bundling server with tsup..."
|
|
15
|
+
npx tsup server/server.ts --format cjs --platform node --target node20 --outDir dist-server --no-splitting --no-minify --external vite
|
|
16
|
+
|
|
14
17
|
echo "Build completed successfully!"
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
set -Eeuo pipefail
|
|
3
3
|
|
|
4
|
+
<% if (process.env.NODE_ENV === 'test') { %>
|
|
5
|
+
# 测试环境:支持环境变量覆盖端口
|
|
6
|
+
PORT="${PORT:-<%= port %>}"
|
|
7
|
+
COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
|
|
8
|
+
DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
|
|
9
|
+
<% } else { %>
|
|
4
10
|
PORT=<%= port %>
|
|
5
11
|
COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
|
|
6
12
|
DEPLOY_RUN_PORT=<%= port %>
|
|
13
|
+
<% } %>
|
|
7
14
|
|
|
8
15
|
cd "${COZE_WORKSPACE_PATH}"
|
|
9
16
|
|
|
@@ -27,6 +34,6 @@ kill_port_if_listening() {
|
|
|
27
34
|
|
|
28
35
|
echo "Clearing port ${PORT} before start."
|
|
29
36
|
kill_port_if_listening
|
|
30
|
-
echo "Starting
|
|
37
|
+
echo "Starting express + Vite dev server on port ${PORT}..."
|
|
31
38
|
|
|
32
|
-
npx
|
|
39
|
+
PORT=$PORT npx tsx watch server/server.ts
|
|
@@ -2,14 +2,20 @@
|
|
|
2
2
|
set -Eeuo pipefail
|
|
3
3
|
|
|
4
4
|
COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
|
|
5
|
+
<% if (process.env.NODE_ENV === 'test') { %>
|
|
6
|
+
# 测试环境:支持环境变量覆盖端口
|
|
7
|
+
PORT="${PORT:-<%= port %>}"
|
|
8
|
+
DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
|
|
9
|
+
<% } else { %>
|
|
5
10
|
PORT=<%= port %>
|
|
6
11
|
DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-$PORT}"
|
|
12
|
+
<% } %>
|
|
7
13
|
|
|
8
14
|
start_service() {
|
|
9
15
|
cd "${COZE_WORKSPACE_PATH}"
|
|
10
|
-
echo "Starting
|
|
11
|
-
|
|
16
|
+
echo "Starting express production server on port ${DEPLOY_RUN_PORT}..."
|
|
17
|
+
PORT=$DEPLOY_RUN_PORT node dist-server/server.js
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
echo "Starting
|
|
20
|
+
echo "Starting express production server on port ${DEPLOY_RUN_PORT}..."
|
|
15
21
|
start_service
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
|
|
3
|
+
const router = Router();
|
|
4
|
+
|
|
5
|
+
// API 路由示例
|
|
6
|
+
router.get('/api/hello', (req, res) => {
|
|
7
|
+
res.json({
|
|
8
|
+
message: 'Hello from Express + Vite!',
|
|
9
|
+
timestamp: new Date().toISOString(),
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
router.post('/api/data', (req, res) => {
|
|
14
|
+
const requestData = req.body;
|
|
15
|
+
res.json({
|
|
16
|
+
success: true,
|
|
17
|
+
data: requestData,
|
|
18
|
+
receivedAt: new Date().toISOString(),
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// 健康检查接口
|
|
23
|
+
router.get('/api/health', (req, res) => {
|
|
24
|
+
res.json({
|
|
25
|
+
status: 'ok',
|
|
26
|
+
env: process.env.COZE_PROJECT_ENV,
|
|
27
|
+
timestamp: new Date().toISOString(),
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export default router;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// ABOUTME: Express server with Vite integration
|
|
2
|
+
// ABOUTME: Handles API routes and serves frontend in dev/prod modes
|
|
3
|
+
|
|
4
|
+
import { createServer, type Server } from 'http';
|
|
5
|
+
import express from 'express';
|
|
6
|
+
import router from './routes/index';
|
|
7
|
+
import { setupVite } from './vite';
|
|
8
|
+
|
|
9
|
+
const isDev = process.env.COZE_PROJECT_ENV !== 'PROD';
|
|
10
|
+
const port = parseInt(process.env.PORT || '<%= port %>', 10);
|
|
11
|
+
const hostname = process.env.HOSTNAME || 'localhost';
|
|
12
|
+
const app = express();
|
|
13
|
+
// 使用 http.createServer 包装 Express app,以便支持 WebSocket 等协议升级
|
|
14
|
+
const server = createServer(app);
|
|
15
|
+
|
|
16
|
+
async function startServer(): Promise<Server> {
|
|
17
|
+
// 请求日志(仅开发环境)
|
|
18
|
+
if (isDev) {
|
|
19
|
+
app.use((req, res, next) => {
|
|
20
|
+
const start = Date.now();
|
|
21
|
+
res.on('finish', () => {
|
|
22
|
+
const ms = Date.now() - start;
|
|
23
|
+
console.log(`${req.method} ${req.url} - ${ms}ms`);
|
|
24
|
+
});
|
|
25
|
+
next();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 添加请求体解析
|
|
30
|
+
app.use(express.json());
|
|
31
|
+
app.use(express.urlencoded({ extended: true }));
|
|
32
|
+
|
|
33
|
+
// 注册 API 路由
|
|
34
|
+
app.use(router);
|
|
35
|
+
|
|
36
|
+
// 集成 Vite(开发模式)或静态文件服务(生产模式)
|
|
37
|
+
await setupVite(app);
|
|
38
|
+
|
|
39
|
+
// 全局错误处理
|
|
40
|
+
app.use((err: Error, req: express.Request, res: express.Response) => {
|
|
41
|
+
console.error('Server error:', err);
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
|
+
const status = 'status' in err ? (err as any).status || 500 : 500;
|
|
44
|
+
res.status(status).json({
|
|
45
|
+
error: err.message || 'Internal server error',
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
server.once('error', err => {
|
|
50
|
+
console.error('Server error:', err);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
server.listen(port, () => {
|
|
55
|
+
console.log(`\n✨ Server running at http://${hostname}:${port}`);
|
|
56
|
+
console.log(`📝 Environment: ${isDev ? 'development' : 'production'}\n`);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return server;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
startServer().catch(err => {
|
|
63
|
+
console.error('Failed to start server:', err);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// ABOUTME: Vite integration for Express server
|
|
2
|
+
// ABOUTME: Handles dev middleware and production static file serving
|
|
3
|
+
|
|
4
|
+
import type { Application, Request, Response } from 'express';
|
|
5
|
+
import express from 'express';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import { createServer as createViteServer } from 'vite';
|
|
9
|
+
import viteConfig from '../vite.config';
|
|
10
|
+
|
|
11
|
+
const isDev = process.env.COZE_PROJECT_ENV !== 'PROD';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 集成 Vite 开发服务器(中间件模式)
|
|
15
|
+
*/
|
|
16
|
+
export async function setupViteMiddleware(app: Application) {
|
|
17
|
+
const vite = await createViteServer({
|
|
18
|
+
...viteConfig,
|
|
19
|
+
server: {
|
|
20
|
+
...viteConfig.server,
|
|
21
|
+
middlewareMode: true,
|
|
22
|
+
},
|
|
23
|
+
appType: 'spa',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// 使用 Vite middleware
|
|
27
|
+
app.use(vite.middlewares);
|
|
28
|
+
|
|
29
|
+
console.log('🚀 Vite dev server initialized');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 设置生产环境静态文件服务
|
|
34
|
+
*/
|
|
35
|
+
export function setupStaticServer(app: Application) {
|
|
36
|
+
const distPath = path.resolve(process.cwd(), 'dist');
|
|
37
|
+
|
|
38
|
+
if (!fs.existsSync(distPath)) {
|
|
39
|
+
console.error('❌ dist folder not found. Please run "pnpm build" first.');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 1. 服务静态文件(如果存在对应文件则直接返回)
|
|
44
|
+
app.use(express.static(distPath));
|
|
45
|
+
|
|
46
|
+
// 2. SPA fallback - 所有未处理的请求返回 index.html
|
|
47
|
+
// 到达这里的请求说明:
|
|
48
|
+
// - 不是 API 请求(已被前面注册的路由处理)
|
|
49
|
+
// - 不是静态文件(express.static 未找到对应文件)
|
|
50
|
+
// - 需要返回 index.html 让前端路由处理
|
|
51
|
+
app.use((_req: Request, res: Response) => {
|
|
52
|
+
res.sendFile(path.join(distPath, 'index.html'));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
console.log('📦 Serving static files from dist/');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 根据环境设置 Vite
|
|
60
|
+
*/
|
|
61
|
+
export async function setupVite(app: Application) {
|
|
62
|
+
if (isDev) {
|
|
63
|
+
await setupViteMiddleware(app);
|
|
64
|
+
} else {
|
|
65
|
+
setupStaticServer(app);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
"target": "ES2020",
|
|
4
4
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
5
5
|
"module": "ESNext",
|
|
6
|
-
"moduleResolution": "
|
|
6
|
+
"moduleResolution": "node",
|
|
7
7
|
"strict": true,
|
|
8
8
|
"esModuleInterop": true,
|
|
9
9
|
"skipLibCheck": true,
|
|
10
10
|
"forceConsistentCasingInFileNames": true,
|
|
11
11
|
"resolveJsonModule": true,
|
|
12
12
|
"isolatedModules": true,
|
|
13
|
-
"noEmit": true
|
|
13
|
+
"noEmit": true,
|
|
14
|
+
"types": ["node"]
|
|
14
15
|
},
|
|
15
|
-
"include": ["src"]
|
|
16
|
+
"include": ["src", "server"]
|
|
16
17
|
}
|
package/lib/cli.js
CHANGED
|
@@ -1722,38 +1722,6 @@ const collectFilesToRender = async (options
|
|
|
1722
1722
|
|
|
1723
1723
|
return filesToWrite;
|
|
1724
1724
|
};
|
|
1725
|
-
|
|
1726
|
-
/**
|
|
1727
|
-
* 检测文件冲突
|
|
1728
|
-
*
|
|
1729
|
-
* @param outputPath - 输出目录路径
|
|
1730
|
-
* @param filesToWrite - 将要写入的文件路径列表
|
|
1731
|
-
* @returns 冲突的文件路径列表
|
|
1732
|
-
*/
|
|
1733
|
-
const detectFileConflicts = (
|
|
1734
|
-
outputPath,
|
|
1735
|
-
filesToWrite,
|
|
1736
|
-
) => {
|
|
1737
|
-
logger.verbose('\nChecking for file conflicts...');
|
|
1738
|
-
|
|
1739
|
-
const conflicts = [];
|
|
1740
|
-
|
|
1741
|
-
for (const file of filesToWrite) {
|
|
1742
|
-
const fullPath = path.join(outputPath, file);
|
|
1743
|
-
if (fs.existsSync(fullPath)) {
|
|
1744
|
-
conflicts.push(file);
|
|
1745
|
-
logger.verbose(` ⚠ Conflict detected: ${file}`);
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
if (conflicts.length === 0) {
|
|
1750
|
-
logger.verbose(' ✓ No conflicts detected');
|
|
1751
|
-
} else {
|
|
1752
|
-
logger.verbose(` ⚠ ${conflicts.length} conflicts detected`);
|
|
1753
|
-
}
|
|
1754
|
-
|
|
1755
|
-
return conflicts;
|
|
1756
|
-
};
|
|
1757
1725
|
// end_aigc
|
|
1758
1726
|
|
|
1759
1727
|
// ABOUTME: Main file processing orchestration for template rendering
|
|
@@ -1809,7 +1777,7 @@ const processSingleFile = async (options
|
|
|
1809
1777
|
* 1. 验证模板目录
|
|
1810
1778
|
* 2. 扫描所有模板文件
|
|
1811
1779
|
* 3. Dry-run:收集将要写入的文件列表(考虑 hooks 影响)
|
|
1812
|
-
* 4.
|
|
1780
|
+
* 4. 冲突检测:检查是否有文件会被覆盖(可通过 force 跳过)
|
|
1813
1781
|
* 5. 实际写入:渲染并写入所有文件
|
|
1814
1782
|
* 6. 复制 node_modules(如果存在)
|
|
1815
1783
|
*
|
|
@@ -1820,8 +1788,9 @@ const processTemplateFiles = async (options
|
|
|
1820
1788
|
|
|
1821
1789
|
|
|
1822
1790
|
|
|
1791
|
+
|
|
1823
1792
|
) => {
|
|
1824
|
-
const { templatePath, outputPath, context, templateConfig
|
|
1793
|
+
const { templatePath, outputPath, context, templateConfig} = options;
|
|
1825
1794
|
logger.verbose('Processing template files:');
|
|
1826
1795
|
logger.verbose(` - Template path: ${templatePath}`);
|
|
1827
1796
|
logger.verbose(` - Output path: ${outputPath}`);
|
|
@@ -1853,23 +1822,17 @@ const processTemplateFiles = async (options
|
|
|
1853
1822
|
}
|
|
1854
1823
|
|
|
1855
1824
|
// 阶段 2: Dry-run - 收集所有将要写入的文件
|
|
1856
|
-
|
|
1825
|
+
await collectFilesToRender({
|
|
1857
1826
|
files,
|
|
1858
1827
|
templatePath,
|
|
1859
1828
|
context,
|
|
1860
1829
|
templateConfig,
|
|
1861
1830
|
});
|
|
1862
1831
|
|
|
1863
|
-
// 阶段 3:
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
// 有冲突,抛出详细的错误信息
|
|
1868
|
-
const conflictList = conflicts.map(f => ` - ${f}`).join('\n');
|
|
1869
|
-
throw new Error(
|
|
1870
|
-
`File conflicts detected in output directory: ${outputPath}\n\n` +
|
|
1871
|
-
`The following files already exist and would be overwritten:\n${conflictList}\n\n` +
|
|
1872
|
-
'Please remove these files or use a different output directory.',
|
|
1832
|
+
// 阶段 3: 冲突检测(force 为 true 时跳过)
|
|
1833
|
+
{
|
|
1834
|
+
logger.verbose(
|
|
1835
|
+
' - Force mode enabled, skipping conflict detection. Existing files will be overwritten.',
|
|
1873
1836
|
);
|
|
1874
1837
|
}
|
|
1875
1838
|
|
|
@@ -1902,6 +1865,7 @@ const processTemplateFiles = async (options
|
|
|
1902
1865
|
|
|
1903
1866
|
|
|
1904
1867
|
|
|
1868
|
+
|
|
1905
1869
|
/**
|
|
1906
1870
|
* 加载模板元数据和路径
|
|
1907
1871
|
*/
|
|
@@ -2011,7 +1975,7 @@ const prepareOutputDirectory = (outputPath) => {
|
|
|
2011
1975
|
const execute = async (
|
|
2012
1976
|
options,
|
|
2013
1977
|
) => {
|
|
2014
|
-
const { templateName, outputPath, command
|
|
1978
|
+
const { templateName, outputPath, command} = options;
|
|
2015
1979
|
|
|
2016
1980
|
// 1. 加载模板
|
|
2017
1981
|
const { templatePath } = await loadTemplateMetadata(templateName);
|
|
@@ -2035,8 +1999,7 @@ const execute = async (
|
|
|
2035
1999
|
templatePath,
|
|
2036
2000
|
outputPath: absoluteOutputPath,
|
|
2037
2001
|
context,
|
|
2038
|
-
templateConfig
|
|
2039
|
-
});
|
|
2002
|
+
templateConfig});
|
|
2040
2003
|
|
|
2041
2004
|
// 7. 执行 onAfterRender 钩子
|
|
2042
2005
|
await executeAfterRenderHook(templateConfig, context, absoluteOutputPath);
|
|
@@ -2087,7 +2050,40 @@ const runPnpmInstall = (projectPath) => {
|
|
|
2087
2050
|
};
|
|
2088
2051
|
|
|
2089
2052
|
/**
|
|
2090
|
-
*
|
|
2053
|
+
* 运行 git 命令的辅助函数
|
|
2054
|
+
*/
|
|
2055
|
+
const runGitCommand = (command, projectPath) => {
|
|
2056
|
+
logger.info(`Executing: ${command}`);
|
|
2057
|
+
|
|
2058
|
+
const result = shelljs.exec(command, {
|
|
2059
|
+
cwd: projectPath,
|
|
2060
|
+
silent: true,
|
|
2061
|
+
});
|
|
2062
|
+
|
|
2063
|
+
// 输出命令的结果
|
|
2064
|
+
if (result.stdout) {
|
|
2065
|
+
process.stdout.write(result.stdout);
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
if (result.stderr) {
|
|
2069
|
+
process.stderr.write(result.stderr);
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
if (result.code !== 0) {
|
|
2073
|
+
const errorMessage = [
|
|
2074
|
+
`${command} failed with exit code ${result.code}`,
|
|
2075
|
+
result.stderr ? `\nStderr:\n${result.stderr}` : '',
|
|
2076
|
+
result.stdout ? `\nStdout:\n${result.stdout}` : '',
|
|
2077
|
+
]
|
|
2078
|
+
.filter(Boolean)
|
|
2079
|
+
.join('');
|
|
2080
|
+
|
|
2081
|
+
throw new Error(errorMessage);
|
|
2082
|
+
}
|
|
2083
|
+
};
|
|
2084
|
+
|
|
2085
|
+
/**
|
|
2086
|
+
* 初始化 git 仓库
|
|
2091
2087
|
* 如果目录中已存在 .git,则跳过初始化
|
|
2092
2088
|
*/
|
|
2093
2089
|
const runGitInit = (projectPath) => {
|
|
@@ -2100,46 +2096,9 @@ const runGitInit = (projectPath) => {
|
|
|
2100
2096
|
return;
|
|
2101
2097
|
}
|
|
2102
2098
|
|
|
2103
|
-
const runGitCommand = (command) => {
|
|
2104
|
-
logger.info(`Executing: ${command}`);
|
|
2105
|
-
|
|
2106
|
-
const result = shelljs.exec(command, {
|
|
2107
|
-
cwd: projectPath,
|
|
2108
|
-
silent: true,
|
|
2109
|
-
});
|
|
2110
|
-
|
|
2111
|
-
// 输出命令的结果
|
|
2112
|
-
if (result.stdout) {
|
|
2113
|
-
process.stdout.write(result.stdout);
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
if (result.stderr) {
|
|
2117
|
-
process.stderr.write(result.stderr);
|
|
2118
|
-
}
|
|
2119
|
-
|
|
2120
|
-
if (result.code !== 0) {
|
|
2121
|
-
const errorMessage = [
|
|
2122
|
-
`${command} failed with exit code ${result.code}`,
|
|
2123
|
-
result.stderr ? `\nStderr:\n${result.stderr}` : '',
|
|
2124
|
-
result.stdout ? `\nStdout:\n${result.stdout}` : '',
|
|
2125
|
-
]
|
|
2126
|
-
.filter(Boolean)
|
|
2127
|
-
.join('');
|
|
2128
|
-
|
|
2129
|
-
throw new Error(errorMessage);
|
|
2130
|
-
}
|
|
2131
|
-
};
|
|
2132
|
-
|
|
2133
2099
|
try {
|
|
2134
2100
|
logger.info('\nInitializing git repository...');
|
|
2135
|
-
runGitCommand('git init');
|
|
2136
|
-
|
|
2137
|
-
logger.info('Adding files to git...');
|
|
2138
|
-
runGitCommand('git add .');
|
|
2139
|
-
|
|
2140
|
-
logger.info('Creating initial commit...');
|
|
2141
|
-
runGitCommand('git commit -m "chore: initial commit"');
|
|
2142
|
-
|
|
2101
|
+
runGitCommand('git init', projectPath);
|
|
2143
2102
|
logger.success('Git repository initialized successfully!');
|
|
2144
2103
|
} catch (error) {
|
|
2145
2104
|
// Git 初始化失败不应该导致整个流程失败
|
|
@@ -2150,6 +2109,35 @@ const runGitInit = (projectPath) => {
|
|
|
2150
2109
|
}
|
|
2151
2110
|
};
|
|
2152
2111
|
|
|
2112
|
+
/**
|
|
2113
|
+
* 提交初始化生成的所有文件
|
|
2114
|
+
*/
|
|
2115
|
+
const commitChanges = (projectPath) => {
|
|
2116
|
+
// 检查是否存在 .git 目录
|
|
2117
|
+
const gitDir = path.join(projectPath, '.git');
|
|
2118
|
+
if (!fs.existsSync(gitDir)) {
|
|
2119
|
+
logger.warn(
|
|
2120
|
+
'\n⚠️ Git repository does not exist, skipping commit. Run git init first.',
|
|
2121
|
+
);
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
try {
|
|
2126
|
+
logger.info('\nCommitting initialized files...');
|
|
2127
|
+
runGitCommand('git add --all', projectPath);
|
|
2128
|
+
runGitCommand('git commit -m "chore: init env"', projectPath);
|
|
2129
|
+
logger.success('Changes committed successfully!');
|
|
2130
|
+
} catch (error) {
|
|
2131
|
+
// Commit 失败不应该导致整个流程失败
|
|
2132
|
+
logger.warn(
|
|
2133
|
+
`Git commit failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
2134
|
+
);
|
|
2135
|
+
logger.info(
|
|
2136
|
+
'You can manually commit later with: git add --all && git commit -m "chore: init env"',
|
|
2137
|
+
);
|
|
2138
|
+
}
|
|
2139
|
+
};
|
|
2140
|
+
|
|
2153
2141
|
/**
|
|
2154
2142
|
* 运行开发服务器(后台模式)
|
|
2155
2143
|
* 启动后台子进程运行开发服务器,父进程可以直接退出
|
|
@@ -2191,6 +2179,8 @@ const executeInit = async (
|
|
|
2191
2179
|
|
|
2192
2180
|
|
|
2193
2181
|
|
|
2182
|
+
|
|
2183
|
+
|
|
2194
2184
|
,
|
|
2195
2185
|
command,
|
|
2196
2186
|
) => {
|
|
@@ -2202,7 +2192,9 @@ const executeInit = async (
|
|
|
2202
2192
|
output: outputPath,
|
|
2203
2193
|
skipInstall,
|
|
2204
2194
|
skipGit,
|
|
2195
|
+
skipCommit,
|
|
2205
2196
|
skipDev,
|
|
2197
|
+
force,
|
|
2206
2198
|
} = options;
|
|
2207
2199
|
|
|
2208
2200
|
logger.info(`Initializing project with template: ${templateName}`);
|
|
@@ -2213,6 +2205,7 @@ const executeInit = async (
|
|
|
2213
2205
|
templateName,
|
|
2214
2206
|
outputPath,
|
|
2215
2207
|
command,
|
|
2208
|
+
force,
|
|
2216
2209
|
});
|
|
2217
2210
|
const { outputPath: absoluteOutputPath, templateConfig, context } = result;
|
|
2218
2211
|
|
|
@@ -2245,6 +2238,12 @@ const executeInit = async (
|
|
|
2245
2238
|
timer.logPhase('Git initialization');
|
|
2246
2239
|
}
|
|
2247
2240
|
|
|
2241
|
+
// 如果没有跳过 commit,则提交初始化生成的文件
|
|
2242
|
+
if (!skipCommit) {
|
|
2243
|
+
commitChanges(absoluteOutputPath);
|
|
2244
|
+
timer.logPhase('Git commit');
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2248
2247
|
// 如果没有跳过 dev,则启动开发服务器
|
|
2249
2248
|
if (!skipDev) {
|
|
2250
2249
|
runDev(absoluteOutputPath);
|
|
@@ -2257,9 +2256,10 @@ const executeInit = async (
|
|
|
2257
2256
|
logger.info(' pnpm install');
|
|
2258
2257
|
}
|
|
2259
2258
|
if (skipGit) {
|
|
2260
|
-
logger.info(
|
|
2261
|
-
|
|
2262
|
-
|
|
2259
|
+
logger.info(' git init');
|
|
2260
|
+
}
|
|
2261
|
+
if (skipCommit) {
|
|
2262
|
+
logger.info(' git add --all && git commit -m "chore: init env"');
|
|
2263
2263
|
}
|
|
2264
2264
|
logger.info(' coze dev');
|
|
2265
2265
|
}
|
|
@@ -2286,12 +2286,19 @@ const registerCommand$1 = program => {
|
|
|
2286
2286
|
.option('-o, --output <path>', 'Output directory', process.cwd())
|
|
2287
2287
|
.option('--skip-install', 'Skip automatic pnpm install', false)
|
|
2288
2288
|
.option('--skip-git', 'Skip automatic git initialization', false)
|
|
2289
|
+
.option(
|
|
2290
|
+
'--skip-commit',
|
|
2291
|
+
'Skip automatic git commit after initialization',
|
|
2292
|
+
false,
|
|
2293
|
+
)
|
|
2289
2294
|
.option('--skip-dev', 'Skip automatic dev server start', false)
|
|
2290
2295
|
.allowUnknownOption() // 允许透传参数
|
|
2291
2296
|
.action(async (directory, options, command) => {
|
|
2292
2297
|
// 位置参数优先级高于 --output 选项
|
|
2293
2298
|
const outputPath = _nullishCoalesce(directory, () => ( options.output));
|
|
2294
|
-
|
|
2299
|
+
// Always use force mode - overwrite existing files without conflict check
|
|
2300
|
+
const force = true;
|
|
2301
|
+
await executeInit({ ...options, output: outputPath, force }, command);
|
|
2295
2302
|
});
|
|
2296
2303
|
};
|
|
2297
2304
|
|
|
@@ -2591,7 +2598,7 @@ const registerCommand = program => {
|
|
|
2591
2598
|
});
|
|
2592
2599
|
};
|
|
2593
2600
|
|
|
2594
|
-
var version = "0.0.1-alpha.
|
|
2601
|
+
var version = "0.0.1-alpha.dcc485";
|
|
2595
2602
|
var packageJson = {
|
|
2596
2603
|
version: version};
|
|
2597
2604
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coze-arch/cli",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.dcc485",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "coze coding devtools cli",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"@coze-arch/vitest-config": "workspace:*",
|
|
51
51
|
"@coze-coding/lambda": "workspace:*",
|
|
52
52
|
"@inquirer/prompts": "^3.2.0",
|
|
53
|
+
"@playwright/test": "~1.55.0",
|
|
53
54
|
"@types/ejs": "^3.1.5",
|
|
54
55
|
"@types/iarna__toml": "^2.0.5",
|
|
55
56
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -57,14 +58,16 @@
|
|
|
57
58
|
"@types/minimist": "^1.2.5",
|
|
58
59
|
"@types/node": "^24",
|
|
59
60
|
"@types/shelljs": "^0.10.0",
|
|
60
|
-
"@vitest/coverage-v8": "~4.0.
|
|
61
|
+
"@vitest/coverage-v8": "~4.0.18",
|
|
61
62
|
"json-schema-to-typescript": "^15.0.3",
|
|
62
63
|
"minimatch": "^10.0.1",
|
|
64
|
+
"playwright": "~1.55.0",
|
|
63
65
|
"rollup": "^4.41.1",
|
|
64
66
|
"sucrase": "^3.35.0",
|
|
67
|
+
"tree-kill": "^1.2.2",
|
|
65
68
|
"tsx": "^4.20.6",
|
|
66
69
|
"vite-tsconfig-paths": "^4.2.1",
|
|
67
|
-
"vitest": "~4.0.
|
|
70
|
+
"vitest": "~4.0.18"
|
|
68
71
|
},
|
|
69
72
|
"publishConfig": {
|
|
70
73
|
"access": "public",
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import Taro from '@tarojs/taro'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 微信小程序调试工具
|
|
5
|
-
* 在开发版/体验版自动开启调试模式
|
|
6
|
-
*/
|
|
7
|
-
export function enableWxDebugIfNeeded() {
|
|
8
|
-
// 仅在微信小程序环境执行
|
|
9
|
-
if (Taro.getEnv() === Taro.ENV_TYPE.WEAPP) {
|
|
10
|
-
try {
|
|
11
|
-
const accountInfo = Taro.getAccountInfoSync()
|
|
12
|
-
const envVersion = accountInfo.miniProgram.envVersion
|
|
13
|
-
console.log('[Debug] envVersion:', envVersion)
|
|
14
|
-
|
|
15
|
-
// 开发版/体验版自动开启调试
|
|
16
|
-
if (envVersion !== 'release') {
|
|
17
|
-
Taro.setEnableDebug({ enableDebug: true })
|
|
18
|
-
}
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.error('[Debug] 开启调试模式失败:', error)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|