@coze-arch/cli 0.0.1-alpha.e9ff73 → 0.0.1-alpha.eaa612
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/__templates__/expo/client/components/Screen.tsx +2 -2
- package/lib/__templates__/expo/client/eslint.config.mjs +4 -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__/nextjs/README.md +5 -0
- package/lib/__templates__/nextjs/_gitignore +0 -3
- package/lib/__templates__/nextjs/eslint.config.mjs +5 -0
- package/lib/__templates__/nextjs/next.config.ts +1 -2
- package/lib/__templates__/nextjs/package.json +1 -5
- package/lib/__templates__/nextjs/pnpm-lock.yaml +1012 -12
- package/lib/__templates__/nextjs/scripts/build.sh +2 -2
- package/lib/__templates__/nextjs/scripts/dev.sh +3 -4
- package/lib/__templates__/nextjs/scripts/start.sh +3 -3
- package/lib/__templates__/nextjs/src/app/layout.tsx +1 -1
- package/lib/__templates__/nextjs/{server.ts → src/server.ts} +14 -14
- package/lib/__templates__/nextjs/tsconfig.json +1 -1
- package/lib/__templates__/nuxt-app/README.md +5 -15
- package/lib/__templates__/nuxt-app/app/app.vue +1 -188
- package/lib/__templates__/nuxt-app/app/pages/index.vue +23 -0
- package/lib/__templates__/nuxt-app/assets/css/main.css +24 -0
- package/lib/__templates__/nuxt-app/nuxt.config.ts +63 -3
- package/lib/__templates__/nuxt-app/package.json +7 -0
- package/lib/__templates__/nuxt-app/pnpm-lock.yaml +1610 -53
- package/lib/__templates__/nuxt-app/postcss.config.mjs +8 -0
- package/lib/__templates__/nuxt-app/scripts/dev.sh +2 -3
- package/lib/__templates__/nuxt-app/scripts/start.sh +3 -3
- package/lib/__templates__/nuxt-app/server/api/hello.ts +10 -0
- package/lib/__templates__/nuxt-app/server/middleware/logger.ts +10 -0
- package/lib/__templates__/nuxt-app/server/routes/health.ts +10 -0
- package/lib/__templates__/nuxt-app/tailwind.config.js +13 -0
- package/lib/__templates__/nuxt-app/template.config.js +9 -0
- package/lib/__templates__/templates.json +7 -0
- package/lib/__templates__/vite/README.md +189 -11
- package/lib/__templates__/vite/_gitignore +1 -0
- package/lib/__templates__/vite/eslint.config.mjs +6 -1
- package/lib/__templates__/vite/package.json +15 -3
- package/lib/__templates__/vite/pnpm-lock.yaml +750 -15
- package/lib/__templates__/vite/scripts/build-server.js +70 -0
- package/lib/__templates__/vite/scripts/build.sh +4 -1
- package/lib/__templates__/vite/scripts/dev.sh +4 -4
- package/lib/__templates__/vite/scripts/start.sh +5 -5
- package/lib/__templates__/vite/server/index.ts +57 -0
- package/lib/__templates__/vite/server/routes/index.ts +31 -0
- package/lib/__templates__/vite/server/vite.ts +79 -0
- package/lib/__templates__/vite/tsconfig.json +4 -3
- package/lib/cli.js +89 -100
- package/package.json +4 -1
- package/lib/__templates__/nuxt-app/.nuxt/app.config.mjs +0 -21
- package/lib/__templates__/nuxt-app/.nuxt/components.d.ts +0 -64
- package/lib/__templates__/nuxt-app/.nuxt/imports.d.ts +0 -31
- package/lib/__templates__/nuxt-app/.nuxt/manifest/meta/f97812ec-f25e-427b-b45d-eab58fba39f9.json +0 -1
- package/lib/__templates__/nuxt-app/.nuxt/nuxt.d.ts +0 -19
- package/lib/__templates__/nuxt-app/.nuxt/nuxt.node.d.ts +0 -14
- package/lib/__templates__/nuxt-app/.nuxt/nuxt.shared.d.ts +0 -6
- package/lib/__templates__/nuxt-app/.nuxt/schema/nuxt.schema.d.ts +0 -17
- package/lib/__templates__/nuxt-app/.nuxt/schema/nuxt.schema.json +0 -3
- package/lib/__templates__/nuxt-app/.nuxt/tsconfig.app.json +0 -201
- package/lib/__templates__/nuxt-app/.nuxt/tsconfig.json +0 -203
- package/lib/__templates__/nuxt-app/.nuxt/tsconfig.node.json +0 -110
- package/lib/__templates__/nuxt-app/.nuxt/tsconfig.server.json +0 -140
- package/lib/__templates__/nuxt-app/.nuxt/tsconfig.shared.json +0 -152
- package/lib/__templates__/nuxt-app/.nuxt/types/app.config.d.ts +0 -35
- package/lib/__templates__/nuxt-app/.nuxt/types/build.d.ts +0 -24
- package/lib/__templates__/nuxt-app/.nuxt/types/builder-env.d.ts +0 -1
- package/lib/__templates__/nuxt-app/.nuxt/types/components.d.ts +0 -69
- package/lib/__templates__/nuxt-app/.nuxt/types/imports.d.ts +0 -360
- package/lib/__templates__/nuxt-app/.nuxt/types/middleware.d.ts +0 -11
- package/lib/__templates__/nuxt-app/.nuxt/types/modules.d.ts +0 -79
- package/lib/__templates__/nuxt-app/.nuxt/types/nitro-config.d.ts +0 -14
- package/lib/__templates__/nuxt-app/.nuxt/types/nitro-imports.d.ts +0 -151
- package/lib/__templates__/nuxt-app/.nuxt/types/nitro-layouts.d.ts +0 -17
- package/lib/__templates__/nuxt-app/.nuxt/types/nitro-nuxt.d.ts +0 -64
- package/lib/__templates__/nuxt-app/.nuxt/types/nitro-routes.d.ts +0 -17
- package/lib/__templates__/nuxt-app/.nuxt/types/nitro.d.ts +0 -3
- package/lib/__templates__/nuxt-app/.nuxt/types/plugins.d.ts +0 -30
- package/lib/__templates__/nuxt-app/.nuxt/types/runtime-config.d.ts +0 -32
- package/lib/__templates__/nuxt-app/.nuxt/types/shared-imports.d.ts +0 -10
- package/lib/__templates__/nuxt-app/.nuxt/types/vue-shim.d.ts +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 构建服务器端代码
|
|
5
|
+
* 自动读取 package.json 的 dependencies,将它们标记为 external
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { build } = require('esbuild');
|
|
9
|
+
const { readFileSync } = require('fs');
|
|
10
|
+
const { resolve } = require('path');
|
|
11
|
+
|
|
12
|
+
const projectRoot = resolve(__dirname, '..');
|
|
13
|
+
|
|
14
|
+
// 读取 package.json
|
|
15
|
+
const packageJsonPath = resolve(projectRoot, 'package.json');
|
|
16
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
17
|
+
|
|
18
|
+
// 获取所有 dependencies(运行时依赖)
|
|
19
|
+
const dependencies = Object.keys(packageJson.dependencies || {});
|
|
20
|
+
|
|
21
|
+
// 添加 Node.js 内置模块到 external 列表
|
|
22
|
+
const nodeBuiltins = [
|
|
23
|
+
'fs',
|
|
24
|
+
'path',
|
|
25
|
+
'url',
|
|
26
|
+
'http',
|
|
27
|
+
'https',
|
|
28
|
+
'stream',
|
|
29
|
+
'util',
|
|
30
|
+
'events',
|
|
31
|
+
'buffer',
|
|
32
|
+
'crypto',
|
|
33
|
+
'os',
|
|
34
|
+
'net',
|
|
35
|
+
'tls',
|
|
36
|
+
'zlib',
|
|
37
|
+
'querystring',
|
|
38
|
+
'child_process',
|
|
39
|
+
'worker_threads',
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// vite 只在开发环境通过动态 import 使用,需要标记为 external 避免打包
|
|
43
|
+
const devOnlyPackages = ['vite'];
|
|
44
|
+
|
|
45
|
+
// 合并所有 external 依赖
|
|
46
|
+
const external = [...dependencies, ...devOnlyPackages, ...nodeBuiltins];
|
|
47
|
+
|
|
48
|
+
console.log('📦 Building server...');
|
|
49
|
+
console.log(`External dependencies (${external.length}):`, external.join(', '));
|
|
50
|
+
|
|
51
|
+
// 使用 esbuild 构建
|
|
52
|
+
build({
|
|
53
|
+
entryPoints: [resolve(projectRoot, 'server/index.ts')],
|
|
54
|
+
bundle: true,
|
|
55
|
+
platform: 'node',
|
|
56
|
+
target: 'node18',
|
|
57
|
+
format: 'cjs',
|
|
58
|
+
outdir: resolve(projectRoot, 'dist-server'),
|
|
59
|
+
external,
|
|
60
|
+
sourcemap: true,
|
|
61
|
+
minify: false, // 生产环境可以设置为 true
|
|
62
|
+
logLevel: 'info',
|
|
63
|
+
})
|
|
64
|
+
.then(() => {
|
|
65
|
+
console.log('✅ Server build completed successfully!');
|
|
66
|
+
})
|
|
67
|
+
.catch((error) => {
|
|
68
|
+
console.error('❌ Server build failed:', error);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
|
@@ -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 "Building server with esbuild..."
|
|
15
|
+
node scripts/build-server.js
|
|
16
|
+
|
|
14
17
|
echo "Build completed successfully!"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
set -Eeuo pipefail
|
|
3
3
|
|
|
4
|
-
PORT
|
|
4
|
+
PORT="${PORT:-<%= port %>}"
|
|
5
5
|
COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
|
|
6
|
-
DEPLOY_RUN_PORT
|
|
6
|
+
DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
|
|
7
7
|
|
|
8
8
|
cd "${COZE_WORKSPACE_PATH}"
|
|
9
9
|
|
|
@@ -27,6 +27,6 @@ kill_port_if_listening() {
|
|
|
27
27
|
|
|
28
28
|
echo "Clearing port ${PORT} before start."
|
|
29
29
|
kill_port_if_listening
|
|
30
|
-
echo "Starting
|
|
30
|
+
echo "Starting Koa + Vite dev server on port ${PORT}..."
|
|
31
31
|
|
|
32
|
-
npx
|
|
32
|
+
PORT=$PORT npx tsx watch server/index.ts
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
set -Eeuo pipefail
|
|
3
3
|
|
|
4
4
|
COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
|
|
5
|
-
PORT
|
|
6
|
-
DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-$PORT}"
|
|
5
|
+
PORT="${PORT:-<%= port %>}"
|
|
6
|
+
DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
|
|
7
7
|
|
|
8
8
|
start_service() {
|
|
9
9
|
cd "${COZE_WORKSPACE_PATH}"
|
|
10
|
-
echo "Starting
|
|
11
|
-
|
|
10
|
+
echo "Starting Koa production server on port ${DEPLOY_RUN_PORT}..."
|
|
11
|
+
PORT=$DEPLOY_RUN_PORT node dist-server/index.js
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
echo "Starting
|
|
14
|
+
echo "Starting Koa production server on port ${DEPLOY_RUN_PORT}..."
|
|
15
15
|
start_service
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import Koa from 'koa';
|
|
2
|
+
import bodyParser from 'koa-bodyparser';
|
|
3
|
+
import router from './routes/index';
|
|
4
|
+
import { setupVite } from './vite';
|
|
5
|
+
|
|
6
|
+
const isDev = process.env.COZE_PROJECT_ENV !== 'PROD';
|
|
7
|
+
|
|
8
|
+
async function createServer() {
|
|
9
|
+
const app = new Koa();
|
|
10
|
+
|
|
11
|
+
// 全局错误处理
|
|
12
|
+
app.use(async (ctx, next) => {
|
|
13
|
+
try {
|
|
14
|
+
await next();
|
|
15
|
+
} catch (err) {
|
|
16
|
+
console.error('Server error:', err);
|
|
17
|
+
const status =
|
|
18
|
+
err instanceof Error && 'status' in err
|
|
19
|
+
? (err as { status?: number }).status || 500
|
|
20
|
+
: 500;
|
|
21
|
+
ctx.status = status;
|
|
22
|
+
ctx.body = {
|
|
23
|
+
error: err instanceof Error ? err.message : 'Internal server error',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// 请求日志(仅开发环境)
|
|
29
|
+
if (isDev) {
|
|
30
|
+
app.use(async (ctx, next) => {
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
await next();
|
|
33
|
+
const ms = Date.now() - start;
|
|
34
|
+
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 添加请求体解析
|
|
39
|
+
app.use(bodyParser());
|
|
40
|
+
|
|
41
|
+
// 注册 API 路由
|
|
42
|
+
app.use(router.routes()).use(router.allowedMethods());
|
|
43
|
+
|
|
44
|
+
// 集成 Vite(开发模式)或静态文件服务(生产模式)
|
|
45
|
+
await setupVite(app);
|
|
46
|
+
|
|
47
|
+
const port = process.env.PORT || <%= port %>;
|
|
48
|
+
app.listen(port, () => {
|
|
49
|
+
console.log(`\n✨ Server running at http://localhost:${port}`);
|
|
50
|
+
console.log(`📝 Environment: ${isDev ? 'development' : 'production'}\n`);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
createServer().catch((err) => {
|
|
55
|
+
console.error('Failed to start server:', err);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Router from '@koa/router';
|
|
2
|
+
|
|
3
|
+
const router = new Router();
|
|
4
|
+
|
|
5
|
+
// API 路由示例
|
|
6
|
+
router.get('/api/hello', async ctx => {
|
|
7
|
+
ctx.body = {
|
|
8
|
+
message: 'Hello from Koa + Vite!',
|
|
9
|
+
timestamp: new Date().toISOString(),
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
router.post('/api/data', async ctx => {
|
|
14
|
+
const requestData = ctx.request.body;
|
|
15
|
+
ctx.body = {
|
|
16
|
+
success: true,
|
|
17
|
+
data: requestData,
|
|
18
|
+
receivedAt: new Date().toISOString(),
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// 健康检查接口
|
|
23
|
+
router.get('/api/health', async ctx => {
|
|
24
|
+
ctx.body = {
|
|
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,79 @@
|
|
|
1
|
+
import type Koa from 'koa';
|
|
2
|
+
import serve from 'koa-static';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
|
|
6
|
+
const isDev = process.env.COZE_PROJECT_ENV !== 'PROD';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 集成 Vite 开发服务器(中间件模式)
|
|
10
|
+
* 使用动态 import 避免在生产构建时打包 vite
|
|
11
|
+
*/
|
|
12
|
+
export async function setupViteMiddleware(app: Koa) {
|
|
13
|
+
// 动态导入 vite,只在开发环境运行时加载
|
|
14
|
+
const { createServer: createViteServer } = await import('vite');
|
|
15
|
+
|
|
16
|
+
const vite = await createViteServer({
|
|
17
|
+
server: {
|
|
18
|
+
middlewareMode: true,
|
|
19
|
+
hmr: {
|
|
20
|
+
port: process.env.HMR_PORT ? parseInt(process.env.HMR_PORT) : undefined,
|
|
21
|
+
overlay: true,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
appType: 'spa',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// 将 Vite middleware 转换为 Koa middleware
|
|
28
|
+
app.use(async ctx => {
|
|
29
|
+
await new Promise<void>((resolve, reject) => {
|
|
30
|
+
vite.middlewares(ctx.req, ctx.res, (err?: Error) => {
|
|
31
|
+
if (err) {
|
|
32
|
+
reject(err);
|
|
33
|
+
} else {
|
|
34
|
+
resolve();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
console.log('🚀 Vite dev server initialized');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 设置生产环境静态文件服务
|
|
45
|
+
*/
|
|
46
|
+
export function setupStaticServer(app: Koa) {
|
|
47
|
+
// 在 CommonJS 编译后,__dirname 会自动可用
|
|
48
|
+
// 在 TypeScript 中,我们使用相对于当前文件的路径
|
|
49
|
+
const distPath = path.resolve(process.cwd(), 'dist');
|
|
50
|
+
|
|
51
|
+
if (!fs.existsSync(distPath)) {
|
|
52
|
+
console.error('❌ dist folder not found. Please run "pnpm build" first.');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 服务静态文件
|
|
57
|
+
app.use(serve(distPath));
|
|
58
|
+
|
|
59
|
+
// SPA fallback - 所有非 API 请求返回 index.html
|
|
60
|
+
app.use(async ctx => {
|
|
61
|
+
if (!ctx.path.startsWith('/api')) {
|
|
62
|
+
ctx.type = 'html';
|
|
63
|
+
ctx.body = fs.createReadStream(path.join(distPath, 'index.html'));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log('📦 Serving static files from dist/');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 根据环境设置 Vite
|
|
72
|
+
*/
|
|
73
|
+
export async function setupVite(app: Koa) {
|
|
74
|
+
if (isDev) {
|
|
75
|
+
await setupViteMiddleware(app);
|
|
76
|
+
} else {
|
|
77
|
+
setupStaticServer(app);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -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
|
|
@@ -1822,7 +1790,7 @@ const processTemplateFiles = async (options
|
|
|
1822
1790
|
|
|
1823
1791
|
|
|
1824
1792
|
) => {
|
|
1825
|
-
const { templatePath, outputPath, context, templateConfig
|
|
1793
|
+
const { templatePath, outputPath, context, templateConfig} = options;
|
|
1826
1794
|
logger.verbose('Processing template files:');
|
|
1827
1795
|
logger.verbose(` - Template path: ${templatePath}`);
|
|
1828
1796
|
logger.verbose(` - Output path: ${outputPath}`);
|
|
@@ -1854,7 +1822,7 @@ const processTemplateFiles = async (options
|
|
|
1854
1822
|
}
|
|
1855
1823
|
|
|
1856
1824
|
// 阶段 2: Dry-run - 收集所有将要写入的文件
|
|
1857
|
-
|
|
1825
|
+
await collectFilesToRender({
|
|
1858
1826
|
files,
|
|
1859
1827
|
templatePath,
|
|
1860
1828
|
context,
|
|
@@ -1862,20 +1830,7 @@ const processTemplateFiles = async (options
|
|
|
1862
1830
|
});
|
|
1863
1831
|
|
|
1864
1832
|
// 阶段 3: 冲突检测(force 为 true 时跳过)
|
|
1865
|
-
|
|
1866
|
-
const conflicts = detectFileConflicts(outputPath, filesToWrite);
|
|
1867
|
-
|
|
1868
|
-
if (conflicts.length > 0) {
|
|
1869
|
-
// 有冲突,抛出详细的错误信息
|
|
1870
|
-
const conflictList = conflicts.map(f => ` - ${f}`).join('\n');
|
|
1871
|
-
throw new Error(
|
|
1872
|
-
`File conflicts detected in output directory: ${outputPath}\n\n` +
|
|
1873
|
-
`The following files already exist and would be overwritten:\n${conflictList}\n\n` +
|
|
1874
|
-
'Please remove these files or use a different output directory.\n' +
|
|
1875
|
-
'Or use --force to overwrite existing files.',
|
|
1876
|
-
);
|
|
1877
|
-
}
|
|
1878
|
-
} else {
|
|
1833
|
+
{
|
|
1879
1834
|
logger.verbose(
|
|
1880
1835
|
' - Force mode enabled, skipping conflict detection. Existing files will be overwritten.',
|
|
1881
1836
|
);
|
|
@@ -2020,7 +1975,7 @@ const prepareOutputDirectory = (outputPath) => {
|
|
|
2020
1975
|
const execute = async (
|
|
2021
1976
|
options,
|
|
2022
1977
|
) => {
|
|
2023
|
-
const { templateName, outputPath, command
|
|
1978
|
+
const { templateName, outputPath, command} = options;
|
|
2024
1979
|
|
|
2025
1980
|
// 1. 加载模板
|
|
2026
1981
|
const { templatePath } = await loadTemplateMetadata(templateName);
|
|
@@ -2044,9 +1999,7 @@ const execute = async (
|
|
|
2044
1999
|
templatePath,
|
|
2045
2000
|
outputPath: absoluteOutputPath,
|
|
2046
2001
|
context,
|
|
2047
|
-
templateConfig
|
|
2048
|
-
force,
|
|
2049
|
-
});
|
|
2002
|
+
templateConfig});
|
|
2050
2003
|
|
|
2051
2004
|
// 7. 执行 onAfterRender 钩子
|
|
2052
2005
|
await executeAfterRenderHook(templateConfig, context, absoluteOutputPath);
|
|
@@ -2097,7 +2050,40 @@ const runPnpmInstall = (projectPath) => {
|
|
|
2097
2050
|
};
|
|
2098
2051
|
|
|
2099
2052
|
/**
|
|
2100
|
-
*
|
|
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 仓库
|
|
2101
2087
|
* 如果目录中已存在 .git,则跳过初始化
|
|
2102
2088
|
*/
|
|
2103
2089
|
const runGitInit = (projectPath) => {
|
|
@@ -2110,46 +2096,9 @@ const runGitInit = (projectPath) => {
|
|
|
2110
2096
|
return;
|
|
2111
2097
|
}
|
|
2112
2098
|
|
|
2113
|
-
const runGitCommand = (command) => {
|
|
2114
|
-
logger.info(`Executing: ${command}`);
|
|
2115
|
-
|
|
2116
|
-
const result = shelljs.exec(command, {
|
|
2117
|
-
cwd: projectPath,
|
|
2118
|
-
silent: true,
|
|
2119
|
-
});
|
|
2120
|
-
|
|
2121
|
-
// 输出命令的结果
|
|
2122
|
-
if (result.stdout) {
|
|
2123
|
-
process.stdout.write(result.stdout);
|
|
2124
|
-
}
|
|
2125
|
-
|
|
2126
|
-
if (result.stderr) {
|
|
2127
|
-
process.stderr.write(result.stderr);
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
|
-
if (result.code !== 0) {
|
|
2131
|
-
const errorMessage = [
|
|
2132
|
-
`${command} failed with exit code ${result.code}`,
|
|
2133
|
-
result.stderr ? `\nStderr:\n${result.stderr}` : '',
|
|
2134
|
-
result.stdout ? `\nStdout:\n${result.stdout}` : '',
|
|
2135
|
-
]
|
|
2136
|
-
.filter(Boolean)
|
|
2137
|
-
.join('');
|
|
2138
|
-
|
|
2139
|
-
throw new Error(errorMessage);
|
|
2140
|
-
}
|
|
2141
|
-
};
|
|
2142
|
-
|
|
2143
2099
|
try {
|
|
2144
2100
|
logger.info('\nInitializing git repository...');
|
|
2145
|
-
runGitCommand('git init');
|
|
2146
|
-
|
|
2147
|
-
logger.info('Adding files to git...');
|
|
2148
|
-
runGitCommand('git add .');
|
|
2149
|
-
|
|
2150
|
-
logger.info('Creating initial commit...');
|
|
2151
|
-
runGitCommand('git commit -m "chore: initial commit"');
|
|
2152
|
-
|
|
2101
|
+
runGitCommand('git init', projectPath);
|
|
2153
2102
|
logger.success('Git repository initialized successfully!');
|
|
2154
2103
|
} catch (error) {
|
|
2155
2104
|
// Git 初始化失败不应该导致整个流程失败
|
|
@@ -2160,6 +2109,35 @@ const runGitInit = (projectPath) => {
|
|
|
2160
2109
|
}
|
|
2161
2110
|
};
|
|
2162
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
|
+
|
|
2163
2141
|
/**
|
|
2164
2142
|
* 运行开发服务器(后台模式)
|
|
2165
2143
|
* 启动后台子进程运行开发服务器,父进程可以直接退出
|
|
@@ -2202,6 +2180,7 @@ const executeInit = async (
|
|
|
2202
2180
|
|
|
2203
2181
|
|
|
2204
2182
|
|
|
2183
|
+
|
|
2205
2184
|
,
|
|
2206
2185
|
command,
|
|
2207
2186
|
) => {
|
|
@@ -2213,6 +2192,7 @@ const executeInit = async (
|
|
|
2213
2192
|
output: outputPath,
|
|
2214
2193
|
skipInstall,
|
|
2215
2194
|
skipGit,
|
|
2195
|
+
skipCommit,
|
|
2216
2196
|
skipDev,
|
|
2217
2197
|
force,
|
|
2218
2198
|
} = options;
|
|
@@ -2258,6 +2238,12 @@ const executeInit = async (
|
|
|
2258
2238
|
timer.logPhase('Git initialization');
|
|
2259
2239
|
}
|
|
2260
2240
|
|
|
2241
|
+
// 如果没有跳过 commit,则提交初始化生成的文件
|
|
2242
|
+
if (!skipCommit) {
|
|
2243
|
+
commitChanges(absoluteOutputPath);
|
|
2244
|
+
timer.logPhase('Git commit');
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2261
2247
|
// 如果没有跳过 dev,则启动开发服务器
|
|
2262
2248
|
if (!skipDev) {
|
|
2263
2249
|
runDev(absoluteOutputPath);
|
|
@@ -2270,9 +2256,10 @@ const executeInit = async (
|
|
|
2270
2256
|
logger.info(' pnpm install');
|
|
2271
2257
|
}
|
|
2272
2258
|
if (skipGit) {
|
|
2273
|
-
logger.info(
|
|
2274
|
-
|
|
2275
|
-
|
|
2259
|
+
logger.info(' git init');
|
|
2260
|
+
}
|
|
2261
|
+
if (skipCommit) {
|
|
2262
|
+
logger.info(' git add --all && git commit -m "chore: init env"');
|
|
2276
2263
|
}
|
|
2277
2264
|
logger.info(' coze dev');
|
|
2278
2265
|
}
|
|
@@ -2299,17 +2286,19 @@ const registerCommand$1 = program => {
|
|
|
2299
2286
|
.option('-o, --output <path>', 'Output directory', process.cwd())
|
|
2300
2287
|
.option('--skip-install', 'Skip automatic pnpm install', false)
|
|
2301
2288
|
.option('--skip-git', 'Skip automatic git initialization', false)
|
|
2302
|
-
.option('--skip-dev', 'Skip automatic dev server start', false)
|
|
2303
2289
|
.option(
|
|
2304
|
-
'--
|
|
2305
|
-
'
|
|
2306
|
-
|
|
2290
|
+
'--skip-commit',
|
|
2291
|
+
'Skip automatic git commit after initialization',
|
|
2292
|
+
false,
|
|
2307
2293
|
)
|
|
2294
|
+
.option('--skip-dev', 'Skip automatic dev server start', false)
|
|
2308
2295
|
.allowUnknownOption() // 允许透传参数
|
|
2309
2296
|
.action(async (directory, options, command) => {
|
|
2310
2297
|
// 位置参数优先级高于 --output 选项
|
|
2311
2298
|
const outputPath = _nullishCoalesce(directory, () => ( options.output));
|
|
2312
|
-
|
|
2299
|
+
// Always use force mode - overwrite existing files without conflict check
|
|
2300
|
+
const force = true;
|
|
2301
|
+
await executeInit({ ...options, output: outputPath, force }, command);
|
|
2313
2302
|
});
|
|
2314
2303
|
};
|
|
2315
2304
|
|
|
@@ -2609,7 +2598,7 @@ const registerCommand = program => {
|
|
|
2609
2598
|
});
|
|
2610
2599
|
};
|
|
2611
2600
|
|
|
2612
|
-
var version = "0.0.1-alpha.
|
|
2601
|
+
var version = "0.0.1-alpha.eaa612";
|
|
2613
2602
|
var packageJson = {
|
|
2614
2603
|
version: version};
|
|
2615
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.eaa612",
|
|
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",
|
|
@@ -60,8 +61,10 @@
|
|
|
60
61
|
"@vitest/coverage-v8": "~4.0.16",
|
|
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
70
|
"vitest": "~4.0.16"
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { defuFn } from 'defu'
|
|
3
|
-
|
|
4
|
-
const inlineConfig = {
|
|
5
|
-
"nuxt": {}
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/** client **/
|
|
9
|
-
import { _replaceAppConfig } from '#app/config'
|
|
10
|
-
|
|
11
|
-
// Vite - webpack is handled directly in #app/config
|
|
12
|
-
if (import.meta.dev && !import.meta.nitro && import.meta.hot) {
|
|
13
|
-
import.meta.hot.accept((newModule) => {
|
|
14
|
-
_replaceAppConfig(newModule.default)
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
/** client-end **/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export default /*@__PURE__*/ defuFn(inlineConfig)
|