@coze-arch/cli 0.0.1-alpha.9f719c → 0.0.1-alpha.a166f2

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 (136) hide show
  1. package/lib/__templates__/expo/.coze +3 -3
  2. package/lib/__templates__/expo/.cozeproj/scripts/dev_build.sh +46 -0
  3. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +229 -0
  4. package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +2 -2
  5. package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +3 -4
  6. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +46 -0
  7. package/lib/__templates__/expo/README.md +68 -7
  8. package/lib/__templates__/expo/_gitignore +1 -1
  9. package/lib/__templates__/expo/_npmrc +2 -4
  10. package/lib/__templates__/expo/client/app/+not-found.tsx +15 -64
  11. package/lib/__templates__/expo/client/app/_layout.tsx +15 -12
  12. package/lib/__templates__/expo/client/app/index.tsx +1 -0
  13. package/lib/__templates__/expo/client/app.config.ts +76 -0
  14. package/lib/__templates__/expo/client/components/Screen.tsx +1 -17
  15. package/lib/__templates__/expo/client/components/ThemedText.tsx +33 -0
  16. package/lib/__templates__/expo/client/components/ThemedView.tsx +37 -0
  17. package/lib/__templates__/expo/client/constants/theme.ts +116 -67
  18. package/lib/__templates__/expo/client/declarations.d.ts +5 -0
  19. package/lib/__templates__/expo/{eslint.config.mjs → client/eslint.config.mjs} +33 -10
  20. package/lib/__templates__/expo/client/hooks/useColorScheme.tsx +48 -0
  21. package/lib/__templates__/expo/client/hooks/useSafeRouter.ts +152 -0
  22. package/lib/__templates__/expo/client/hooks/useTheme.ts +26 -6
  23. package/lib/__templates__/expo/client/metro.config.js +124 -0
  24. package/lib/__templates__/expo/client/package.json +95 -0
  25. package/lib/__templates__/expo/client/screens/demo/index.tsx +25 -0
  26. package/lib/__templates__/expo/client/screens/demo/styles.ts +28 -0
  27. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +1 -0
  28. package/lib/__templates__/expo/client/tsconfig.json +24 -0
  29. package/lib/__templates__/expo/client/utils/index.ts +22 -0
  30. package/lib/__templates__/expo/eslint-plugins/fontawesome6/index.js +9 -0
  31. package/lib/__templates__/expo/eslint-plugins/fontawesome6/names.js +1889 -0
  32. package/lib/__templates__/expo/eslint-plugins/fontawesome6/rule.js +174 -0
  33. package/lib/__templates__/expo/eslint-plugins/fontawesome6/v5-only-names.js +388 -0
  34. package/lib/__templates__/expo/eslint-plugins/react-native/index.js +9 -0
  35. package/lib/__templates__/expo/eslint-plugins/react-native/rule.js +64 -0
  36. package/lib/__templates__/expo/eslint-plugins/reanimated/index.js +9 -0
  37. package/lib/__templates__/expo/eslint-plugins/reanimated/rule.js +88 -0
  38. package/lib/__templates__/expo/package.json +16 -107
  39. package/lib/__templates__/expo/patches/expo@54.0.33.patch +45 -0
  40. package/lib/__templates__/expo/pnpm-lock.yaml +1437 -3171
  41. package/lib/__templates__/expo/pnpm-workspace.yaml +3 -0
  42. package/lib/__templates__/expo/server/build.js +21 -0
  43. package/lib/__templates__/expo/server/package.json +34 -0
  44. package/lib/__templates__/expo/server/src/index.ts +20 -0
  45. package/lib/__templates__/expo/server/tsconfig.json +24 -0
  46. package/lib/__templates__/expo/template.config.js +57 -0
  47. package/lib/__templates__/expo/tsconfig.json +1 -24
  48. package/lib/__templates__/native-static/.coze +11 -0
  49. package/lib/__templates__/native-static/index.html +33 -0
  50. package/lib/__templates__/native-static/styles/main.css +136 -0
  51. package/lib/__templates__/native-static/template.config.js +22 -0
  52. package/lib/__templates__/nextjs/.babelrc +15 -0
  53. package/lib/__templates__/nextjs/.coze +1 -0
  54. package/lib/__templates__/nextjs/_npmrc +1 -0
  55. package/lib/__templates__/nextjs/next.config.ts +12 -0
  56. package/lib/__templates__/nextjs/package.json +13 -2
  57. package/lib/__templates__/nextjs/pnpm-lock.yaml +2682 -1786
  58. package/lib/__templates__/nextjs/scripts/prepare.sh +9 -0
  59. package/lib/__templates__/nextjs/src/app/globals.css +109 -89
  60. package/lib/__templates__/nextjs/src/app/layout.tsx +5 -14
  61. package/lib/__templates__/nextjs/src/app/page.tsx +18 -48
  62. package/lib/__templates__/nextjs/src/components/ui/resizable.tsx +29 -22
  63. package/lib/__templates__/nextjs/src/components/ui/sidebar.tsx +228 -230
  64. package/lib/__templates__/nextjs/template.config.js +67 -2
  65. package/lib/__templates__/taro/.coze +14 -0
  66. package/lib/__templates__/taro/.cozeproj/scripts/deploy_build.sh +19 -0
  67. package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +14 -0
  68. package/lib/__templates__/taro/.cozeproj/scripts/dev_build.sh +2 -0
  69. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +151 -0
  70. package/lib/__templates__/taro/.cozeproj/scripts/init_env.sh +5 -0
  71. package/lib/__templates__/taro/.cozeproj/scripts/pack.sh +24 -0
  72. package/lib/__templates__/taro/README.md +749 -0
  73. package/lib/__templates__/taro/_gitignore +40 -0
  74. package/lib/__templates__/taro/_npmrc +18 -0
  75. package/lib/__templates__/taro/babel.config.js +12 -0
  76. package/lib/__templates__/taro/config/dev.ts +9 -0
  77. package/lib/__templates__/taro/config/index.ts +173 -0
  78. package/lib/__templates__/taro/config/prod.ts +35 -0
  79. package/lib/__templates__/taro/eslint.config.mjs +79 -0
  80. package/lib/__templates__/taro/key/private.appid.key +0 -0
  81. package/lib/__templates__/taro/package.json +97 -0
  82. package/lib/__templates__/taro/pnpm-lock.yaml +22694 -0
  83. package/lib/__templates__/taro/pnpm-workspace.yaml +2 -0
  84. package/lib/__templates__/taro/project.config.json +15 -0
  85. package/lib/__templates__/taro/server/nest-cli.json +10 -0
  86. package/lib/__templates__/taro/server/package.json +40 -0
  87. package/lib/__templates__/taro/server/src/app.controller.ts +23 -0
  88. package/lib/__templates__/taro/server/src/app.module.ts +10 -0
  89. package/lib/__templates__/taro/server/src/app.service.ts +8 -0
  90. package/lib/__templates__/taro/server/src/interceptors/http-status.interceptor.ts +23 -0
  91. package/lib/__templates__/taro/server/src/main.ts +49 -0
  92. package/lib/__templates__/taro/server/tsconfig.json +24 -0
  93. package/lib/__templates__/taro/src/app.config.ts +11 -0
  94. package/lib/__templates__/taro/src/app.css +52 -0
  95. package/lib/__templates__/taro/src/app.tsx +9 -0
  96. package/lib/__templates__/taro/src/index.html +39 -0
  97. package/lib/__templates__/taro/src/network.ts +39 -0
  98. package/lib/__templates__/taro/src/pages/index/index.config.ts +3 -0
  99. package/lib/__templates__/taro/src/pages/index/index.css +1 -0
  100. package/lib/__templates__/taro/src/pages/index/index.tsx +33 -0
  101. package/lib/__templates__/taro/src/presets/h5-navbar.tsx +171 -0
  102. package/lib/__templates__/taro/src/presets/h5-styles.ts +33 -0
  103. package/lib/__templates__/taro/src/presets/index.tsx +18 -0
  104. package/lib/__templates__/taro/src/presets/wx-debug.ts +23 -0
  105. package/lib/__templates__/taro/stylelint.config.mjs +4 -0
  106. package/lib/__templates__/taro/template.config.js +68 -0
  107. package/lib/__templates__/taro/tsconfig.json +29 -0
  108. package/lib/__templates__/taro/types/global.d.ts +32 -0
  109. package/lib/__templates__/templates.json +104 -43
  110. package/lib/__templates__/vite/.coze +1 -0
  111. package/lib/__templates__/vite/_npmrc +1 -0
  112. package/lib/__templates__/vite/eslint.config.mjs +9 -0
  113. package/lib/__templates__/vite/package.json +14 -1
  114. package/lib/__templates__/vite/pnpm-lock.yaml +1581 -105
  115. package/lib/__templates__/vite/scripts/prepare.sh +9 -0
  116. package/lib/__templates__/vite/src/main.ts +17 -48
  117. package/lib/__templates__/vite/template.config.js +67 -6
  118. package/lib/__templates__/vite/vite.config.ts +1 -0
  119. package/lib/cli.js +1006 -154
  120. package/package.json +9 -3
  121. package/lib/__templates__/expo/.cozeproj/scripts/deploy_build.sh +0 -109
  122. package/lib/__templates__/expo/.cozeproj/scripts/deploy_run.sh +0 -232
  123. package/lib/__templates__/expo/app.json +0 -63
  124. package/lib/__templates__/expo/babel.config.js +0 -19
  125. package/lib/__templates__/expo/client/app/(tabs)/_layout.tsx +0 -43
  126. package/lib/__templates__/expo/client/app/(tabs)/home.tsx +0 -1
  127. package/lib/__templates__/expo/client/app/(tabs)/index.tsx +0 -7
  128. package/lib/__templates__/expo/client/hooks/useColorScheme.ts +0 -1
  129. package/lib/__templates__/expo/client/index.js +0 -12
  130. package/lib/__templates__/expo/client/screens/home/index.tsx +0 -51
  131. package/lib/__templates__/expo/client/screens/home/styles.ts +0 -60
  132. package/lib/__templates__/expo/metro.config.js +0 -51
  133. package/lib/__templates__/expo/src/index.ts +0 -12
  134. package/lib/__templates__/nextjs/.vscode/settings.json +0 -121
  135. package/lib/__templates__/vite/.vscode/settings.json +0 -7
  136. /package/lib/__templates__/expo/{eslint-formatter-simple.mjs → client/eslint-formatter-simple.mjs} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coze-arch/cli",
