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

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 (78) hide show
  1. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +15 -14
  2. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +9 -8
  3. package/lib/__templates__/expo/README.md +14 -17
  4. package/lib/__templates__/expo/client/app/+not-found.tsx +4 -19
  5. package/lib/__templates__/expo/client/app/_layout.tsx +16 -17
  6. package/lib/__templates__/expo/client/eslint.config.mjs +17 -1
  7. package/lib/__templates__/expo/client/global.css +78 -0
  8. package/lib/__templates__/expo/client/metro.config.js +8 -1
  9. package/lib/__templates__/expo/client/package.json +37 -34
  10. package/lib/__templates__/expo/client/screens/demo/index.tsx +6 -12
  11. package/lib/__templates__/expo/client/styles.css +263 -0
  12. package/lib/__templates__/expo/client/uniwind-types.d.ts +10 -0
  13. package/lib/__templates__/expo/eslint-plugins/react-native/index.js +9 -0
  14. package/lib/__templates__/expo/eslint-plugins/react-native/rule.js +64 -0
  15. package/lib/__templates__/expo/package.json +1 -1
  16. package/lib/__templates__/expo/patches/expo@54.0.33.patch +45 -0
  17. package/lib/__templates__/expo/pnpm-lock.yaml +338 -1735
  18. package/lib/__templates__/expo/server/package.json +9 -7
  19. package/lib/__templates__/expo/server/src/index.ts +1 -0
  20. package/lib/__templates__/expo/template.config.js +56 -0
  21. package/lib/__templates__/nextjs/package.json +3 -1
  22. package/lib/__templates__/nextjs/pnpm-lock.yaml +1051 -934
  23. package/lib/__templates__/nextjs/src/app/page.tsx +18 -60
  24. package/lib/__templates__/nextjs/template.config.js +49 -14
  25. package/lib/__templates__/taro/.coze +14 -0
  26. package/lib/__templates__/taro/.cozeproj/scripts/deploy_build.sh +19 -0
  27. package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +14 -0
  28. package/lib/__templates__/taro/.cozeproj/scripts/dev_build.sh +2 -0
  29. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +80 -0
  30. package/lib/__templates__/taro/.cozeproj/scripts/init_env.sh +5 -0
  31. package/lib/__templates__/taro/.cozeproj/scripts/pack.sh +1 -0
  32. package/lib/__templates__/taro/README.md +747 -0
  33. package/lib/__templates__/taro/_gitignore +40 -0
  34. package/lib/__templates__/taro/_npmrc +18 -0
  35. package/lib/__templates__/taro/babel.config.js +12 -0
  36. package/lib/__templates__/taro/config/dev.ts +9 -0
  37. package/lib/__templates__/taro/config/index.ts +173 -0
  38. package/lib/__templates__/taro/config/prod.ts +35 -0
  39. package/lib/__templates__/taro/eslint.config.mjs +57 -0
  40. package/lib/__templates__/taro/key/private.appid.key +0 -0
  41. package/lib/__templates__/taro/package.json +97 -0
  42. package/lib/__templates__/taro/pnpm-lock.yaml +22708 -0
  43. package/lib/__templates__/taro/pnpm-workspace.yaml +2 -0
  44. package/lib/__templates__/taro/project.config.json +15 -0
  45. package/lib/__templates__/taro/server/nest-cli.json +10 -0
  46. package/lib/__templates__/taro/server/package.json +41 -0
  47. package/lib/__templates__/taro/server/src/app.controller.ts +23 -0
  48. package/lib/__templates__/taro/server/src/app.module.ts +10 -0
  49. package/lib/__templates__/taro/server/src/app.service.ts +8 -0
  50. package/lib/__templates__/taro/server/src/interceptors/http-status.interceptor.ts +23 -0
  51. package/lib/__templates__/taro/server/src/main.ts +49 -0
  52. package/lib/__templates__/taro/server/tsconfig.json +24 -0
  53. package/lib/__templates__/taro/src/app.config.ts +11 -0
  54. package/lib/__templates__/taro/src/app.css +52 -0
  55. package/lib/__templates__/taro/src/app.ts +14 -0
  56. package/lib/__templates__/taro/src/index.html +39 -0
  57. package/lib/__templates__/taro/src/network.ts +39 -0
  58. package/lib/__templates__/taro/src/pages/index/index.config.ts +3 -0
  59. package/lib/__templates__/taro/src/pages/index/index.css +1 -0
  60. package/lib/__templates__/taro/src/pages/index/index.tsx +33 -0
  61. package/lib/__templates__/taro/src/utils/h5-styles.ts +33 -0
  62. package/lib/__templates__/taro/src/utils/wx-debug.ts +23 -0
  63. package/lib/__templates__/taro/stylelint.config.mjs +4 -0
  64. package/lib/__templates__/taro/template.config.js +68 -0
  65. package/lib/__templates__/taro/tsconfig.json +29 -0
  66. package/lib/__templates__/taro/types/global.d.ts +32 -0
  67. package/lib/__templates__/templates.json +32 -0
  68. package/lib/__templates__/vite/package.json +5 -1
  69. package/lib/__templates__/vite/pnpm-lock.yaml +146 -1659
  70. package/lib/__templates__/vite/src/main.ts +17 -47
  71. package/lib/__templates__/vite/template.config.js +49 -14
  72. package/lib/cli.js +353 -76
  73. package/package.json +1 -1
  74. package/lib/__templates__/expo/client/constants/theme.ts +0 -177
  75. package/lib/__templates__/expo/client/hooks/useColorScheme.tsx +0 -48
  76. package/lib/__templates__/expo/client/hooks/useTheme.ts +0 -33
  77. package/lib/__templates__/expo/client/screens/demo/styles.ts +0 -28
  78. package/lib/__templates__/expo/patches/expo@54.0.32.patch +0 -28
