@coze-arch/cli 0.0.1-alpha.b6f2c1 → 0.0.1-alpha.bcc7d9

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.
Files changed (46) hide show
  1. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +22 -14
  2. package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +2 -2
  3. package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +2 -2
  4. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +20 -2
  5. package/lib/__templates__/expo/README.md +2 -21
  6. package/lib/__templates__/expo/client/app/+not-found.tsx +30 -0
  7. package/lib/__templates__/expo/client/app/_layout.tsx +11 -8
  8. package/lib/__templates__/expo/client/app.config.ts +2 -2
  9. package/lib/__templates__/expo/client/components/Screen.tsx +1 -17
  10. package/lib/__templates__/expo/client/components/ThemedView.tsx +1 -2
  11. package/lib/__templates__/expo/client/constants/theme.ts +21 -698
  12. package/lib/__templates__/expo/client/declarations.d.ts +5 -0
  13. package/lib/__templates__/expo/client/eslint.config.mjs +17 -10
  14. package/lib/__templates__/expo/client/hooks/{useColorScheme.ts → useColorScheme.tsx} +20 -6
  15. package/lib/__templates__/expo/client/hooks/useSafeRouter.ts +152 -0
  16. package/lib/__templates__/expo/client/hooks/useTheme.ts +26 -6
  17. package/lib/__templates__/expo/client/package.json +2 -1
  18. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +1 -0
  19. package/lib/__templates__/expo/client/utils/index.ts +22 -0
  20. package/lib/__templates__/expo/eslint-plugins/fontawesome6/index.js +9 -0
  21. package/lib/__templates__/expo/eslint-plugins/fontawesome6/names.js +1889 -0
  22. package/lib/__templates__/expo/eslint-plugins/fontawesome6/rule.js +174 -0
  23. package/lib/__templates__/expo/eslint-plugins/fontawesome6/v5-only-names.js +388 -0
  24. package/lib/__templates__/expo/eslint-plugins/reanimated/index.js +9 -0
  25. package/lib/__templates__/expo/eslint-plugins/reanimated/rule.js +88 -0
  26. package/lib/__templates__/expo/package.json +3 -0
  27. package/lib/__templates__/expo/patches/expo@54.0.32.patch +28 -0
  28. package/lib/__templates__/expo/pnpm-lock.yaml +1921 -1842
  29. package/lib/__templates__/expo/server/build.js +21 -0
  30. package/lib/__templates__/expo/server/package.json +1 -1
  31. package/lib/__templates__/expo/server/src/index.ts +2 -1
  32. package/lib/__templates__/expo/server/tsconfig.json +2 -2
  33. package/lib/__templates__/nextjs/.babelrc +15 -0
  34. package/lib/__templates__/nextjs/next.config.ts +2 -2
  35. package/lib/__templates__/nextjs/package.json +9 -1
  36. package/lib/__templates__/nextjs/pnpm-lock.yaml +2485 -1714
  37. package/lib/__templates__/nextjs/src/app/layout.tsx +5 -3
  38. package/lib/__templates__/nextjs/src/app/page.tsx +2 -2
  39. package/lib/__templates__/nextjs/template.config.js +5 -5
  40. package/lib/__templates__/vite/package.json +6 -1
  41. package/lib/__templates__/vite/pnpm-lock.yaml +504 -982
  42. package/lib/__templates__/vite/src/main.ts +1 -2
  43. package/lib/__templates__/vite/template.config.js +6 -4
  44. package/lib/cli.js +523 -99
  45. package/package.json +1 -1
  46. package/lib/__templates__/expo/client/app/demo.tsx +0 -1
@@ -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"
@@ -15,13 +15,14 @@ EXPO_PORT="5000"
15
15
  WEB_URL="${COZE_PROJECT_DOMAIN_DEFAULT:-http://127.0.0.1:${SERVER_PORT}}"
16
16
  ASSUME_YES="1"
17
17
  EXPO_PUBLIC_BACKEND_BASE_URL="${EXPO_PUBLIC_BACKEND_BASE_URL:-$WEB_URL}"
18
-
18
+ EXPO_PUBLIC_COZE_PROJECT_ID="${COZE_PROJECT_ID:-}"
19
19
 
20
20
  EXPO_PACKAGER_PROXY_URL="${EXPO_PUBLIC_BACKEND_BASE_URL}"
21
- export EXPO_PUBLIC_BACKEND_BASE_URL EXPO_PACKAGER_PROXY_URL
21
+ export EXPO_PUBLIC_BACKEND_BASE_URL EXPO_PACKAGER_PROXY_URL EXPO_PUBLIC_COZE_PROJECT_ID
22
22
  # 运行时变量(为避免 set -u 的未绑定错误,预置为空)
23
23
  SERVER_PID=""