3
- "version": "0.0.1-alpha.9f719c",
3
+ "version": "0.0.1-alpha.a166f2",
4
4
  "private": false,
5
5
  "description": "coze coding devtools cli",
6
6
  "license": "MIT",
@@ -19,12 +19,13 @@
19
19
  "scripts": {
20
20
  "prebuild": "tsx scripts/prebuild.ts",
21
21
  "build": "tsx scripts/build.ts",
22
+ "create": "tsx scripts/create-template.ts",
22
23
  "lint": "eslint ./ --cache",
23
24
  "postpublish": "bash scripts/sync-npmmirror.sh",
24
25
  "test": "vitest --run --passWithNoTests",
25
26
  "test:all": "bash scripts/test-coverage.sh",
26
27
  "test:cov": "vitest --run --passWithNoTests --coverage",
27
- "test:e2e": "bash scripts/e2e.sh",
28
+ "test:e2e": "NODE_ENV=test bash scripts/e2e.sh",
28
29
  "test:perf": "vitest bench --run --config vitest.perf.config.ts",
29
30
  "test:perf:compare": "bash scripts/compare-perf.sh",
30
31
  "test:perf:save": "bash scripts/run-perf-with-output.sh"
@@ -48,21 +49,26 @@
48
49
  "@coze-arch/ts-config": "workspace:*",
49
50
  "@coze-arch/vitest-config": "workspace:*",
50
51
  "@coze-coding/lambda": "workspace:*",
52
+ "@inquirer/prompts": "^3.2.0",
51
53
  "@types/ejs": "^3.1.5",
52
54
  "@types/iarna__toml": "^2.0.5",
53
55
  "@types/js-yaml": "^4.0.9",
56
+ "@types/minimatch": "^5.1.2",
54
57
  "@types/minimist": "^1.2.5",
55
58
  "@types/node": "^24",
56
59
  "@types/shelljs": "^0.10.0",
57
60
  "@vitest/coverage-v8": "~4.0.16",
58
61
  "json-schema-to-typescript": "^15.0.3",
62
+ "minimatch": "^10.0.1",
59
63
  "rollup": "^4.41.1",
60
64
  "sucrase": "^3.35.0",
61
65
  "tsx": "^4.20.6",
66
+ "vite-tsconfig-paths": "^4.2.1",
62
67
  "vitest": "~4.0.16"
63
68
  },