@@ -1,7 +1,7 @@
1
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
- LOG_FILE="$LOG_DIR/app.log"
4
+ LOG_CLIENT_FILE="$LOG_DIR/client.log"
5
5
  mkdir -p "$LOG_DIR"
6
6
 
7
7
  # ==================== 配置项 ====================
@@ -89,14 +89,17 @@ ensure_port() {
89
89
  pipe_to_log() {
90
90
  local source="${1:-CLIENT}"
91
91
  local raw_log="${2:-}"
92
- local line timestamp ts msg record
92
+ local line clean_line timestamp
93
93
  while IFS= read -r line || [ -n "$line" ]; do
94
+ clean_line=$(printf '%s' "$line" | sed 's/\x1b\[[0-9;]*[mA-Za-z]//g')
95
+ if echo "$clean_line" | grep -qE '(^(Web|iOS|Android) node_modules/.*expo-router.*entry\.js.*%|^(Web|iOS|Android) Bundled [0-9]+ms node_modules/.*expo-router.*entry\.js|Logs will appear in the browser)'; then
96
+ continue
97
+ fi
94
98
  if [ -n "$raw_log" ]; then
95
- echo "$line" >> "$raw_log"
99
+ timestamp=$(date '+%Y-%m-%d %H:%M:%S')
100
+ echo "[$timestamp] $clean_line" >> "$raw_log"
96
101
  fi
97
- line=$(echo "[$source] $line" | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\x1b\[[0-9;]*m//g')
98
- msg="${line}"
99
- echo "$msg"
102
+ printf '[%s] %s\n' "$source" "$clean_line"
100
103
  done
101
104
  }
102
105
 
@@ -115,11 +118,11 @@ start_expo() {
115
118
  pushd "$ROOT_DIR/client"
116
119
 
117
120
  if [ "$offline" = "1" ]; then
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" ) &
121
+ ( EXPO_OFFLINE=1 EXPO_NO_DEPENDENCY_VALIDATION=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" "$LOG_CLIENT_FILE" ) &
120
123
  else
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" ) &
124
+ ( EXPO_NO_DEPENDENCY_VALIDATION=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" \
125
+ nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$LOG_CLIENT_FILE" ) &
123
126
  fi
124
127
  EXPO_PID=$!
125
128
  disown $EXPO_PID 2>/dev/null || true
@@ -130,9 +133,9 @@ start_expo() {
130
133
  detect_expo_fetch_failed() {
131
134
  local timeout="${1:-8}"
132
135
  local waited=0
133
- local log_file="$ROOT_DIR/logs/client.log"
136
+ local log_file="$LOG_CLIENT_FILE"
134
137
  while [ "$waited" -lt "$timeout" ]; do
135
- if [ -f "$log_file" ] && grep -q "TypeError: fetch failed" "$log_file" 2>/dev/null; then
138
+ if [ -f "$log_file" ] && tail -n 100 "$log_file" 2>/dev/null | grep -q "TypeError: fetch failed"; then
136
139
  return 0
137
140
  fi
138
141
  sleep 1
@@ -166,8 +169,6 @@ check_command "pnpm"
166
169
  check_command "lsof"
167
170
  check_command "bash"
168
171
 
169
- echo "准备日志目录:$ROOT_DIR/logs"
170
- mkdir -p "$ROOT_DIR/logs"
171
172
  # 端口占用预检查与处理
172
173
  ensure_port SERVER_PORT "$SERVER_PORT"
173
174
  ensure_port EXPO_PORT "$EXPO_PORT"
@@ -2,8 +2,8 @@
2
2
 
3
3
  ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
4
4
  SERVER_DIR="$ROOT_DIR/server"
5
- LOG_DIR="$ROOT_DIR/logs"
6
- LOG_FILE="$LOG_DIR/server.log"
5
+ LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
6
+ LOG_SERVER_FILE="$LOG_DIR/server.log"
7
7
  SERVER_PORT="${SERVER_PORT:-9091}"
8
8
 
9
9
  mkdir -p "$LOG_DIR"
@@ -11,13 +11,14 @@ mkdir -p "$LOG_DIR"
11
11
  pipe_to_log() {
12
12
  local source="${1:-SERVER}"
13
13
  local raw_log="${2:-}"
14
- local line
14
+ local line clean_line timestamp
15
15
  while IFS= read -r line || [ -n "$line" ]; do
16
+ clean_line=$(printf '%s' "$line" | sed 's/\x1b\[[0-9;]*[mA-Za-z]//g')
16
17
  if [ -n "$raw_log" ]; then
17
- echo "$line" >> "$raw_log"
18
+ timestamp=$(date '+%Y-%m-%d %H:%M:%S')
19
+ echo "[$timestamp] $clean_line" >> "$raw_log"
18
20
  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
+ printf '[%s] %s\n' "$source" "$clean_line"
21
22
  done
22
23
  }
23
24
 
@@ -36,10 +37,10 @@ kill_old_server() {
36
37
  echo "==================== Server Dev Run ===================="
37
38
  echo "Server 目录:$SERVER_DIR"
38
39
  echo "Server 端口:$SERVER_PORT"
39
- echo "日志文件:$LOG_FILE"
40
+ echo "日志文件:$LOG_SERVER_FILE"
40
41
 
41
42
  kill_old_server
42
43
 
43
44
  echo "启动 server 服务..."
44
45
  cd "$SERVER_DIR"
45
- NODE_ENV=development PORT="$SERVER_PORT" npx tsx ./src/index.ts 2>&1 | pipe_to_log "SERVER" "$LOG_FILE"
46
+ NODE_ENV=development PORT="$SERVER_PORT" npx tsx watch ./src/index.ts 2>&1 | pipe_to_log "SERVER" "$LOG_SERVER_FILE"
@@ -1,6 +1,6 @@
1
1
  # Expo App + Express.js
2
2
 
3
- ## 目录结构规范(严格遵循)
3
+ ## 目录结构规范
4
4
 
5
5
  当前仓库是一个 monorepo(基于 pnpm 的 workspace)
6
6
 
@@ -15,18 +15,15 @@
15
15
  | └── package.json # 服务端 package.json
16
16
  ├── client/ # React Native 前端代码
17
17
  │ ├── app/ # Expo Router 路由目录(仅路由配置)
18
- │ │ ├── _layout.tsx # 根布局文件(必需)
19
- │ │ ├── home.tsx # 首页
20
- │ │ └── index.tsx # re-export home.tsx
18
+ │ │ ├── _layout.tsx # 根布局文件(必需,务必阅读)
19
+ │ │ └── index.tsx # 首页
21
20
  │ ├── screens/ # 页面实现目录(与 app/ 路由对应)
22
- │ │ └── home/
23
- │ │ ├── index.tsx # 页面组件实现
24
- │ │ └── styles.ts # 页面样式
21
+ │ │ └── demo/
22
+ │ │ └── index.tsx # demo 示例页面(默认首页,不需要可以删除,记得同时更新路由文件)
25
23
  │ ├── components/ # 可复用组件
26
24
  │ │ └── Screen.tsx # 页面容器组件(必用)
27
25
  │ ├── hooks/ # 自定义 Hooks
28
26
  │ ├── contexts/ # React Context 代码
29
- │ ├── constants/ # 常量定义(如主题配置)
30
27
  │ ├── utils/ # 工具函数
31
28
  │ ├── assets/ # 静态资源
32
29
  | └── package.json # Expo 应用 package.json
@@ -34,6 +31,15 @@
34
31
  ├── .cozeproj # 预置脚手架脚本(禁止修改)
35
32
  └── .coze # 配置文件(禁止修改)
36
33
 
34
+ ## 技术选型(严格遵循)
35
+
36
+ - 前端:Expo + React Native + TailwindCSS
37
+ - 后端:Express.js
38
+
39
+ 本项目通过 uniwind 实现了 react-native 对 TailwindCSS v4 的支持,在编写样式时应使用 TailwindCSS 写法
40
+
41
+ 在开始开发前,先查看 client/global.css 了解必要的信息
42
+
37
43
  ## 安装依赖
38
44
 
39
45
  ### 命令
@@ -42,15 +48,6 @@
42
48
  pnpm i
43
49
  ```
44
50
 
45
- ### 新增依赖约束
46
-
47
- 如果需要新增依赖,需在 client 和 server 各自的目录添加(原因:隔离前后端的依赖),禁止在根目录直接安装依赖
48
-
49
- ### 新增依赖标准流程
50
-
51
- - 编辑 `client/package.json` 或 `server/package.json`
52
- - 在根目录执行 `pnpm i`
53
-
54
51
  ## Expo 开发规范
55
52
 
56
53
  ### 路径别名
@@ -1,30 +1,15 @@
1
- import { View, Text, StyleSheet } from 'react-native';
1
+ import { View, Text } from 'react-native';
2
2
  import { Link } from 'expo-router';
3
- import { useTheme } from '@/hooks/useTheme';
4
- import { Spacing } from '@/constants/theme';
5
3
 
6
4
  export default function NotFoundScreen() {
7
- const { theme } = useTheme();
8
-
9
5
  return (
10
- <View style={[styles.container, { backgroundColor: theme.backgroundRoot }]}>
11
- <Text>
6
+ <View className="flex-1 justify-center items-center bg-background">
7
+ <Text className="text-foreground">
12
8
  页面不存在
13
9
  </Text>
14
- <Link href="/" style={[styles.gohome]}>
10
+ <Link href="/" className="text-accent mt-6">
15
11
  返回首页
16
12
  </Link>
17
13
  </View>
18
14
  );
19
15
  }
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,7 +5,8 @@ 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
+ import '../global.css';
9
10
 
10
11
  LogBox.ignoreLogs([
11
12
  "TurboModuleRegistry.getEnforcing(...): 'RNMapsAirModule' could not be found",
@@ -15,22 +16,20 @@ LogBox.ignoreLogs([
15
16
  export default function RootLayout() {
16
17
  return (
17
18
  <AuthProvider>
18
- <ColorSchemeProvider>
19
- <GestureHandlerRootView style={{ flex: 1 }}>
20
- <StatusBar style="dark"></StatusBar>
21
- <Stack screenOptions={{
22
- // 设置所有页面的切换动画为从右侧滑入,适用于iOS 和 Android
23
- animation: 'slide_from_right',
24
- gestureEnabled: true,
25
- gestureDirection: 'horizontal',
26
- // 隐藏自带的头部
27
- headerShown: false
28
- }}>
29
- <Stack.Screen name="index" options={{ title: "" }} />
30
- </Stack>
31
- <Toast />
32
- </GestureHandlerRootView>
33
- </ColorSchemeProvider>
19
+ <GestureHandlerRootView style={{ flex: 1 }}>
20
+ <StatusBar style="dark"></StatusBar>
21
+ <Stack screenOptions={{
22
+ // 设置所有页面的切换动画为从右侧滑入,适用于iOS 和 Android
23
+ animation: 'slide_from_right',
24
+ gestureEnabled: true,
25
+ gestureDirection: 'horizontal',
26
+ // 隐藏自带的头部
27
+ headerShown: false
28
+ }}>
29
+ <Stack.Screen name="index" options={{ title: "" }} />
30
+ </Stack>
31
+ <Toast />
32
+ </GestureHandlerRootView>
34
33
  </AuthProvider>
35
34
  );
36
35
  }
@@ -6,7 +6,8 @@ import reactHooks from 'eslint-plugin-react-hooks';
6
6
  import regexp from 'eslint-plugin-regexp';
7
7
  import pluginImport from 'eslint-plugin-import';
8
8
  import fontawesome6 from '../eslint-plugins/fontawesome6/index.js';
9
- import reanimated from '../eslint-plugins/reanimated/index.js'
9
+ import reanimated from '../eslint-plugins/reanimated/index.js';
10
+ import reactnative from '../eslint-plugins/react-native/index.js';
10
11
 
11
12
  export default [
12
13
  {
@@ -18,6 +19,7 @@ export default [
18
19
  '.expo/**', // 排除 Expo 自动生成的文件
19
20
  'tailwind.config.js', // 排除 Tailwind 配置文件
20
21
  '**/*.d.ts',
22
+ 'eslint.config.*',
21
23
  ],
22
24
  },
23
25
  regexp.configs["flat/recommended"],
@@ -57,6 +59,7 @@ export default [
57
59
  import: pluginImport,
58
60
  fontawesome6,
59
61
  reanimated,
62
+ reactnative,
60
63
  },
61
64
  rules: {
62
65
  // 关闭代码风格规则
@@ -77,6 +80,19 @@ export default [
77
80
  'react/jsx-uses-react': 'off',
78
81
  'fontawesome6/valid-name': 'error',
79
82
  'reanimated/ban-mix-use': 'error',
83
+ // 禁止使用 via.placeholder.com 服务
84
+ 'no-restricted-syntax': [
85
+ 'error',
86
+ {
87
+ 'selector': 'Literal[value=/via\\.placeholder\\.com/]',
88
+ 'message': 'via.placeholder.com 服务不可用,禁止在代码中使用',
89
+ },
90
+ {
91
+ 'selector': 'TemplateLiteral > TemplateElement[value.raw=/via\\.placeholder\\.com/]',
92
+ 'message': 'via.placeholder.com 服务不可用,禁止在代码中使用',
93
+ },
94
+ ],
95
+ 'reactnative/wrap-horizontal-scrollview-inside-view': ['error'],
80
96
  },
81
97
  },
82
98
 
@@ -0,0 +1,78 @@
1
+ @import 'tailwindcss';
2
+ @import 'uniwind';
3
+
4
+ @import './styles';
5
+
6
+ :root,
7
+ .light,
8
+ .default,
9
+ [data-theme="light"],
10
+ [data-theme="default"] {
11
+ /* Theme Colors (Light Mode) */
12
+ --accent: oklch(55.00% 0.2500 254.00);
13
+ --accent-foreground: oklch(99.11% 0 0);
14
+ --background: oklch(97.02% 0.0040 254.00);
15
+ --border: oklch(90.00% 0.0040 254.00);
16
+ --danger: oklch(65.32% 0.2347 25.76);
17
+ --danger-foreground: oklch(99.11% 0 0);
18
+ --default: oklch(94.00% 0.0040 254.00);
19
+ --default-foreground: oklch(21.03% 0.0059 254.00);
20
+ --field-background: oklch(100.00% 0.0020 254.00);
21
+ --field-foreground: oklch(21.03% 0.0059 254.00);
22
+ --field-placeholder: oklch(55.17% 0.0081 254.00);
23
+ --focus: oklch(55.00% 0.2500 254.00);
24
+ --foreground: oklch(21.03% 0.0059 254.00);
25
+ --muted: oklch(55.17% 0.0081 254.00);
26
+ --overlay: oklch(100.00% 0.0012 254.00);
27
+ --overlay-foreground: oklch(21.03% 0.0059 254.00);
28
+ --scrollbar: oklch(87.10% 0.0040 254.00);
29
+ --segment: oklch(100.00% 0.0040 254.00);
30
+ --segment-foreground: oklch(21.03% 0.0059 254.00);
31
+ --separator: oklch(92.00% 0.0040 254.00);
32
+ --success: oklch(73.29% 0.1951 150.83);
33
+ --success-foreground: oklch(21.03% 0.0059 150.83);
34
+ --surface: oklch(100.00% 0.0020 254.00);
35
+ --surface-foreground: oklch(21.03% 0.0059 254.00);
36
+ --warning: oklch(78.19% 0.1598 72.35);
37
+ --warning-foreground: oklch(21.03% 0.0059 72.35);
38
+
39
+ /* Border Radius */
40
+ --radius: 0.75rem;
41
+ --field-radius: 0.5rem;
42
+
43
+ /* Font Family */
44
+ /* Make sure to load Google Sans font in your app */
45
+ --font-sans: var(--font-google-sans);
46
+ }
47
+
48
+ .dark,
49
+ [data-theme="dark"] {
50
+ color-scheme: dark;
51
+ /* Theme Colors (Dark Mode) */
52
+ --accent: oklch(55.00% 0.2500 254.00);
53
+ --accent-foreground: oklch(99.11% 0 0);
54
+ --background: oklch(12.00% 0.0040 254.00);
55
+ --border: oklch(28.00% 0.0040 254.00);
56
+ --danger: oklch(59.40% 0.1983 24.65);
57
+ --danger-foreground: oklch(99.11% 0 0);
58
+ --default: oklch(27.40% 0.0040 254.00);
59
+ --default-foreground: oklch(99.11% 0 0);
60
+ --field-background: oklch(21.03% 0.0081 254.00);
61
+ --field-foreground: oklch(99.11% 0.0000 0.00);
62
+ --field-placeholder: oklch(70.50% 0.0081 254.00);
63
+ --focus: oklch(55.00% 0.2500 254.00);
64
+ --foreground: oklch(99.11% 0.0000 0.00);
65
+ --muted: oklch(70.50% 0.0081 254.00);
66
+ --overlay: oklch(21.03% 0.0081 254.00);
67
+ --overlay-foreground: oklch(99.11% 0.0000 0.00);
68
+ --scrollbar: oklch(70.50% 0.0040 254.00);
69
+ --segment: oklch(39.64% 0.0040 254.00);
70
+ --segment-foreground: oklch(99.11% 0.0000 0.00);
71
+ --separator: oklch(25.00% 0.0040 254.00);
72
+ --success: oklch(73.29% 0.1951 150.83);
73
+ --success-foreground: oklch(21.03% 0.0059 150.83);
74
+ --surface: oklch(21.03% 0.0081 254.00);
75
+ --surface-foreground: oklch(99.11% 0.0000 0.00);
76
+ --warning: oklch(82.03% 0.1399 76.36);
77
+ --warning-foreground: oklch(21.03% 0.0059 76.36);
78
+ }
@@ -1,6 +1,7 @@
1
1
  const { getDefaultConfig } = require('expo/metro-config');
2
2
  const { createProxyMiddleware } = require('http-proxy-middleware');
3
3
  const connect = require('connect');
4
+ const { withUniwindConfig } = require('uniwind/metro');
4
5
 
5
6
  const config = getDefaultConfig(__dirname);
6
7
 
@@ -118,4 +119,10 @@ config.server = {
118
119
  },
119
120
  };
120
121
 
121
- module.exports = config;
122
+ module.exports = withUniwindConfig(config, {
123
+ // relative path to your global.css file (from previous step)
124
+ cssEntryFile: './global.css',
125
+ // (optional) path where we gonna auto-generate typings
126
+ // defaults to project's root
127
+ dtsFile: './uniwind-types.d.ts'
128
+ });
@@ -15,37 +15,38 @@
15
15
  "preset": "jest-expo"
16
16
  },
17
17
  "dependencies": {
18
- "@expo/metro-runtime": "^6.1.2",
19
- "@expo/vector-icons": "^15.0.0",
20
- "@react-native-async-storage/async-storage": "^2.2.0",
21
- "@react-native-community/datetimepicker": "^8.5.0",
22
- "@react-native-community/slider": "^5.0.1",
23
- "@react-native-masked-view/masked-view": "^0.3.2",
24
- "@react-native-picker/picker": "^2.11.0",
18
+ "@expo/metro-runtime": "~6.1.2",
19
+ "@expo/vector-icons": "^15.0.3",
20
+ "@react-native-async-storage/async-storage": "2.2.0",
21
+ "@react-native-community/datetimepicker": "8.4.4",
22
+ "@react-native-community/slider": "5.0.1",
23
+ "@react-native-masked-view/masked-view": "0.3.2",
24
+ "@react-native-picker/picker": "2.11.1",
25
25
  "@react-navigation/bottom-tabs": "^7.2.0",
26
26
  "@react-navigation/native": "^7.0.14",
27
27
  "dayjs": "^1.11.19",
28
- "expo": "54.0.32",
29
- "expo-auth-session": "^7.0.9",
30
- "expo-av": "~16.0.6",
31
- "expo-blur": "~15.0.6",
28
+ "expo": "54.0.33",
29
+ "expo-auth-session": "~7.0.10",
30
+ "expo-av": "~16.0.8",
31
+ "expo-blur": "~15.0.8",
32
32
  "expo-camera": "~17.0.10",
33
- "expo-constants": "~18.0.8",
34
- "expo-crypto": "^15.0.7",
35
- "expo-font": "~14.0.7",
36
- "expo-haptics": "~15.0.6",
37
- "expo-image-picker": "~17.0.7",
38
- "expo-linear-gradient": "~15.0.6",
39
- "expo-linking": "~8.0.7",
40
- "expo-location": "~19.0.7",
41
- "expo-image": "^3.0.11",
42
- "js-base64": "^3.7.7",
43
- "expo-router": "~6.0.0",
44
- "expo-splash-screen": "~31.0.8",
45
- "expo-status-bar": "~3.0.7",
46
- "expo-symbols": "~1.0.6",
33
+ "expo-constants": "~18.0.13",
34
+ "expo-crypto": "~15.0.8",
35
+ "expo-file-system": "~19.0.21",
36
+ "expo-font": "~14.0.11",
37
+ "expo-haptics": "~15.0.8",
38
+ "expo-image": "~3.0.11",
39
+ "expo-image-picker": "~17.0.10",
40
+ "expo-linear-gradient": "~15.0.8",
41
+ "expo-linking": "~8.0.11",
42
+ "expo-location": "~19.0.8",
43
+ "expo-router": "~6.0.23",
44
+ "expo-splash-screen": "~31.0.13",
45
+ "expo-status-bar": "~3.0.9",
46
+ "expo-symbols": "~1.0.8",
47
47
  "expo-system-ui": "~6.0.9",
48
48
  "expo-web-browser": "~15.0.10",
49
+ "js-base64": "^3.7.7",
49
50
  "react": "19.1.0",
50
51
  "react-dom": "19.1.0",
51
52
  "react-native": "0.81.5",
@@ -53,25 +54,26 @@
53
54
  "react-native-gesture-handler": "~2.28.0",
54
55
  "react-native-keyboard-aware-scroll-view": "^0.9.5",
55
56
  "react-native-modal-datetime-picker": "18.0.0",
56
- "react-native-reanimated": "~4.1.0",
57
+ "react-native-reanimated": "~4.1.1",
57
58
  "react-native-safe-area-context": "~5.6.0",
58
59
  "react-native-screens": "~4.16.0",
59
- "react-native-svg": "15.15.0",
60
+ "react-native-svg": "15.12.1",
60
61
  "react-native-toast-message": "^2.3.3",
61
- "react-native-web": "^0.21.2",
62
- "react-native-webview": "~13.15.0",
62
+ "react-native-web": "~0.21.0",
63
+ "react-native-webview": "13.15.0",
63
64
  "react-native-worklets": "0.5.1",
64
65
  "zod": "^4.2.1"
65
66
  },
66
67
  "devDependencies": {
67
68
  "@babel/core": "^7.25.2",
68
- "babel-plugin-module-resolver": "^5.0.2",
69
- "babel-preset-expo": "^54.0.9",
70
69
  "@eslint/js": "^9.27.0",
71
70
  "@types/jest": "^29.5.12",
72
71
  "@types/react": "~19.1.0",
73
72
  "@types/react-test-renderer": "19.1.0",
73
+ "babel-plugin-module-resolver": "^5.0.2",
74
+ "babel-preset-expo": "^54.0.9",
74
75
  "chalk": "^4.1.2",
76
+ "connect": "^3.7.0",
75
77
  "depcheck": "^1.4.7",
76
78
  "esbuild": "0.27.2",
77
79
  "eslint": "^9.39.2",
@@ -82,13 +84,14 @@
82
84
  "eslint-plugin-react-hooks": "^7.0.1",
83
85
  "eslint-plugin-regexp": "^2.10.0",
84
86
  "globals": "^16.1.0",
87
+ "http-proxy-middleware": "^3.0.5",
85
88
  "jest": "^29.2.1",
86
- "jest-expo": "~54.0.10",
89
+ "jest-expo": "~54.0.17",
87
90
  "react-test-renderer": "19.1.0",
88
91
  "tsx": "^4.21.0",
89
92
  "typescript": "^5.8.3",
90
93
  "typescript-eslint": "^8.32.1",
91
- "connect": "^3.7.0",
92
- "http-proxy-middleware": "^3.0.5"
94
+ "tailwindcss": "^4.1.18",
95
+ "uniwind": "^1.2.7"
93
96
  }
94
97
  }
@@ -1,24 +1,18 @@
1
1
  import { View, Text } from 'react-native';
2
2
  import { Image } from 'expo-image';
3
3
 
4
- import { useTheme } from '@/hooks/useTheme';
5
4
  import { Screen } from '@/components/Screen';
6
- import { styles } from './styles';
7
5
 
8
6
  export default function DemoPage() {
9
- const { theme, isDark } = useTheme();
10
-
11
7
  return (
12
- <Screen backgroundColor={theme.backgroundRoot} statusBarStyle={isDark ? 'light' : 'dark'}>
13
- <View
14
- style={styles.container}
15
- >
8
+ <Screen backgroundColor="var(--background)" statusBarStyle="auto">
9
+ <View className="absolute top-0 left-0 w-full h-full flex flex-col items-center justify-center">
16
10
  <Image
17
- style={styles.logo}
11
+ className="w-[130px] h-[109px]"
18
12
  source="https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/coze-coding/expo/coze-loading.gif"
19
- ></Image>
20
- <Text style={{...styles.title, color: theme.textPrimary}}>APP 开发中</Text>
21
- <Text style={{...styles.description, color: theme.textSecondary}}>即将为您呈现应用界面</Text>
13
+ />
14
+ <Text className="text-base font-bold text-foreground">APP 开发中</Text>
15
+ <Text className="text-sm mt-2 text-muted">即将为您呈现应用界面</Text>
22
16
  </View>
23
17
  </Screen>
24
18
  );