24
24
  EXPO_PID=""
25
+
25
26
  # ==================== 工具函数 ====================
26
27
  check_command() {
27
28
  if ! command -v "$1" &> /dev/null; then
@@ -111,14 +112,14 @@ wait_port_connectable() {
111
112
  start_expo() {
112
113
  local offline="${1:-0}"
113
114
 
114
- pushd ./client
115
+ pushd "$ROOT_DIR/client"
115
116
 
116
117
  if [ "$offline" = "1" ]; then
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" "../logs/client.log" ) &
118
+ ( 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" EXPO_PUBLIC_COZE_PROJECT_ID="$EXPO_PUBLIC_COZE_PROJECT_ID" \
119
+ nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$ROOT_DIR/logs/client.log" ) &
119
120
  else
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" "../logs/client.log" ) &
121
+ ( EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" EXPO_PUBLIC_COZE_PROJECT_ID="$EXPO_PUBLIC_COZE_PROJECT_ID" \
122
+ nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$ROOT_DIR/logs/client.log" ) &
122
123
  fi
123
124
  EXPO_PID=$!
124
125
  disown $EXPO_PID 2>/dev/null || true
@@ -129,7 +130,7 @@ start_expo() {
129
130
  detect_expo_fetch_failed() {
130
131
  local timeout="${1:-8}"
131
132
  local waited=0
132
- local log_file="logs/client.log"
133
+ local log_file="$ROOT_DIR/logs/client.log"
133
134
  while [ "$waited" -lt "$timeout" ]; do
134
135
  if [ -f "$log_file" ] && grep -q "TypeError: fetch failed" "$log_file" 2>/dev/null; then
135
136
  return 0
@@ -150,6 +151,12 @@ if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
150
151
  python "$PREVIEW_DIR/pre_install.py" || echo "pre_install.py 执行失败"
151
152
  fi
152
153
 
154
+ echo "检查根目录 post_install.py"
155
+ if [ -f "$PREVIEW_DIR/post_install.py" ]; then
156
+ echo "执行:python $PREVIEW_DIR/post_install.py"
157
+ python "$PREVIEW_DIR/post_install.py" || echo "post_install.py 执行失败"
158
+ fi
159
+
153
160
  echo "==================== 开始启动 ===================="
154
161
  echo "开始执行服务启动脚本(start_dev.sh)..."
155
162
  echo "正在检查依赖命令和目录是否存在..."
@@ -159,15 +166,15 @@ check_command "pnpm"
159
166
  check_command "lsof"
160
167
  check_command "bash"
161
168
 
162
- echo "准备日志目录:logs"
163
- mkdir -p logs
169
+ echo "准备日志目录:$ROOT_DIR/logs"
170
+ mkdir -p "$ROOT_DIR/logs"
164
171
  # 端口占用预检查与处理
165
172
  ensure_port SERVER_PORT "$SERVER_PORT"
166
173
  ensure_port EXPO_PORT "$EXPO_PORT"
167
174
 
168
175
  echo "==================== 启动 server 服务 ===================="
169
- echo "正在执行:npm run dev"
170
- ( PORT="$SERVER_PORT" nohup npm run dev --prefix ./server 2>&1 | pipe_to_log "SERVER" "logs/server.log" ) &
176
+ echo "正在执行:pnpm run dev (server)"
177
+ ( pushd "$ROOT_DIR/server" > /dev/null && SERVER_PORT="$SERVER_PORT" nohup pnpm run dev; popd > /dev/null ) &
171
178
  SERVER_PID=$!
172
179
  disown $SERVER_PID 2>/dev/null || true
173
180
  if [ -z "${SERVER_PID}" ]; then
@@ -181,13 +188,14 @@ start_expo 0
181
188
  if detect_expo_fetch_failed 8; then
182
189
  echo "Expo 启动检测到网络错误:TypeError: fetch failed,启用离线模式重试"
183
190
  if [ -n "${EXPO_PID}" ]; then kill -9 "$EXPO_PID" 2>/dev/null || true; fi
184
- : > logs/client.log
191
+ : > "$ROOT_DIR/logs/client.log"
185
192
  start_expo 1
186
193
  fi
187
194
  # 输出以下环境变量,确保 Expo 项目能正确连接到 Server 服务
188
195
  echo "Expo 环境变量配置:"
189
196
  echo "EXPO_PUBLIC_BACKEND_BASE_URL=${EXPO_PUBLIC_BACKEND_BASE_URL}"
190
197
  echo "EXPO_PACKAGER_PROXY_URL=${EXPO_PACKAGER_PROXY_URL}"
198
+ echo "EXPO_PUBLIC_COZE_PROJECT_ID=${EXPO_PUBLIC_COZE_PROJECT_ID}"
191
199
  if [ -z "${EXPO_PID}" ]; then
192
200
  echo "无法获取 Expo 后台进程 PID"
193
201
  fi
@@ -40,8 +40,8 @@ fi
40
40
  info "==================== 依赖安装完成!====================\n"
41
41
 
42
42
  info "==================== dist打包 ===================="
43
- info "开始执行:npm run build --prefix server"
44
- (cd "$ROOT_DIR" && npm run build --prefix ./server) || error "dist打包失败"
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 "开始执行:npm run start"
33
- (cd "$ROOT_DIR" && PORT="$PORT" npm run start --prefix ./server) || error "服务启动失败"
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"
@@ -2,7 +2,24 @@
2
2
 
3
3
  ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
4
4
  SERVER_DIR="$ROOT_DIR/server"
5
- SERVER_PORT="9091"
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
+ }
6
23
 
7
24
  kill_old_server() {
8
25
  if command -v lsof &> /dev/null; then
@@ -19,9 +36,10 @@ kill_old_server() {
19
36
  echo "==================== Server Dev Run ===================="
20
37
  echo "Server 目录:$SERVER_DIR"
21
38
  echo "Server 端口:$SERVER_PORT"
39
+ echo "日志文件:$LOG_FILE"
22
40
 
23
41
  kill_old_server
24
42
 
25
43
  echo "启动 server 服务..."
26
44
  cd "$SERVER_DIR"
27
- NODE_ENV=development PORT="$SERVER_PORT" npx tsx ./src/index.ts
45
+ NODE_ENV=development PORT="$SERVER_PORT" npx tsx ./src/index.ts 2>&1 | pipe_to_log "SERVER" "$LOG_FILE"
@@ -26,6 +26,8 @@
26
26
  │ │ └── Screen.tsx # 页面容器组件(必用)
27
27
  │ ├── hooks/ # 自定义 Hooks
28
28
  │ ├── contexts/ # React Context 代码
29
+ │ ├── constants/ # 常量定义(如主题配置)
30
+ │ ├── utils/ # 工具函数
29
31
  │ ├── assets/ # 静态资源
30
32
  | └── package.json # Expo 应用 package.json
31
33
  ├── package.json
@@ -63,27 +65,6 @@ import { Screen } from '@/components/Screen';
63
65
  import { Screen } from '../../../components/Screen';
64
66
  ```
65
67
 
66
- ## Server 开发规范
67
-
68
- 服务端是一个 Node.js 项目,基于 ESM 规范开发,在引用相对路径时,需要加上明确的后缀名
69
-
70
- 错误的做法
71
-
72
- ```ts
73
- import file from './file'
74
- import folder from './folder'
75
- import isoWeek from 'dayjs/plugin/isoWeek'
76
- ```
77
-
78
- 正确的做法
79
-
80
- ```ts
81
- import file from './file.ts'
82
- import folder from './folder/index.ts'
83
- // 如果是来自 npm 包某个具体路径的引用,如果实际路径为 .js,则使用 .js 后缀
84
- import isoWeek from 'dayjs/plugin/isoWeek.js'
85
- ```
86
-
87
68
  ## 本地开发
88
69
 
89
70
  运行 coze dev 可以同时启动前端和后端服务,如果端口已占用,该命令会先杀掉占用端口的进程再启动,也可以用来重启前端和后端服务
@@ -0,0 +1,30 @@
1
+ import { View, Text, StyleSheet } from 'react-native';
2
+ import { Link } from 'expo-router';
3
+ import { useTheme } from '@/hooks/useTheme';
4
+ import { Spacing } from '@/constants/theme';
5
+
6
+ export default function NotFoundScreen() {
7
+ const { theme } = useTheme();
8
+
9
+ return (
10
+ <View style={[styles.container, { backgroundColor: theme.backgroundRoot }]}>
11
+ <Text>
12
+ 页面不存在
13
+ </Text>
14
+ <Link href="/" style={[styles.gohome]}>
15
+ 返回首页
16
+ </Link>
17
+ </View>
18
+ );
19
+ }
20
+
21
+ const styles = StyleSheet.create({
22
+ container: {
23
+ flex: 1,
24
+ justifyContent: 'center',
25
+ alignItems: 'center',
26
+ },
27
+ gohome: {
28
+ marginTop: Spacing['2xl'],
29
+ },
30
+ });
@@ -5,6 +5,7 @@ import { StatusBar } from 'expo-status-bar';
5
5
  import { LogBox } from 'react-native';
6
6
  import Toast from 'react-native-toast-message';
7
7
  import { AuthProvider } from "@/contexts/AuthContext";
8
+ import { ColorSchemeProvider } from '@/hooks/useColorScheme';
8
9
 
9
10
  LogBox.ignoreLogs([
10
11
  "TurboModuleRegistry.getEnforcing(...): 'RNMapsAirModule' could not be found",
@@ -14,20 +15,22 @@ LogBox.ignoreLogs([
14
15
  export default function RootLayout() {
15
16
  return (
16
17
  <AuthProvider>
17
- <GestureHandlerRootView style={{ flex: 1 }}>
18
+ <ColorSchemeProvider>
19
+ <GestureHandlerRootView style={{ flex: 1 }}>
18
20
  <StatusBar style="dark"></StatusBar>
19
21
  <Stack screenOptions={{
20
- // 设置所有页面的切换动画为从右侧滑入,适用于iOS 和 Android
21
- animation: 'slide_from_right',
22
- gestureEnabled: true,
23
- gestureDirection: 'horizontal',
24
- // 隐藏自带的头部
25
- headerShown: false
22
+ // 设置所有页面的切换动画为从右侧滑入,适用于iOS 和 Android
23
+ animation: 'slide_from_right',
24
+ gestureEnabled: true,
25
+ gestureDirection: 'horizontal',
26
+ // 隐藏自带的头部
27
+ headerShown: false
26
28
  }}>
27
29
  <Stack.Screen name="index" options={{ title: "" }} />
28
30
  </Stack>
29
31
  <Toast />
30
- </GestureHandlerRootView>
32
+ </GestureHandlerRootView>
33
+ </ColorSchemeProvider>
31
34
  </AuthProvider>
32
35
  );
33
36
  }
@@ -1,7 +1,7 @@
1
1
  import { ExpoConfig, ConfigContext } from 'expo/config';
2
2
 
3
- const appName = process.env.EXPO_PUBLIC_COZE_PROJECT_NAME || '应用';
4
- const projectId = process.env.EXPO_PUBLIC_COZE_PROJECT_ID;
3
+ const appName = process.env.COZE_PROJECT_NAME || process.env.EXPO_PUBLIC_COZE_PROJECT_NAME || '应用';
4
+ const projectId = process.env.COZE_PROJECT_ID || process.env.EXPO_PUBLIC_COZE_PROJECT_ID;
5
5
  const slugAppName = projectId ? `app${projectId}` : 'myapp';
6
6
 
7
7
  export default ({ config }: ConfigContext): ExpoConfig => {
@@ -197,26 +197,10 @@ export const Screen = ({
197
197
  // 强制禁用 iOS 自动调整内容区域,完全由手动 padding 控制,消除系统自动计算带来的多余空白
198
198
  const contentInsetBehaviorIOS = 'never';
199
199
 
200
- // 1. 外层容器样式
201
- // 负责:背景色、Top/Left/Right 安全区、以及非滚动模式下的 Bottom 安全区
202
- const childArray = React.Children.toArray(children);
203
- let firstChild: React.ReactElement<any, any> | null = null;
204
- for (let i = 0; i < childArray.length; i++) {
205
- const el = childArray[i];
206
- if (React.isValidElement(el)) { firstChild = el as React.ReactElement<any, any>; break; }
207
- }
208
- const firstChildHasInlinePaddingTop = (() => {
209
- if (!firstChild) return false;
210
- const st: any = (firstChild as any).props?.style;
211
- const arr = Array.isArray(st) ? st : st ? [st] : [];
212
- return arr.some((s) => s && typeof s === 'object' && typeof (s as any).paddingTop === 'number' && (s as any).paddingTop > 10);
213
- })();
214
- const applyTopInset = hasTop && !firstChildHasInlinePaddingTop;
215
-
216
200
  const wrapperStyle: ViewStyle = {
217
201
  flex: 1,
218
202
  backgroundColor,
219
- paddingTop: applyTopInset ? insets.top : 0,
203
+ paddingTop: hasTop ? insets.top : 0,
220
204
  paddingLeft: hasLeft ? insets.left : 0,
221
205
  paddingRight: hasRight ? insets.right : 0,
222
206
  // 当页面不使用外层 ScrollView 时(子树本身可滚动),由外层 View 负责底部安全区
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { View, ViewProps, ViewStyle } from 'react-native';
3
3
  import { useTheme } from '@/hooks/useTheme';
4
4
 
5
- type BackgroundLevel = 'root' | 'default' | 'secondary' | 'tertiary';
5
+ type BackgroundLevel = 'root' | 'default' | 'tertiary';
6
6
 
7
7
  interface ThemedViewProps extends ViewProps {
8
8
  level?: BackgroundLevel;
@@ -12,7 +12,6 @@ interface ThemedViewProps extends ViewProps {
12
12
  const backgroundMap: Record<BackgroundLevel, string> = {
13
13
  root: 'backgroundRoot',
14
14
  default: 'backgroundDefault',
15
- secondary: 'backgroundSecondary',
16
15
  tertiary: 'backgroundTertiary',
17
16
  };
18
17