@coze-arch/cli 0.0.1-alpha.ee5d83 → 0.0.1-alpha.f626fa
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/.cozeproj/scripts/dev_run.sh +10 -10
- package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +2 -2
- package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +2 -2
- package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +45 -0
- package/lib/__templates__/expo/client/app/_layout.tsx +14 -14
- package/lib/__templates__/expo/client/app/index.tsx +1 -1
- package/lib/__templates__/expo/client/app.config.ts +4 -3
- package/lib/__templates__/expo/client/declarations.d.ts +5 -0
- package/lib/__templates__/expo/client/screens/{home → demo}/index.tsx +1 -1
- package/lib/__templates__/expo/client/scripts/install-missing-deps.js +1 -0
- package/lib/__templates__/expo/client/utils/index.ts +22 -0
- package/lib/__templates__/expo/server/build.js +21 -0
- package/lib/__templates__/expo/server/package.json +2 -2
- package/lib/__templates__/nextjs/next.config.ts +2 -2
- package/lib/__templates__/nextjs/src/app/page.tsx +2 -2
- package/lib/__templates__/vite/src/main.ts +1 -2
- package/lib/cli.js +13 -6
- package/package.json +1 -1
- package/lib/__templates__/expo/client/app/home.tsx +0 -1
- /package/lib/__templates__/expo/client/screens/{home → demo}/styles.ts +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
1
|
+
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
2
2
|
PREVIEW_DIR="${COZE_PREVIEW_DIR:-/source/preview}"
|
|
3
3
|
LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
|
|
4
4
|
LOG_FILE="$LOG_DIR/app.log"
|
|
@@ -111,14 +111,14 @@ wait_port_connectable() {
|
|
|
111
111
|
start_expo() {
|
|
112
112
|
local offline="${1:-0}"
|
|
113
113
|
|
|
114
|
-
pushd
|
|
114
|
+
pushd "$ROOT_DIR/client"
|
|
115
115
|
|
|
116
116
|
if [ "$offline" = "1" ]; then
|
|
117
117
|
( EXPO_OFFLINE=1 EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" \
|
|
118
|
-
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "
|
|
118
|
+
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$ROOT_DIR/logs/client.log" ) &
|
|
119
119
|
else
|
|
120
120
|
( EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" \
|
|
121
|
-
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "
|
|
121
|
+
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$ROOT_DIR/logs/client.log" ) &
|
|
122
122
|
fi
|
|
123
123
|
EXPO_PID=$!
|
|
124
124
|
disown $EXPO_PID 2>/dev/null || true
|
|
@@ -129,7 +129,7 @@ start_expo() {
|
|
|
129
129
|
detect_expo_fetch_failed() {
|
|
130
130
|
local timeout="${1:-8}"
|
|
131
131
|
local waited=0
|
|
132
|
-
local log_file="logs/client.log"
|
|
132
|
+
local log_file="$ROOT_DIR/logs/client.log"
|
|
133
133
|
while [ "$waited" -lt "$timeout" ]; do
|
|
134
134
|
if [ -f "$log_file" ] && grep -q "TypeError: fetch failed" "$log_file" 2>/dev/null; then
|
|
135
135
|
return 0
|
|
@@ -159,15 +159,15 @@ check_command "pnpm"
|
|
|
159
159
|
check_command "lsof"
|
|
160
160
|
check_command "bash"
|
|
161
161
|
|
|
162
|
-
echo "
|
|
163
|
-
mkdir -p logs
|
|
162
|
+
echo "准备日志目录:$ROOT_DIR/logs"
|
|
163
|
+
mkdir -p "$ROOT_DIR/logs"
|
|
164
164
|
# 端口占用预检查与处理
|
|
165
165
|
ensure_port SERVER_PORT "$SERVER_PORT"
|
|
166
166
|
ensure_port EXPO_PORT "$EXPO_PORT"
|
|
167
167
|
|
|
168
168
|
echo "==================== 启动 server 服务 ===================="
|
|
169
|
-
echo "正在执行:
|
|
170
|
-
(
|
|
169
|
+
echo "正在执行:pnpm run dev (server)"
|
|
170
|
+
( pushd "$ROOT_DIR/server" > /dev/null && SERVER_PORT="$SERVER_PORT" nohup pnpm run dev; popd > /dev/null ) &
|
|
171
171
|
SERVER_PID=$!
|
|
172
172
|
disown $SERVER_PID 2>/dev/null || true
|
|
173
173
|
if [ -z "${SERVER_PID}" ]; then
|
|
@@ -181,7 +181,7 @@ start_expo 0
|
|
|
181
181
|
if detect_expo_fetch_failed 8; then
|
|
182
182
|
echo "Expo 启动检测到网络错误:TypeError: fetch failed,启用离线模式重试"
|
|
183
183
|
if [ -n "${EXPO_PID}" ]; then kill -9 "$EXPO_PID" 2>/dev/null || true; fi
|
|
184
|
-
: > logs/client.log
|
|
184
|
+
: > "$ROOT_DIR/logs/client.log"
|
|
185
185
|
start_expo 1
|
|
186
186
|
fi
|
|
187
187
|
# 输出以下环境变量,确保 Expo 项目能正确连接到 Server 服务
|
|
@@ -40,8 +40,8 @@ fi
|
|
|
40
40
|
info "==================== 依赖安装完成!====================\n"
|
|
41
41
|
|
|
42
42
|
info "==================== dist打包 ===================="
|
|
43
|
-
info "开始执行:
|
|
44
|
-
(
|
|
43
|
+
info "开始执行:pnpm run build (server)"
|
|
44
|
+
(pushd "$ROOT_DIR/server" > /dev/null && pnpm run build; popd > /dev/null) || error "dist打包失败"
|
|
45
45
|
info "==================== dist打包完成!====================\n"
|
|
46
46
|
|
|
47
47
|
info "下一步:执行 ./prod_run.sh 启动服务"
|
|
@@ -29,6 +29,6 @@ check_command() {
|
|
|
29
29
|
check_command "pnpm"
|
|
30
30
|
check_command "npm"
|
|
31
31
|
|
|
32
|
-
info "开始执行:
|
|
33
|
-
(
|
|
32
|
+
info "开始执行:pnpm run start (server)"
|
|
33
|
+
(pushd "$ROOT_DIR/server" > /dev/null && PORT="$PORT" pnpm run start; popd > /dev/null) || error "服务启动失败"
|
|
34
34
|
info "服务启动完成!\n"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
4
|
+
SERVER_DIR="$ROOT_DIR/server"
|
|
5
|
+
LOG_DIR="$ROOT_DIR/logs"
|
|
6
|
+
LOG_FILE="$LOG_DIR/server.log"
|
|
7
|
+
SERVER_PORT="${SERVER_PORT:-9091}"
|
|
8
|
+
|
|
9
|
+
mkdir -p "$LOG_DIR"
|
|
10
|
+
|
|
11
|
+
pipe_to_log() {
|
|
12
|
+
local source="${1:-SERVER}"
|
|
13
|
+
local raw_log="${2:-}"
|
|
14
|
+
local line
|
|
15
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
16
|
+
if [ -n "$raw_log" ]; then
|
|
17
|
+
echo "$line" >> "$raw_log"
|
|
18
|
+
fi
|
|
19
|
+
line=$(echo "[$source] $line" | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\x1b\[[0-9;]*m//g')
|
|
20
|
+
echo "$line"
|
|
21
|
+
done
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
kill_old_server() {
|
|
25
|
+
if command -v lsof &> /dev/null; then
|
|
26
|
+
local pids
|
|
27
|
+
pids=$(lsof -t -i tcp:"$SERVER_PORT" -sTCP:LISTEN 2>/dev/null || true)
|
|
28
|
+
if [ -n "$pids" ]; then
|
|
29
|
+
echo "正在关闭旧的 server 进程:$pids"
|
|
30
|
+
kill -9 $pids 2>/dev/null || echo "关闭进程失败:$pids"
|
|
31
|
+
sleep 1
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
echo "==================== Server Dev Run ===================="
|
|
37
|
+
echo "Server 目录:$SERVER_DIR"
|
|
38
|
+
echo "Server 端口:$SERVER_PORT"
|
|
39
|
+
echo "日志文件:$LOG_FILE"
|
|
40
|
+
|
|
41
|
+
kill_old_server
|
|
42
|
+
|
|
43
|
+
echo "启动 server 服务..."
|
|
44
|
+
cd "$SERVER_DIR"
|
|
45
|
+
NODE_ENV=development PORT="$SERVER_PORT" npx tsx ./src/index.ts 2>&1 | pipe_to_log "SERVER" "$LOG_FILE"
|
|
@@ -14,20 +14,20 @@ LogBox.ignoreLogs([
|
|
|
14
14
|
export default function RootLayout() {
|
|
15
15
|
return (
|
|
16
16
|
<AuthProvider>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
18
|
+
<StatusBar style="dark"></StatusBar>
|
|
19
|
+
<Stack screenOptions={{
|
|
20
|
+
// 设置所有页面的切换动画为从右侧滑入,适用于iOS 和 Android
|
|
21
|
+
animation: 'slide_from_right',
|
|
22
|
+
gestureEnabled: true,
|
|
23
|
+
gestureDirection: 'horizontal',
|
|
24
|
+
// 隐藏自带的头部
|
|
25
|
+
headerShown: false
|
|
26
|
+
}}>
|
|
27
|
+
<Stack.Screen name="index" options={{ title: "" }} />
|
|
28
|
+
</Stack>
|
|
29
|
+
<Toast />
|
|
30
|
+
</GestureHandlerRootView>
|
|
31
31
|
</AuthProvider>
|
|
32
32
|
);
|
|
33
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from '
|
|
1
|
+
export { default } from '@/screens/demo';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ExpoConfig, ConfigContext } from 'expo/config';
|
|
2
2
|
|
|
3
|
-
const appName =
|
|
4
|
-
const
|
|
3
|
+
const appName = process.env.EXPO_PUBLIC_COZE_PROJECT_NAME || '应用';
|
|
4
|
+
const projectId = process.env.EXPO_PUBLIC_COZE_PROJECT_ID;
|
|
5
|
+
const slugAppName = projectId ? `app${projectId}` : 'myapp';
|
|
5
6
|
|
|
6
7
|
export default ({ config }: ConfigContext): ExpoConfig => {
|
|
7
8
|
return {
|
|
@@ -22,7 +23,7 @@ export default ({ config }: ConfigContext): ExpoConfig => {
|
|
|
22
23
|
"foregroundImage": "./assets/images/adaptive-icon.png",
|
|
23
24
|
"backgroundColor": "#ffffff"
|
|
24
25
|
},
|
|
25
|
-
"package":
|
|
26
|
+
"package": `com.anonymous.x${projectId || '0'}`
|
|
26
27
|
},
|
|
27
28
|
"web": {
|
|
28
29
|
"bundler": "metro",
|
|
@@ -5,7 +5,7 @@ import { useTheme } from '@/hooks/useTheme';
|
|
|
5
5
|
import { Screen } from '@/components/Screen';
|
|
6
6
|
import { styles } from './styles';
|
|
7
7
|
|
|
8
|
-
export default function
|
|
8
|
+
export default function DemoPage() {
|
|
9
9
|
const { theme, isDark } = useTheme();
|
|
10
10
|
|
|
11
11
|
return (
|
|
@@ -1,9 +1,31 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
1
2
|
import dayjs from 'dayjs';
|
|
2
3
|
import utc from 'dayjs/plugin/utc';
|
|
3
4
|
dayjs.extend(utc);
|
|
4
5
|
|
|
5
6
|
const API_BASE = (process.env.EXPO_PUBLIC_API_BASE ?? '').replace(/\/$/, '');
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* 创建跨平台兼容的文件对象,用于 FormData.append()
|
|
10
|
+
* - Web 端返回 File 对象
|
|
11
|
+
* - 移动端返回 { uri, type, name } 对象(RN fetch 会自动处理)
|
|
12
|
+
* @param fileUri Expo 媒体库(如 expo-image-picker、expo-camera)返回的 uri
|
|
13
|
+
* @param fileName 上传时的文件名,如 'photo.jpg'
|
|
14
|
+
* @param mimeType 文件 MIME 类型,如 'image/jpeg'、'audio/mpeg'
|
|
15
|
+
*/
|
|
16
|
+
export async function createFormDataFile(
|
|
17
|
+
fileUri: string,
|
|
18
|
+
fileName: string,
|
|
19
|
+
mimeType: string
|
|
20
|
+
): Promise<File | { uri: string; type: string; name: string }> {
|
|
21
|
+
if (Platform.OS === 'web') {
|
|
22
|
+
const response = await fetch(fileUri);
|
|
23
|
+
const blob = await response.blob();
|
|
24
|
+
return new File([blob], fileName, { type: mimeType });
|
|
25
|
+
}
|
|
26
|
+
return { uri: fileUri, type: mimeType, name: fileName };
|
|
27
|
+
}
|
|
28
|
+
|
|
7
29
|
/**
|
|
8
30
|
* 构建文件或图片完整的URL
|
|
9
31
|
* @param url 相对或绝对路径
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as esbuild from 'esbuild';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const pkg = require('./package.json');
|
|
6
|
+
const dependencies = pkg.dependencies || {};
|
|
7
|
+
const externalList = Object.keys(dependencies).filter(dep => dep !== 'dayjs');
|
|
8
|
+
try {
|
|
9
|
+
await esbuild.build({
|
|
10
|
+
entryPoints: ['src/index.ts'],
|
|
11
|
+
bundle: true,
|
|
12
|
+
platform: 'node',
|
|
13
|
+
format: 'esm',
|
|
14
|
+
outdir: 'dist',
|
|
15
|
+
external: externalList,
|
|
16
|
+
});
|
|
17
|
+
console.log('⚡ Build complete!');
|
|
18
|
+
} catch (e) {
|
|
19
|
+
console.error(e);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"preinstall": "npx only-allow pnpm",
|
|
7
|
-
"dev": "
|
|
8
|
-
"build": "
|
|
7
|
+
"dev": "bash ../.cozeproj/scripts/server_dev_run.sh",
|
|
8
|
+
"build": "node build.js",
|
|
9
9
|
"start": "NODE_ENV=production PORT=${PORT:-5000} node dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
@@ -2,14 +2,14 @@ import type { NextConfig } from 'next';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
4
|
const nextConfig: NextConfig = {
|
|
5
|
-
outputFileTracingRoot: path.resolve(__dirname, '../../'),
|
|
5
|
+
// outputFileTracingRoot: path.resolve(__dirname, '../../'),
|
|
6
6
|
/* config options here */
|
|
7
7
|
allowedDevOrigins: ['*.dev.coze.site'],
|
|
8
8
|
images: {
|
|
9
9
|
remotePatterns: [
|
|
10
10
|
{
|
|
11
11
|
protocol: 'https',
|
|
12
|
-
hostname: '
|
|
12
|
+
hostname: 'lf-coze-web-cdn.coze.cn',
|
|
13
13
|
pathname: '/**',
|
|
14
14
|
},
|
|
15
15
|
],
|
|
@@ -15,11 +15,11 @@ export default function Home() {
|
|
|
15
15
|
{/* 头部:Logo 和 产品名称 */}
|
|
16
16
|
<div className="flex items-center gap-3">
|
|
17
17
|
<Image
|
|
18
|
-
|
|
19
|
-
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/hkpzboz/coze_logo.png"
|
|
18
|
+
src="https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/favicon.svg"
|
|
20
19
|
alt="扣子编程 Logo"
|
|
21
20
|
width={40}
|
|
22
21
|
height={40}
|
|
22
|
+
unoptimized
|
|
23
23
|
/>
|
|
24
24
|
<span className="text-xl font-bold tracking-tight text-foreground dark:text-foreground">
|
|
25
25
|
扣子编程
|
|
@@ -13,8 +13,7 @@ export function initApp(): void {
|
|
|
13
13
|
<!-- 头部:Logo 和 产品名称 -->
|
|
14
14
|
<div class="flex items-center gap-3">
|
|
15
15
|
<img
|
|
16
|
-
|
|
17
|
-
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/hkpzboz/coze_logo.png"
|
|
16
|
+
src="https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/favicon.svg"
|
|
18
17
|
alt="扣子编程 Logo"
|
|
19
18
|
width="40"
|
|
20
19
|
height="40"
|
package/lib/cli.js
CHANGED
|
@@ -1748,13 +1748,20 @@ const runGitInit = (projectPath) => {
|
|
|
1748
1748
|
/**
|
|
1749
1749
|
* 运行开发服务器(后台模式)
|
|
1750
1750
|
* 启动后台子进程运行开发服务器,父进程可以直接退出
|
|
1751
|
+
* 使用 CLI 自己的 dev 命令(定义在 run.ts)而不是直接运行 npm run dev
|
|
1751
1752
|
*/
|
|
1752
|
-
const
|
|
1753
|
+
const runDev = (projectPath) => {
|
|
1753
1754
|
logger.info('\nStarting development server in background...');
|
|
1754
|
-
|
|
1755
|
+
|
|
1756
|
+
// 获取当前 CLI 的可执行文件路径
|
|
1757
|
+
// process.argv[0] 是 node,process.argv[1] 是 CLI 入口文件
|
|
1758
|
+
const cliPath = process.argv[1];
|
|
1759
|
+
|
|
1760
|
+
logger.info(`Executing: ${cliPath} dev in ${projectPath}`);
|
|
1755
1761
|
|
|
1756
1762
|
// 使用通用的后台执行函数启动开发服务器
|
|
1757
|
-
|
|
1763
|
+
// 调用 CLI 自己的 dev 命令
|
|
1764
|
+
const pid = spawnDetached(process.argv[0], [cliPath, 'dev'], {
|
|
1758
1765
|
cwd: projectPath,
|
|
1759
1766
|
verbose: false, // 不输出额外的进程信息,由 logger 统一处理
|
|
1760
1767
|
});
|
|
@@ -1830,7 +1837,7 @@ const executeInit = async (
|
|
|
1830
1837
|
|
|
1831
1838
|
// 如果没有跳过 dev,则启动开发服务器
|
|
1832
1839
|
if (!skipDev) {
|
|
1833
|
-
|
|
1840
|
+
runDev(absoluteOutputPath);
|
|
1834
1841
|
timer.logPhase('Dev server startup');
|
|
1835
1842
|
} else {
|
|
1836
1843
|
// 只有跳过 dev 时才显示 Next steps
|
|
@@ -1844,7 +1851,7 @@ const executeInit = async (
|
|
|
1844
1851
|
' git init && git add . && git commit -m "initial commit"',
|
|
1845
1852
|
);
|
|
1846
1853
|
}
|
|
1847
|
-
logger.info('
|
|
1854
|
+
logger.info(' coze dev');
|
|
1848
1855
|
}
|
|
1849
1856
|
|
|
1850
1857
|
// 输出总耗时
|
|
@@ -1878,7 +1885,7 @@ const registerCommand = program => {
|
|
|
1878
1885
|
});
|
|
1879
1886
|
};
|
|
1880
1887
|
|
|
1881
|
-
var version = "0.0.1-alpha.
|
|
1888
|
+
var version = "0.0.1-alpha.f626fa";
|
|
1882
1889
|
var packageJson = {
|
|
1883
1890
|
version: version};
|
|
1884
1891
|
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from '@/screens/home'
|
|
File without changes
|