64
69
  "publishConfig": {
65
- "access": "public"
70
+ "access": "public",
71
+ "registry": "https://registry.npmjs.org"
66
72
  },
67
73
  "cozePublishConfig": {
68
74
  "bin": {
@@ -1,109 +0,0 @@
1
- #!/bin/bash
2
- if [ -z "${BASH_VERSION:-}" ]; then exec /usr/bin/env bash "$0" "$@"; fi
3
- set -euo pipefail
4
- ROOT_DIR="$(pwd)"
5
- PREVIEW_DIR="${COZE_PREVIEW_DIR:-$ROOT_DIR}"
6
- LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
7
- LOG_FILE="$LOG_DIR/app.log"
8
- mkdir -p "$LOG_DIR"
9
-
10
- # ==================== 配置项 ====================
11
- SERVER_DIR="app"
12
- EXPO_DIR="expo"
13
- CHECK_HASH_SCRIPT="$ROOT_DIR/check_hash.py"
14
- # ==================== 工具函数 ====================
15
- info() {
16
- echo -e "\033[32m[INFO] $1\033[0m"
17
- }
18
- warn() {
19
- echo -e "\033[33m[WARN] $1\033[0m"
20
- }
21
- error() {
22
- echo -e "\033[31m[ERROR] $1\033[0m"
23
- exit 1
24
- }
25
- check_command() {
26
- if ! command -v "$1" &> /dev/null; then
27
- error "命令 $1 未找到,请先安装"
28
- fi
29
- }
30
- write_log() {
31
- local level="${1:-INFO}"
32
- local msg="${2:-}"
33
- node -e '
34
- const fs=require("fs");
35
- const path=process.argv[1];
36
- const level=(process.argv[2]||"").toUpperCase();
37
- let msg=String(process.argv[3]||"");
38
- const ts=Date.now();
39
- const dt=new Date();
40
- const parts=new Intl.DateTimeFormat("en-GB",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:false}).formatToParts(dt);
41
- const o={};
42
- for(const p of parts){o[p.type]=p.value}
43
- const dt_str=`${o.year}-${o.month}-${o.day} ${o.hour}:${o.minute}:${o.second}`;
44
- msg=msg.replace(/\\n/g,"\n");
45
- msg=`${dt_str} [${level}] ${msg}`;
46
- const record=JSON.stringify({level, message: msg, timestamp: ts},null,0);
47
- const fd=fs.openSync(path,"a");
48
- fs.writeSync(fd, record+"\n", null, "utf8");
49
- fs.fsyncSync(fd);
50
- fs.closeSync(fd);
51
- ' "$LOG_FILE" "$level" "$msg"
52
- }
53
-
54
- # ==================== 前置检查 ====================
55
- write_log "INFO" "==================== 开始构建 ===================="
56
-
57
- write_log "INFO" "检查根目录 pre_install.py"
58
- if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
59
- write_log "INFO" "执行:python $PREVIEW_DIR/pre_install.py"
60
- python "$PREVIEW_DIR/pre_install.py" || write_log "ERROR" "pre_install.py 执行失败"
61
- fi
62
-
63
- write_log "INFO" "开始执行构建脚本(build_dev.sh)..."
64
- write_log "INFO" "正在检查依赖命令是否存在..."
65
- # 检查核心命令
66
- # check_command "pip"
67
- # check_command "python"
68
- check_command "pnpm"
69
- check_command "npm"
70
-
71
- # ==================== 步骤 1:安装项目依赖 ====================
72
- write_log "INFO" "==================== 安装项目依赖 ===================="
73
- if [ ! -f "package.json" ]; then
74
- write_log "ERROR" "项目目录下无 package.json,不是合法的 Node.js 项目"
75
- fi
76
- # 步骤 2.1/2.2:安装 Expo 项目依赖(按哈希变化执行)
77
- if [ -f "$CHECK_HASH_SCRIPT" ]; then
78
- write_log "INFO" "检测 package.json 哈希是否变化"
79
- set +e
80
- python "$CHECK_HASH_SCRIPT" --config "package.json" --check
81
- rc_node=$?
82
- set -e
83
- if [ $rc_node -eq 1 ]; then
84
- write_log "INFO" "依赖哈希已变化,执行:pnpm install"
85
- pnpm install --registry=https://registry.npmmirror.com || write_log "ERROR" "Expo 项目依赖安装失败(pnpm 执行出错)"
86
-
87
- write_log "INFO" "依赖哈希已变化,执行:npm run install-missing"
88
- npm run install-missing || write_log "ERROR" "npm run install-missing 执行失败,请检查 package.json 中的脚本配置"
89
-
90
- set +e
91
- python "$CHECK_HASH_SCRIPT" --config "package.json" --update
92
- set -e
93
- else
94
- write_log "INFO" "跳过 pnpm install 与 npm run install-missing"
95
- fi
96
- else
97
- write_log "WARN" "未找到 check_hash.py,默认执行:pnpm install 与 npm run install-missing"
98
- pnpm install --registry=https://registry.npmmirror.com || write_log "ERROR" "Expo 项目依赖安装失败(pnpm 执行出错)"
99
- npm run install-missing || write_log "ERROR" "npm run install-missing 执行失败,请检查 package.json 中的脚本配置"
100
- fi
101
-
102
- write_log "INFO" "检查根目录 post_install.py"
103
- if [ -f "$ROOT_DIR/post_install.py" ]; then
104
- write_log "INFO" "执行:python $ROOT_DIR/post_install.py"
105
- python "$ROOT_DIR/post_install.py" || write_log "ERROR" "post_install.py 执行失败"
106
- fi
107
-
108
- write_log "INFO" "==================== 依赖安装完成!====================\n"
109
- write_log "INFO" "下一步:执行 ./deploy_run.sh 启动服务"
@@ -1,232 +0,0 @@
1
- ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
2
- PREVIEW_DIR="${COZE_PREVIEW_DIR:-$ROOT_DIR}"
3
- LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
4
- LOG_FILE="$LOG_DIR/app.log"
5
- mkdir -p "$LOG_DIR"
6
-
7
- # ==================== 配置项 ====================
8
- # Server 服务配置
9
- SERVER_HOST="0.0.0.0"
10
- SERVER_PORT="9091"
11
- # Expo 项目配置
12
- EXPO_HOST="0.0.0.0"
13
- EXPO_DIR="expo"
14
- EXPO_PORT="5000"
15
- WEB_URL="${COZE_PROJECT_DOMAIN_DEFAULT:-http://127.0.0.1:${SERVER_PORT}}"
16
- ASSUME_YES="1"
17
- EXPO_PUBLIC_BACKEND_BASE_URL="${EXPO_PUBLIC_BACKEND_BASE_URL:-$WEB_URL}"
18
-
19
-
20
- EXPO_PACKAGER_PROXY_URL="${EXPO_PUBLIC_BACKEND_BASE_URL}"
21
- export EXPO_PUBLIC_BACKEND_BASE_URL EXPO_PACKAGER_PROXY_URL
22
- # 运行时变量(为避免 set -u 的未绑定错误,预置为空)
23
- SERVER_PID=""
24
- EXPO_PID=""
25
- # ==================== 工具函数 ====================
26
- info() {
27
- echo -e "\033[32m[INFO] $1\033[0m"
28
- }
29
- warn() {
30
- echo -e "\033[33m[WARN] $1\033[0m"
31
- }
32
- error() {
33
- echo -e "\033[31m[ERROR] $1\033[0m"
34
- exit 1
35
- }
36
- check_command() {
37
- if ! command -v "$1" &> /dev/null; then
38
- error "命令 $1 未找到,请先安装"
39
- fi
40
- }
41
- while [ $# -gt 0 ]; do
42
- case "$1" in
43
- -y|--yes)
44
- ASSUME_YES="1"
45
- shift
46
- ;;
47
- *)
48
- shift
49
- ;;
50
- esac
51
- done
52
- is_port_free() {
53
- ! lsof -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1
54
- }
55
- choose_next_free_port() {
56
- local start=$1
57
- local p=$start
58
- while ! is_port_free "$p"; do
59
- p=$((p+1))
60
- done
61
- echo "$p"
62
- }
63
- ensure_port() {
64
- local var_name=$1
65
- local port_val=$2
66
- if is_port_free "$port_val"; then
67
- info "端口未占用:$port_val"
68
- eval "$var_name=$port_val"
69
- else
70
- warn "端口已占用:$port_val"
71
- local choice
72
- if [ "$ASSUME_YES" = "1" ]; then choice="Y"; else read -r -p "是否关闭该端口的进程?[Y/n] " choice || choice="Y"; fi
73
- if [ -z "$choice" ] || [ "$choice" = "y" ] || [ "$choice" = "Y" ]; then
74
- if command -v lsof &> /dev/null; then
75
- local pids
76
- pids=$(lsof -t -i tcp:"$port_val" -sTCP:LISTEN 2>/dev/null || true)
77
- if [ -n "$pids" ]; then
78
- info "正在关闭进程:$pids"
79
- kill -9 $pids 2>/dev/null || warn "关闭进程失败:$pids"
80
- eval "$var_name=$port_val"
81
- else
82
- warn "未获取到占用该端口的进程"
83
- eval "$var_name=$port_val"
84
- fi
85
- else
86
- warn "缺少 lsof,无法自动关闭进程"
87
- eval "$var_name=$port_val"
88
- fi
89
- else
90
- local new_port
91
- new_port=$(choose_next_free_port "$port_val")
92
- info "使用新的端口:$new_port"
93
- eval "$var_name=$new_port"
94
- fi
95
- fi
96
- }
97
-
98
- write_log() {
99
- local level="${1:-INFO}"
100
- local msg="${2:-}"
101
- node -e '
102
- const fs=require("fs");
103
- const path=process.argv[1];
104
- const level=(process.argv[2]||"").toUpperCase();
105
- let msg=String(process.argv[3]||"");
106
- const ts=Date.now();
107
- msg=msg.replace(/\\n/g,"\n");
108
- const dt=new Date();
109
- const parts=new Intl.DateTimeFormat("en-GB",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:false}).formatToParts(dt);
110
- const o={};
111
- for(const p of parts){o[p.type]=p.value}
112
- const dt_str=`${o.year}-${o.month}-${o.day} ${o.hour}:${o.minute}:${o.second}`;
113
- msg=`${dt_str} [${level}] ${msg}`;
114
- const record=JSON.stringify({level, message: msg, timestamp: ts},null,0);
115
- const fd=fs.openSync(path,"a");
116
- fs.writeSync(fd, record+"\n", null, "utf8");
117
- fs.fsyncSync(fd);
118
- fs.closeSync(fd);
119
- ' "$LOG_FILE" "$level" "$msg"
120
- }
121
-
122
- wait_port_connectable() {
123
- local host=$1 port=$2 retries=${3:-10}
124
- for _ in $(seq 1 "$retries"); do
125
- nc -z "$host" "$port" && return 0
126
- sleep 1
127
- done
128
- return 1
129
- }
130
-
131
- start_expo() {
132
- local offline="${1:-0}"
133
- if [ "$offline" = "1" ]; then
134
- 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" nohup npx expo start --port "$EXPO_PORT" > logs/expo.log 2>&1 &
135
- else
136
- EXPO_NO_DOCTOR=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" nohup npx expo start --port "$EXPO_PORT" > logs/expo.log 2>&1 &
137
- fi
138
- EXPO_PID=$!
139
- echo "$EXPO_PID"
140
- }
141
-
142
- detect_expo_fetch_failed() {
143
- local timeout="${1:-8}"
144
- local waited=0
145
- local log_file="logs/expo.log"
146
- while [ "$waited" -lt "$timeout" ]; do
147
- if [ -f "$log_file" ] && grep -q "TypeError: fetch failed" "$log_file" 2>/dev/null; then
148
- return 0
149
- fi
150
- sleep 1
151
- waited=$((waited+1))
152
- done
153
- return 1
154
- }
155
-
156
- # ==================== 前置检查 ====================
157
- write_log "INFO" "检查根目录 pre_install.py"
158
- if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
159
- write_log "INFO" "执行:python $PREVIEW_DIR/pre_install.py"
160
- python "$PREVIEW_DIR/pre_install.py" || write_log "ERROR" "pre_install.py 执行失败"
161
- fi
162
-
163
- write_log "INFO" "==================== 开始启动 ===================="
164
- write_log "INFO" "开始执行服务启动脚本(start_dev.sh)..."
165
- write_log "INFO" "正在检查依赖命令和目录是否存在..."
166
- # 检查核心命令
167
- # check_command "python"
168
- check_command "npm"
169
- check_command "pnpm"
170
- check_command "lsof"
171
- check_command "bash"
172
-
173
- info "准备日志目录:logs"
174
- mkdir -p logs
175
- # 端口占用预检查与处理
176
- ensure_port SERVER_PORT "$SERVER_PORT"
177
- ensure_port EXPO_PORT "$EXPO_PORT"
178
-
179
- # ==================== 启动 Server 服务 ====================
180
- write_log "INFO" "==================== 启动 server 服务 ===================="
181
- write_log "INFO" "正在执行:npm run server"
182
- PORT="$SERVER_PORT" nohup npm run server > logs/app.log 2>&1 &
183
- SERVER_PID=$!
184
- if [ -z "${SERVER_PID}" ]; then
185
- write_log "ERROR" "无法获取 server 后台进程 PID"
186
- fi
187
- write_log "INFO" "server 服务已启动,进程 ID:${SERVER_PID:-unknown}"
188
-
189
- write_log "INFO" "==================== 启动 Expo 项目 ===================="
190
- write_log "INFO" "正在执行:npx expo start --port ${EXPO_PORT}"
191
- write_log "INFO" "开始启动 Expo 服务"
192
- EXPO_PID=$(start_expo 0)
193
- if detect_expo_fetch_failed 8; then
194
- write_log "WARN" "Expo 启动检测到网络错误:TypeError: fetch failed,启用离线模式重试"
195
- if [ -n "${EXPO_PID}" ]; then kill -9 "$EXPO_PID" 2>/dev/null || true; fi
196
- : > logs/expo.log
197
- EXPO_PID=$(start_expo 1)
198
- fi
199
- # 输出以下环境变量,确保 Expo 项目能正确连接到 Server 服务
200
- write_log "INFO" "Expo 环境变量配置:"
201
- write_log "INFO" "EXPO_PUBLIC_BACKEND_BASE_URL=${EXPO_PUBLIC_BACKEND_BASE_URL}"
202
- write_log "INFO" "EXPO_PACKAGER_PROXY_URL=${EXPO_PACKAGER_PROXY_URL}"
203
- if [ -z "${EXPO_PID}" ]; then
204
- write_log "ERROR" "无法获取 Expo 后台进程 PID"
205
- fi
206
-
207
- write_log "INFO" "所有服务已启动。Server PID: ${SERVER_PID}, Expo PID: ${EXPO_PID}"
208
-
209
- write_log "INFO" "检查 Server 服务端口:$SERVER_HOST:$SERVER_PORT"
210
- if wait_port_connectable "$SERVER_HOST" "$SERVER_PORT" 10 2; then
211
- write_log "INFO" "端口可连接:$SERVER_HOST:$SERVER_PORT"
212
- else
213
- write_log "WARN" "端口不可连接:$SERVER_HOST:$SERVER_PORT 10 次)"
214
- fi
215
-
216
- write_log "INFO" "检查 Expo 服务端口:$EXPO_HOST:$EXPO_PORT"
217
- if wait_port_connectable "$EXPO_HOST" "$EXPO_PORT" 10 2; then
218
- write_log "INFO" "端口可连接:$EXPO_HOST:$EXPO_PORT"
219
- else
220
- write_log "WARN" "端口不可连接:$EXPO_HOST:$EXPO_PORT(已尝试 10 次)"
221
- fi
222
-
223
- write_log "INFO" "服务端口检查完成"
224
-
225
- write_log "INFO" "检查根目录 post_run.py"
226
- if [ -f "$ROOT_DIR/post_run.py" ]; then
227
- write_log "INFO" "启动检查中"
228
- python "$ROOT_DIR/post_run.py" --port "$EXPO_PORT" || write_log "ERROR" "post_run.py 执行失败"
229
- write_log "INFO" "启动检查结束"
230
- fi
231
-
232
- write_log "INFO" "==================== 服务启动完成 ===================="
@@ -1,63 +0,0 @@
1
- {
2
- "expo": {
3
- "name": "${app_name}",
4
- "slug": "${slug}",
5
- "version": "1.0.0",
6
- "orientation": "portrait",
7
- "icon": "./client/assets/images/icon.png",
8
- "scheme": "myapp",
9
- "userInterfaceStyle": "automatic",
10
- "newArchEnabled": true,
11
- "ios": {
12
- "supportsTablet": true
13
- },
14
- "android": {
15
- "adaptiveIcon": {
16
- "foregroundImage": "./client/assets/images/adaptive-icon.png",
17
- "backgroundColor": "#ffffff"
18
- }
19
- },
20
- "web": {
21
- "bundler": "metro",
22
- "output": "single",
23
- "favicon": "./client/assets/images/favicon.png"
24
- },
25
- "plugins": [
26
- "expo-router",
27
- [
28
- "expo-splash-screen",
29
- {
30
- "image": "./client/assets/images/splash-icon.png",
31
- "imageWidth": 200,
32
- "resizeMode": "contain",
33
- "backgroundColor": "#ffffff"
34
- }
35
- ],
36
- [
37
- "expo-image-picker",
38
- {
39
- "photosPermission": "允许${app_name}访问您的相册,以便您上传或保存图片。",
40
- "cameraPermission": "允许${app_name}使用您的相机,以便您直接拍摄照片上传。",
41
- "microphonePermission": "允许${app_name}访问您的麦克风,以便您拍摄带有声音的视频。"
42
- }
43
- ],
44
- [
45
- "expo-location",
46
- {
47
- "locationWhenInUsePermission": "${app_name}需要访问您的位置以提供周边服务及导航功能。"
48
- }
49
- ],
50
- [
51
- "expo-camera",
52
- {
53
- "cameraPermission": "${app_name}需要访问相机以拍摄照片和视频。",
54
- "microphonePermission": "${app_name}需要访问麦克风以录制视频声音。",
55
- "recordAudioAndroid": true
56
- }
57
- ]
58
- ],
59
- "experiments": {
60
- "typedRoutes": true
61
- }
62
- }
63
- }
@@ -1,19 +0,0 @@
1
- module.exports = function (api) {
2
- api.cache(true);
3
- return {
4
- presets: ["babel-preset-expo"],
5
- plugins: [
6
- [
7
- "module-resolver",
8
- {
9
- root: ["./"],
10
- alias: {
11
- "@": "./client",
12
- },
13
- extensions: [".ios.js", ".android.js", ".js", ".ts", ".tsx", ".json"],
14
- },
15
- ],
16
- "react-native-reanimated/plugin",
17
- ],
18
- };
19
- };
@@ -1,43 +0,0 @@
1
- import { Tabs } from 'expo-router';
2
- import { FontAwesome6 } from '@expo/vector-icons';
3
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
- import { useTheme } from '@/hooks/useTheme';
5
-
6
- export default function TabLayout() {
7
- const insets = useSafeAreaInsets();
8
- const { theme } = useTheme();
9
- const tabBarHeight = 56 + Math.max(insets.bottom, 8);
10
-
11
- return (
12
- <Tabs
13
- backBehavior='history'
14
- screenOptions={{
15
- headerShown: false,
16
- tabBarActiveTintColor: theme.tabIconSelected,
17
- tabBarInactiveTintColor: theme.tabIconDefault,
18
- tabBarStyle: {
19
- backgroundColor: theme.backgroundRoot,
20
- borderTopColor: theme.backgroundSecondary,
21
- borderTopWidth: 1,
22
- height: tabBarHeight,
23
- paddingBottom: Math.max(insets.bottom, 8),
24
- paddingTop: 6,
25
- },
26
- }}
27
- >
28
- <Tabs.Screen
29
- name='index'
30
- options={{ href: null }}
31
- />
32
- <Tabs.Screen
33
- name='home'
34
- options={{
35
- title: '首页',
36
- tabBarIcon: ({ color }) => (
37
- <FontAwesome6 name='house' size={20} color={color} />
38
- ),
39
- }}
40
- />
41
- </Tabs>
42
- );
43
- }
@@ -1 +0,0 @@
1
- export { default } from "@/screens/home";
@@ -1,7 +0,0 @@
1
- import { Redirect } from 'expo-router';
2
-
3
- const Index = () => {
4
- return <Redirect href="./home" relativeToDirectory />;
5
- };
6
-
7
- export default Index;
@@ -1 +0,0 @@
1
- export { useColorScheme } from "react-native";
@@ -1,12 +0,0 @@
1
- import '@expo/metro-runtime';
2
- import { registerRootComponent } from 'expo';
3
- import { ExpoRoot } from 'expo-router';
4
-
5
- // 显式定义 App 组件
6
- export function App() {
7
- // eslint-disable-next-line no-undef
8
- const ctx = require.context('./app');
9
- return <ExpoRoot context={ctx} />;
10
- }
11
-
12
- registerRootComponent(App);
@@ -1,51 +0,0 @@
1
- import React, { useState, useCallback } from 'react';
2
- import {
3
- View,
4
- Text,
5
- ScrollView,
6
- RefreshControl,
7
- } from 'react-native';
8
- import { useRouter, useFocusEffect } from 'expo-router';
9
- import { FontAwesome6 } from '@expo/vector-icons';
10
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
11
- import { useTheme } from "@/hooks/useTheme";
12
-
13
- import { Screen } from '@/components/Screen';
14
-
15
- import { styles } from './styles';
16
-
17
-
18
- export default function HomeScreen() {
19
- const insets = useSafeAreaInsets();
20
- const { theme, isDark } = useTheme();
21
-
22
- const [isRefreshing, setIsRefreshing] = useState(false);
23
-
24
- const loadData = useCallback(async () => {
25
- }, []);
26
-
27
- useFocusEffect(
28
- useCallback(() => {
29
- loadData();
30
- }, [loadData])
31
- );
32
-
33
- const handleRefresh = useCallback(() => {
34
- setIsRefreshing(true);
35
- loadData();
36
- }, [loadData]);
37
- return (
38
- <Screen backgroundColor={theme.backgroundRoot} statusBarStyle={isDark ? 'light' : 'dark'}>
39
- <ScrollView
40
- showsVerticalScrollIndicator={false}
41
- contentContainerStyle={{}}
42
- refreshControl={
43
- <RefreshControl refreshing={isRefreshing} onRefresh={handleRefresh} colors={['#2563EB']} />
44
- }
45
- >
46
- <View style={[styles.header]}>
47
- </View>
48
- </ScrollView>
49
- </Screen>
50
- );
51
- }
@@ -1,60 +0,0 @@
1
- import { StyleSheet, Platform } from 'react-native';
2
-
3
- export const styles = StyleSheet.create({
4
- loadingContainer: {
5
- flex: 1,
6
- justifyContent: 'center',
7
- alignItems: 'center',
8
- },
9
- loadingText: {
10
- marginTop: 12,
11
- fontSize: 14,
12
- color: '#64748B',
13
- },
14
- errorContainer: {
15
- flex: 1,
16
- justifyContent: 'center',
17
- alignItems: 'center',
18
- paddingHorizontal: 24,
19
- },
20
- errorText: {
21
- marginTop: 16,
22
- fontSize: 16,
23
- color: '#64748B',
24
- },
25
- header: {
26
- flexDirection: 'row',
27
- justifyContent: 'space-between',
28
- alignItems: 'center',
29
- paddingHorizontal: 16,
30
- // paddingBottom: 16,
31
- backgroundColor: '#FFFFFF',
32
- // borderBottomWidth: 1,
33
- borderBottomColor: '#E2E8F0',
34
- },
35
- logoContainer: {
36
- width: 32,
37
- height: 32,
38
- backgroundColor: '#2563EB',
39
- borderRadius: 8,
40
- justifyContent: 'center',
41
- alignItems: 'center',
42
- ...Platform.select({
43
- ios: {
44
- shadowColor: '#000',
45
- shadowOffset: { width: 0, height: 1 },
46
- shadowOpacity: 0.1,
47
- shadowRadius: 2,
48
- },
49
- android: {
50
- elevation: 2,
51
- },
52
- }),
53
- },
54
- logoText: {
55
- fontSize: 18,
56
- fontWeight: '700',
57
- color: '#1E293B',
58
- letterSpacing: -0.5,
59
- },
60
- });