@coze-arch/cli 0.0.1-alpha.f74941 → 0.0.1-alpha.ff64d9

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 (167) hide show
  1. package/lib/__templates__/expo/.coze +7 -2
  2. package/lib/__templates__/expo/.cozeproj/scripts/dev_build.sh +46 -0
  3. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +220 -0
  4. package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +47 -0
  5. package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +34 -0
  6. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +45 -0
  7. package/lib/__templates__/expo/README.md +66 -7
  8. package/lib/__templates__/expo/_gitignore +1 -1
  9. package/lib/__templates__/expo/_npmrc +3 -5
  10. package/lib/__templates__/expo/client/app/_layout.tsx +14 -14
  11. package/lib/__templates__/expo/client/app/demo.tsx +1 -0
  12. package/lib/__templates__/expo/client/app/index.tsx +1 -0
  13. package/lib/__templates__/expo/client/app.config.ts +75 -0
  14. package/lib/__templates__/expo/client/components/ThemedText.tsx +33 -0
  15. package/lib/__templates__/expo/client/components/ThemedView.tsx +38 -0
  16. package/lib/__templates__/expo/client/constants/theme.ts +786 -50
  17. package/lib/__templates__/expo/client/contexts/AuthContext.tsx +14 -107
  18. package/lib/__templates__/expo/client/declarations.d.ts +5 -0
  19. package/lib/__templates__/expo/client/hooks/useColorScheme.ts +34 -1
  20. package/lib/__templates__/expo/client/hooks/useTheme.ts +1 -1
  21. package/lib/__templates__/expo/client/metro.config.js +121 -0
  22. package/lib/__templates__/expo/client/package.json +93 -0
  23. package/lib/__templates__/expo/client/screens/demo/index.tsx +25 -0
  24. package/lib/__templates__/expo/client/screens/demo/styles.ts +28 -0
  25. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +36 -12
  26. package/lib/__templates__/expo/client/tsconfig.json +24 -0
  27. package/lib/__templates__/expo/client/utils/index.ts +1 -2
  28. package/lib/__templates__/expo/package.json +13 -92
  29. package/lib/__templates__/expo/pnpm-lock.yaml +675 -678
  30. package/lib/__templates__/expo/pnpm-workspace.yaml +3 -0
  31. package/lib/__templates__/expo/server/package.json +32 -0
  32. package/lib/__templates__/expo/{src → server/src}/index.ts +8 -2
  33. package/lib/__templates__/expo/server/tsconfig.json +24 -0
  34. package/lib/__templates__/expo/template.config.js +2 -1
  35. package/lib/__templates__/expo/tsconfig.json +1 -24
  36. package/lib/__templates__/nextjs/.coze +4 -3
  37. package/lib/__templates__/nextjs/README.md +341 -19
  38. package/lib/__templates__/nextjs/_npmrc +2 -1
  39. package/lib/__templates__/nextjs/components.json +21 -0
  40. package/lib/__templates__/nextjs/next.config.ts +12 -0
  41. package/lib/__templates__/nextjs/package.json +56 -2
  42. package/lib/__templates__/nextjs/pnpm-lock.yaml +7951 -1519
  43. package/lib/__templates__/nextjs/scripts/dev.sh +9 -27
  44. package/lib/__templates__/{react-rsbuild/scripts/build.sh → nextjs/scripts/prepare.sh} +0 -5
  45. package/lib/__templates__/nextjs/src/app/globals.css +124 -13
  46. package/lib/__templates__/nextjs/src/app/layout.tsx +19 -30
  47. package/lib/__templates__/nextjs/src/app/page.tsx +35 -23
  48. package/lib/__templates__/nextjs/src/components/ui/accordion.tsx +66 -0
  49. package/lib/__templates__/nextjs/src/components/ui/alert-dialog.tsx +157 -0
  50. package/lib/__templates__/nextjs/src/components/ui/alert.tsx +66 -0
  51. package/lib/__templates__/nextjs/src/components/ui/aspect-ratio.tsx +11 -0
  52. package/lib/__templates__/nextjs/src/components/ui/avatar.tsx +53 -0
  53. package/lib/__templates__/nextjs/src/components/ui/badge.tsx +46 -0
  54. package/lib/__templates__/nextjs/src/components/ui/breadcrumb.tsx +109 -0
  55. package/lib/__templates__/nextjs/src/components/ui/button-group.tsx +83 -0
  56. package/lib/__templates__/nextjs/src/components/ui/button.tsx +62 -0
  57. package/lib/__templates__/nextjs/src/components/ui/calendar.tsx +220 -0
  58. package/lib/__templates__/nextjs/src/components/ui/card.tsx +92 -0
  59. package/lib/__templates__/nextjs/src/components/ui/carousel.tsx +241 -0
  60. package/lib/__templates__/nextjs/src/components/ui/chart.tsx +357 -0
  61. package/lib/__templates__/nextjs/src/components/ui/checkbox.tsx +32 -0
  62. package/lib/__templates__/nextjs/src/components/ui/collapsible.tsx +33 -0
  63. package/lib/__templates__/nextjs/src/components/ui/command.tsx +184 -0
  64. package/lib/__templates__/nextjs/src/components/ui/context-menu.tsx +252 -0
  65. package/lib/__templates__/nextjs/src/components/ui/dialog.tsx +143 -0
  66. package/lib/__templates__/nextjs/src/components/ui/drawer.tsx +135 -0
  67. package/lib/__templates__/nextjs/src/components/ui/dropdown-menu.tsx +257 -0
  68. package/lib/__templates__/nextjs/src/components/ui/empty.tsx +104 -0
  69. package/lib/__templates__/nextjs/src/components/ui/field.tsx +248 -0
  70. package/lib/__templates__/nextjs/src/components/ui/form.tsx +167 -0
  71. package/lib/__templates__/nextjs/src/components/ui/hover-card.tsx +44 -0
  72. package/lib/__templates__/nextjs/src/components/ui/input-group.tsx +170 -0
  73. package/lib/__templates__/nextjs/src/components/ui/input-otp.tsx +77 -0
  74. package/lib/__templates__/nextjs/src/components/ui/input.tsx +21 -0
  75. package/lib/__templates__/nextjs/src/components/ui/item.tsx +193 -0
  76. package/lib/__templates__/nextjs/src/components/ui/kbd.tsx +28 -0
  77. package/lib/__templates__/nextjs/src/components/ui/label.tsx +24 -0
  78. package/lib/__templates__/nextjs/src/components/ui/menubar.tsx +276 -0
  79. package/lib/__templates__/nextjs/src/components/ui/navigation-menu.tsx +168 -0
  80. package/lib/__templates__/nextjs/src/components/ui/pagination.tsx +127 -0
  81. package/lib/__templates__/nextjs/src/components/ui/popover.tsx +48 -0
  82. package/lib/__templates__/nextjs/src/components/ui/progress.tsx +31 -0
  83. package/lib/__templates__/nextjs/src/components/ui/radio-group.tsx +45 -0
  84. package/lib/__templates__/nextjs/src/components/ui/resizable.tsx +63 -0
  85. package/lib/__templates__/nextjs/src/components/ui/scroll-area.tsx +58 -0
  86. package/lib/__templates__/nextjs/src/components/ui/select.tsx +190 -0
  87. package/lib/__templates__/nextjs/src/components/ui/separator.tsx +28 -0
  88. package/lib/__templates__/nextjs/src/components/ui/sheet.tsx +139 -0
  89. package/lib/__templates__/nextjs/src/components/ui/sidebar.tsx +724 -0
  90. package/lib/__templates__/nextjs/src/components/ui/skeleton.tsx +13 -0
  91. package/lib/__templates__/nextjs/src/components/ui/slider.tsx +63 -0
  92. package/lib/__templates__/nextjs/src/components/ui/sonner.tsx +40 -0
  93. package/lib/__templates__/nextjs/src/components/ui/spinner.tsx +16 -0
  94. package/lib/__templates__/nextjs/src/components/ui/switch.tsx +31 -0
  95. package/lib/__templates__/nextjs/src/components/ui/table.tsx +116 -0
  96. package/lib/__templates__/nextjs/src/components/ui/tabs.tsx +66 -0
  97. package/lib/__templates__/nextjs/src/components/ui/textarea.tsx +18 -0
  98. package/lib/__templates__/nextjs/src/components/ui/toggle-group.tsx +83 -0
  99. package/lib/__templates__/nextjs/src/components/ui/toggle.tsx +47 -0
  100. package/lib/__templates__/nextjs/src/components/ui/tooltip.tsx +61 -0
  101. package/lib/__templates__/nextjs/src/hooks/use-mobile.ts +19 -0
  102. package/lib/__templates__/nextjs/src/lib/utils.ts +6 -0
  103. package/lib/__templates__/nextjs/template.config.js +32 -2
  104. package/lib/__templates__/templates.json +61 -74
  105. package/lib/__templates__/vite/.coze +4 -3
  106. package/lib/__templates__/vite/README.md +204 -26
  107. package/lib/__templates__/vite/_npmrc +2 -1
  108. package/lib/__templates__/vite/eslint.config.mjs +9 -0
  109. package/lib/__templates__/vite/package.json +6 -2
  110. package/lib/__templates__/vite/pnpm-lock.yaml +3486 -19
  111. package/lib/__templates__/vite/scripts/dev.sh +7 -26
  112. package/lib/__templates__/{rsbuild/scripts/build.sh → vite/scripts/prepare.sh} +0 -5
  113. package/lib/__templates__/vite/src/main.ts +1 -2
  114. package/lib/__templates__/vite/template.config.js +39 -6
  115. package/lib/__templates__/vite/vite.config.ts +3 -3
  116. package/lib/cli.js +634 -313
  117. package/package.json +11 -4
  118. package/lib/__templates__/expo/.cozeproj/scripts/deploy_build.sh +0 -109
  119. package/lib/__templates__/expo/.cozeproj/scripts/deploy_run.sh +0 -257
  120. package/lib/__templates__/expo/app.json +0 -63
  121. package/lib/__templates__/expo/babel.config.js +0 -9
  122. package/lib/__templates__/expo/client/app/(tabs)/_layout.tsx +0 -43
  123. package/lib/__templates__/expo/client/app/(tabs)/home.tsx +0 -1
  124. package/lib/__templates__/expo/client/app/(tabs)/index.tsx +0 -7
  125. package/lib/__templates__/expo/client/app/+not-found.tsx +0 -79
  126. package/lib/__templates__/expo/client/index.js +0 -11
  127. package/lib/__templates__/expo/client/screens/home/index.tsx +0 -54
  128. package/lib/__templates__/expo/client/screens/home/styles.ts +0 -332
  129. package/lib/__templates__/expo/metro.config.js +0 -53
  130. package/lib/__templates__/nextjs/.vscode/settings.json +0 -121
  131. package/lib/__templates__/react-rsbuild/.coze +0 -11
  132. package/lib/__templates__/react-rsbuild/.vscode/settings.json +0 -121
  133. package/lib/__templates__/react-rsbuild/README.md +0 -61
  134. package/lib/__templates__/react-rsbuild/_gitignore +0 -97
  135. package/lib/__templates__/react-rsbuild/_npmrc +0 -22
  136. package/lib/__templates__/react-rsbuild/package.json +0 -31
  137. package/lib/__templates__/react-rsbuild/pnpm-lock.yaml +0 -997
  138. package/lib/__templates__/react-rsbuild/rsbuild.config.ts +0 -13
  139. package/lib/__templates__/react-rsbuild/scripts/dev.sh +0 -51
  140. package/lib/__templates__/react-rsbuild/scripts/start.sh +0 -15
  141. package/lib/__templates__/react-rsbuild/src/App.tsx +0 -60
  142. package/lib/__templates__/react-rsbuild/src/index.css +0 -21
  143. package/lib/__templates__/react-rsbuild/src/index.html +0 -12
  144. package/lib/__templates__/react-rsbuild/src/index.tsx +0 -16
  145. package/lib/__templates__/react-rsbuild/tailwind.config.js +0 -9
  146. package/lib/__templates__/react-rsbuild/template.config.js +0 -54
  147. package/lib/__templates__/react-rsbuild/tsconfig.json +0 -17
  148. package/lib/__templates__/rsbuild/.coze +0 -11
  149. package/lib/__templates__/rsbuild/.vscode/settings.json +0 -7
  150. package/lib/__templates__/rsbuild/README.md +0 -61
  151. package/lib/__templates__/rsbuild/_gitignore +0 -97
  152. package/lib/__templates__/rsbuild/_npmrc +0 -22
  153. package/lib/__templates__/rsbuild/package.json +0 -24
  154. package/lib/__templates__/rsbuild/pnpm-lock.yaml +0 -888
  155. package/lib/__templates__/rsbuild/rsbuild.config.ts +0 -12
  156. package/lib/__templates__/rsbuild/scripts/dev.sh +0 -51
  157. package/lib/__templates__/rsbuild/scripts/start.sh +0 -15
  158. package/lib/__templates__/rsbuild/src/index.css +0 -21
  159. package/lib/__templates__/rsbuild/src/index.html +0 -12
  160. package/lib/__templates__/rsbuild/src/index.ts +0 -5
  161. package/lib/__templates__/rsbuild/src/main.ts +0 -65
  162. package/lib/__templates__/rsbuild/tailwind.config.js +0 -9
  163. package/lib/__templates__/rsbuild/template.config.js +0 -56
  164. package/lib/__templates__/rsbuild/tsconfig.json +0 -16
  165. package/lib/__templates__/vite/.vscode/settings.json +0 -7
  166. /package/lib/__templates__/expo/{eslint-formatter-simple.mjs → client/eslint-formatter-simple.mjs} +0 -0
  167. /package/lib/__templates__/expo/{eslint.config.mjs → client/eslint.config.mjs} +0 -0
@@ -4,19 +4,15 @@
4
4
  *
5
5
  * 基于固定的 API 接口实现,可复用到其他项目
6
6
  * 其他项目使用时,只需修改 @api 的导入路径指向项目的 api 模块
7
+ *
8
+ * 注意:
9
+ * - 如果需要登录/鉴权场景,请扩展本文件,完善 login/logout、token 管理、用户信息获取与刷新等逻辑
10
+ * - 将示例中的占位实现替换为项目实际的接口调用与状态管理
7
11
  */
8
- import React, {
9
- createContext,
10
- useContext,
11
- useState,
12
- useEffect,
13
- ReactNode,
14
- } from "react";
15
- import AsyncStorage from "@react-native-async-storage/async-storage";
16
- //import { UserOut, UsersService, AuthenticationService } from "@api";
12
+ import React, { createContext, useContext, ReactNode } from "react";
17
13
 
18
14
  interface UserOut {
19
-
15
+
20
16
  }
21
17
 
22
18
  interface AuthContextType {
@@ -31,105 +27,16 @@ interface AuthContextType {
31
27
 
32
28
  const AuthContext = createContext<AuthContextType | undefined>(undefined);
33
29
 
34
- export const AuthProvider: React.FC<{ children: ReactNode }> = ({
35
- children,
36
- }) => {
37
- const [user, setUser] = useState<UserOut | null>(null);
38
- const [token, setToken] = useState<string | null>(null);
39
- const [isLoading, setIsLoading] = useState(true);
40
-
41
- useEffect(() => {
42
- loadAuthData();
43
- }, []);
44
-
45
- const loadAuthData = async () => {
46
- try {
47
- const results = await AsyncStorage.multiGet(["access_token", "user_data"]);
48
- const storedToken = results?.[0]?.[1] ?? null;
49
- const storedUser = results?.[1]?.[1] ?? null;
50
-
51
- if (!storedToken) {
52
- setToken(null);
53
- setUser(null);
54
- await AsyncStorage.multiRemove(["access_token", "user_data"]);
55
- return;
56
- }
57
-
58
- if (storedToken && storedUser) {
59
- setToken(storedToken);
60
- setUser(JSON.parse(storedUser));
61
- } else if (storedToken && !storedUser) {
62
- // 若仅有 token,主动拉取当前用户信息
63
- setToken(storedToken);
64
- try {
65
- // const me = await UsersService.getCurrentUserApiV1UsersMeGet();
66
- //if (me?.success && me.data) {
67
- // setUser(me.data);
68
- // await AsyncStorage.setItem("user_data", JSON.stringify(me.data));
69
- //}
70
- } catch (e) {
71
- // 拉取失败则保持未登录状态
72
- console.error("Failed to fetch current user with stored token:", e);
73
- }
74
- }
75
- } catch (error) {
76
- console.error("Failed to load auth data:", error);
77
- } finally {
78
- setIsLoading(false);
79
- }
80
- };
81
-
82
- const login = async (newToken: string) => {
83
- try {
84
- setToken(newToken);
85
- // 统一写入 access_token,供 OpenAPI 读取并自动携带
86
- await AsyncStorage.setItem("access_token", newToken);
87
- // 登录后拉取当前用户并缓存
88
- try {
89
- const me = await UsersService.getCurrentUserApiV1UsersMeGet();
90
- if (me?.success && me.data) {
91
- setUser(me.data);
92
- await AsyncStorage.setItem("user_data", JSON.stringify(me.data));
93
- }
94
- } catch (e) {
95
- console.error("Fetch current user after login failed:", e);
96
- }
97
- } catch (error) {
98
- console.error("Login failed:", error);
99
- throw error;
100
- }
101
- };
102
-
103
- const logout = async () => {
104
- try {
105
- // await AuthenticationService.logoutApiV1AuthLogoutPost(true);
106
- } catch(error) {
107
- console.warn('Logout failed:', error);
108
- }
109
- // remove token
110
- setToken(null);
111
- setUser(null);
112
- await AsyncStorage.multiRemove(["auth_token", "access_token", "user_data"]);
113
- };
114
-
115
- const updateUser = (userData: Partial<UserOut>) => {
116
- if (user) {
117
- const updatedUser = { ...user, ...userData };
118
- setUser(updatedUser);
119
- AsyncStorage.setItem("user_data", JSON.stringify(updatedUser));
120
- }
121
- };
122
-
30
+ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
123
31
  const value: AuthContextType = {
124
- user,
125
- token,
126
- isAuthenticated: !!token && !!user,
127
- isLoading,
128
- login,
129
- logout,
130
- updateUser,
32
+ user: null,
33
+ token: null,
34
+ isAuthenticated: false,
35
+ isLoading: false,
36
+ login: async (token: string) => {},
37
+ logout: async () => {},
38
+ updateUser: () => {},
131
39
  };
132
-
133
40
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
134
41
  };
135
42
 
@@ -0,0 +1,5 @@
1
+ // declarations.d.ts
2
+
3
+ declare module 'expo-file-system/legacy' {
4
+ export * from 'expo-file-system';
5
+ }
@@ -1 +1,34 @@
1
- export { useColorScheme } from "react-native";
1
+ import { useEffect, useState } from 'react';
2
+ import { ColorSchemeName, useColorScheme as useReactNativeColorScheme, Platform } from 'react-native';
3
+
4
+ export function useColorScheme() {
5
+ const systemColorScheme = useReactNativeColorScheme();
6
+ const [colorScheme, setColorScheme] = useState<ColorSchemeName>(systemColorScheme);
7
+
8
+ useEffect(() => {
9
+ setColorScheme(systemColorScheme);
10
+ }, [systemColorScheme])
11
+
12
+ useEffect(() => {
13
+ function handleMessage(e: MessageEvent<{ event: string; colorScheme: ColorSchemeName; } | undefined>) {
14
+ if (e.data?.event === 'coze.workbench.colorScheme') {
15
+ const cs = e.data.colorScheme;
16
+ if (typeof cs === 'string') {
17
+ setColorScheme(cs);
18
+ }
19
+ }
20
+ }
21
+
22
+ if (Platform.OS === 'web') {
23
+ window.addEventListener('message', handleMessage, false);
24
+ }
25
+
26
+ return () => {
27
+ if (Platform.OS === 'web') {
28
+ window.removeEventListener('message', handleMessage, false);
29
+ }
30
+ }
31
+ }, []);
32
+
33
+ return colorScheme;
34
+ }
@@ -4,7 +4,7 @@ import { useColorScheme } from "@/hooks/useColorScheme";
4
4
  export function useTheme() {
5
5
  const colorScheme = useColorScheme();
6
6
  const isDark = colorScheme === "dark";
7
- const theme = Colors[colorScheme ?? "light"];
7
+ const theme = Colors[(colorScheme as "light" | "dark") ?? "light"];
8
8
 
9
9
  return {
10
10
  theme,
@@ -0,0 +1,121 @@
1
+ const { getDefaultConfig } = require('expo/metro-config');
2
+ const { createProxyMiddleware } = require('http-proxy-middleware');
3
+ const connect = require('connect');
4
+
5
+ const config = getDefaultConfig(__dirname);
6
+
7
+ // 安全地获取 Expo 的默认排除列表
8
+ const existingBlockList = [].concat(config.resolver.blockList || []);
9
+
10
+ config.resolver.blockList = [
11
+ ...existingBlockList,
12
+ /.*\/\.expo\/.*/, // Expo 的缓存和构建产物目录
13
+
14
+ // 1. 原生代码 (Java/C++/Objective-C)
15
+ /.*\/react-native\/ReactAndroid\/.*/,
16
+ /.*\/react-native\/ReactCommon\/.*/,
17
+
18
+ // 2. 纯开发和调试工具
19
+ // 这些工具只在开发电脑上运行,不会被打包到应用中
20
+ /.*\/@typescript-eslint\/eslint-plugin\/.*/,
21
+
22
+ // 3. 构建时数据
23
+ // 这个数据库只在打包过程中使用,应用运行时不需要
24
+ /.*\/caniuse-lite\/data\/.*/,
25
+
26
+ // 4. 通用规则
27
+ /.*\/__tests__\/.*/, // 排除所有测试目录
28
+ /.*\.git\/.*/, // 排除 Git 目录
29
+ ];
30
+
31
+ const BACKEND_TARGET = 'http://localhost:9091';
32
+
33
+ const apiProxy = createProxyMiddleware({
34
+ target: BACKEND_TARGET,
35
+ changeOrigin: true,
36
+ logLevel: 'debug',
37
+ proxyTimeout: 86400000,
38
+ onProxyReq: (proxyReq, req) => {
39
+ const accept = req.headers.accept || '';
40
+ if (accept.includes('text/event-stream')) {
41
+ proxyReq.setHeader('accept-encoding', 'identity');
42
+ }
43
+ },
44
+ onProxyRes: (proxyRes, req, res) => {
45
+ const contentType = proxyRes.headers['content-type'] || '';
46
+ if (contentType.includes('text/event-stream') || contentType.includes('application/stream')) {
47
+ res.setHeader('Cache-Control', 'no-cache');
48
+ res.setHeader('Connection', 'keep-alive');
49
+ res.setHeader('X-Accel-Buffering', 'no');
50
+ if (typeof res.flushHeaders === 'function') {
51
+ try { res.flushHeaders(); } catch {}
52
+ }
53
+ }
54
+ },
55
+ });
56
+
57
+ const streamProxy = createProxyMiddleware({
58
+ target: BACKEND_TARGET,
59
+ changeOrigin: true,
60
+ logLevel: 'debug',
61
+ ws: true,
62
+ proxyTimeout: 86400000,
63
+ onProxyReq: (proxyReq, req) => {
64
+ const upgrade = req.headers.upgrade;
65
+ const accept = req.headers.accept || '';
66
+ if (upgrade && upgrade.toLowerCase() === 'websocket') {
67
+ proxyReq.setHeader('Connection', 'upgrade');
68
+ proxyReq.setHeader('Upgrade', req.headers.upgrade);
69
+ } else if (accept.includes('text/event-stream')) {
70
+ proxyReq.setHeader('accept-encoding', 'identity');
71
+ proxyReq.setHeader('Connection', 'keep-alive');
72
+ }
73
+ },
74
+ onProxyRes: (proxyRes, req, res) => {
75
+ const contentType = proxyRes.headers['content-type'] || '';
76
+ if (contentType.includes('text/event-stream') || contentType.includes('application/stream')) {
77
+ res.setHeader('Cache-Control', 'no-cache');
78
+ res.setHeader('Connection', 'keep-alive');
79
+ res.setHeader('X-Accel-Buffering', 'no');
80
+ if (typeof res.flushHeaders === 'function') {
81
+ try { res.flushHeaders(); } catch {}
82
+ }
83
+ }
84
+ },
85
+ });
86
+
87
+ const shouldProxyToBackend = (url) => {
88
+ if (!url) return false;
89
+ if (/^\/api\/v\d+\//.test(url)) {
90
+ return true;
91
+ }
92
+ return false;
93
+ };
94
+
95
+ const isWebSocketRequest = (req) =>
96
+ !!(req.headers.upgrade && req.headers.upgrade.toLowerCase() === 'websocket');
97
+ const isSSERequest = (req) => {
98
+ const accept = req.headers.accept || '';
99
+ return accept.includes('text/event-stream');
100
+ };
101
+
102
+ config.server = {
103
+ ...config.server,
104
+ enhanceMiddleware: (metroMiddleware, metroServer) => {
105
+ return connect()
106
+ .use((req, res, next) => {
107
+ if (shouldProxyToBackend(req.url)) {
108
+ console.log(`[Metro Proxy] Forwarding ${req.method} ${req.url}`);
109
+
110
+ if (isWebSocketRequest(req) || isSSERequest(req)) {
111
+ return streamProxy(req, res, next);
112
+ }
113
+ return apiProxy(req, res, next);
114
+ }
115
+ next();
116
+ })
117
+ .use(metroMiddleware);
118
+ },
119
+ };
120
+
121
+ module.exports = config;
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "expo-app",
3
+ "description": "<%= appName %>",
4
+ "main": "expo-router/entry",
5
+ "private": true,
6
+ "scripts": {
7
+ "check-deps": "npx depcheck",
8
+ "postinstall": "npm run install-missing",
9
+ "install-missing": "node ./scripts/install-missing-deps.js",
10
+ "lint": "expo lint",
11
+ "start": "expo start --web --clear",
12
+ "test": "jest --watchAll"
13
+ },
14
+ "jest": {
15
+ "preset": "jest-expo"
16
+ },
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",
25
+ "@react-navigation/bottom-tabs": "^7.2.0",
26
+ "@react-navigation/native": "^7.0.14",
27
+ "dayjs": "^1.11.19",
28
+ "expo": "^54.0.7",
29
+ "expo-auth-session": "^7.0.9",
30
+ "expo-av": "~16.0.6",
31
+ "expo-blur": "~15.0.6",
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
+ "expo-router": "~6.0.0",
43
+ "expo-splash-screen": "~31.0.8",
44
+ "expo-status-bar": "~3.0.7",
45
+ "expo-symbols": "~1.0.6",
46
+ "expo-system-ui": "~6.0.9",
47
+ "expo-web-browser": "~15.0.10",
48
+ "react": "19.1.0",
49
+ "react-dom": "19.1.0",
50
+ "react-native": "0.81.5",
51
+ "react-native-chart-kit": "^6.12.0",
52
+ "react-native-gesture-handler": "~2.28.0",
53
+ "react-native-keyboard-aware-scroll-view": "^0.9.5",
54
+ "react-native-modal-datetime-picker": "18.0.0",
55
+ "react-native-reanimated": "~4.1.0",
56
+ "react-native-safe-area-context": "~5.6.0",
57
+ "react-native-screens": "~4.16.0",
58
+ "react-native-svg": "15.15.0",
59
+ "react-native-toast-message": "^2.3.3",
60
+ "react-native-web": "^0.21.2",
61
+ "react-native-webview": "~13.15.0",
62
+ "react-native-worklets": "0.5.1",
63
+ "zod": "^4.2.1"
64
+ },
65
+ "devDependencies": {
66
+ "@babel/core": "^7.25.2",
67
+ "babel-plugin-module-resolver": "^5.0.2",
68
+ "babel-preset-expo": "^54.0.9",
69
+ "@eslint/js": "^9.27.0",
70
+ "@types/jest": "^29.5.12",
71
+ "@types/react": "~19.1.0",
72
+ "@types/react-test-renderer": "19.1.0",
73
+ "chalk": "^4.1.2",
74
+ "depcheck": "^1.4.7",
75
+ "esbuild": "0.27.2",
76
+ "eslint": "^9.39.2",
77
+ "eslint-formatter-compact": "^9.0.1",
78
+ "eslint-import-resolver-typescript": "^4.4.4",
79
+ "eslint-plugin-import": "^2.32.0",
80
+ "eslint-plugin-react": "^7.37.5",
81
+ "eslint-plugin-react-hooks": "^7.0.1",
82
+ "eslint-plugin-regexp": "^2.10.0",
83
+ "globals": "^16.1.0",
84
+ "jest": "^29.2.1",
85
+ "jest-expo": "~54.0.10",
86
+ "react-test-renderer": "19.1.0",
87
+ "tsx": "^4.21.0",
88
+ "typescript": "^5.8.3",
89
+ "typescript-eslint": "^8.32.1",
90
+ "connect": "^3.7.0",
91
+ "http-proxy-middleware": "^3.0.5"
92
+ }
93
+ }
@@ -0,0 +1,25 @@
1
+ import { View, Text } from 'react-native';
2
+ import { Image } from 'expo-image';
3
+
4
+ import { useTheme } from '@/hooks/useTheme';
5
+ import { Screen } from '@/components/Screen';
6
+ import { styles } from './styles';
7
+
8
+ export default function DemoPage() {
9
+ const { theme, isDark } = useTheme();
10
+
11
+ return (
12
+ <Screen backgroundColor={theme.backgroundRoot} statusBarStyle={isDark ? 'light' : 'dark'}>
13
+ <View
14
+ style={styles.container}
15
+ >
16
+ <Image
17
+ style={styles.logo}
18
+ 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>
22
+ </View>
23
+ </Screen>
24
+ );
25
+ }
@@ -0,0 +1,28 @@
1
+ import { Spacing } from '@/constants/theme';
2
+ import { StyleSheet } from 'react-native';
3
+
4
+ export const styles = StyleSheet.create({
5
+ container: {
6
+ position: 'absolute',
7
+ top: 0,
8
+ left: 0,
9
+ width: '100%',
10
+ height: '100%',
11
+ display: 'flex',
12
+ flexDirection: 'column',
13
+ alignItems: 'center',
14
+ justifyContent: 'center',
15
+ },
16
+ logo: {
17
+ width: 130,
18
+ height: 109,
19
+ },
20
+ title: {
21
+ fontSize: 16,
22
+ fontWeight: 'bold',
23
+ },
24
+ description: {
25
+ fontSize: 14,
26
+ marginTop: Spacing.sm,
27
+ },
28
+ });
@@ -18,7 +18,7 @@ try {
18
18
  try {
19
19
  depcheckOutput = execSync('npx depcheck --json', {
20
20
  encoding: 'utf-8',
21
- stdio: ['pipe', 'pipe', 'pipe']
21
+ stdio: ['pipe', 'pipe', 'pipe'],
22
22
  });
23
23
  } catch (execError) {
24
24
  // depcheck 返回非零退出码时仍然有输出
@@ -30,10 +30,34 @@ try {
30
30
  }
31
31
 
32
32
  const result = JSON.parse(depcheckOutput);
33
-
33
+
34
34
  // 获取缺失的依赖
35
35
  const missing = result.missing || {};
36
- const missingPackages = Object.keys(missing).filter(pkg => !pkg.startsWith('@api/') && !pkg.startsWith('@/') && pkg !== '@api');
36
+
37
+ // 需要忽略的文件模式
38
+ const ignoreFilePatterns = [
39
+ /template\.config\.(ts|js)$/, // 模板配置文件
40
+ /\.template\./, // 其他模板文件
41
+ ];
42
+
43
+ // 过滤包:排除内部别名和只被模板文件引用的包
44
+ const missingPackages = Object.keys(missing).filter(pkg => {
45
+ // 排除内部路径别名
46
+ if (pkg.startsWith('@api/') || pkg.startsWith('@/') || pkg === '@api') {
47
+ return false;
48
+ }
49
+
50
+ // 获取引用该包的文件列表
51
+ const referencingFiles = missing[pkg] || [];
52
+
53
+ // 过滤掉模板配置文件
54
+ const nonTemplateFiles = referencingFiles.filter(file => {
55
+ return !ignoreFilePatterns.some(pattern => pattern.test(file));
56
+ });
57
+
58
+ // 只有当存在非模板文件引用时才保留该包
59
+ return nonTemplateFiles.length > 0;
60
+ });
37
61
 
38
62
  if (missingPackages.length === 0) {
39
63
  console.log('✅ 没有发现缺失的依赖!');
@@ -44,30 +68,31 @@ try {
44
68
  missingPackages.forEach((pkg, index) => {
45
69
  const files = missing[pkg];
46
70
  console.log(` ${index + 1}. ${pkg}`);
47
- console.log(` 被引用于: ${files.slice(0, 2).join(', ')}${files.length > 2 ? ' ...' : ''}`);
71
+ console.log(
72
+ ` 被引用于: ${files.slice(0, 2).join(', ')}${files.length > 2 ? ' ...' : ''}`,
73
+ );
48
74
  });
49
75
 
50
76
  console.log('\n🚀 开始安装...\n');
51
77
 
52
78
  // 使用 expo install 安装所有缺失的包
53
79
  const packagesToInstall = missingPackages.join(' ');
54
-
80
+
55
81
  try {
56
82
  execSync(`pnpm expo install ${packagesToInstall}`, {
57
- stdio: 'inherit'
83
+ stdio: 'inherit',
58
84
  });
59
-
85
+
60
86
  console.log('\n✅ 所有缺失的依赖已安装完成!');
61
87
  } catch (installError) {
62
88
  console.log('\n⚠️ expo install 失败,尝试使用 npm install...\n');
63
-
89
+
64
90
  execSync(`npm install ${packagesToInstall}`, {
65
- stdio: 'inherit'
91
+ stdio: 'inherit',
66
92
  });
67
-
93
+
68
94
  console.log('\n✅ 所有缺失的依赖已通过 npm 安装完成!');
69
95
  }
70
-
71
96
  } catch (error) {
72
97
  if (error.message.includes('depcheck')) {
73
98
  console.error('❌ depcheck 未安装或运行失败');
@@ -77,4 +102,3 @@ try {
77
102
  }
78
103
  process.exit(1);
79
104
  }
80
-
@@ -0,0 +1,24 @@
1
+ {
2
+ "extends": "expo/tsconfig.base",
3
+ "compilerOptions": {
4
+ "skipLibCheck": true,
5
+ "jsx": "react-jsx",
6
+ "baseUrl": ".",
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "paths": {
10
+ "@/*": ["./*"]
11
+ }
12
+ },
13
+ "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"],
14
+ "exclude": [
15
+ "node_modules",
16
+ "**/*.spec.ts",
17
+ "**/*.test.ts",
18
+ "**/*.spec.tsx",
19
+ "**/*.test.tsx",
20
+ "dist",
21
+ "build",
22
+ ".expo"
23
+ ]
24
+ }
@@ -1,4 +1,3 @@
1
- // import { OpenAPI } from '@api'; // 如果使用 openapi 客户端,请取消注释并确保安装
2
1
  import dayjs from 'dayjs';
3
2
  import utc from 'dayjs/plugin/utc';
4
3
  dayjs.extend(utc);
@@ -26,7 +25,7 @@ export const buildAssetUrl = (url?: string | null, w?: number, h?: number): stri
26
25
  // 3. 构造参数,保留原有 Query (如有)
27
26
  const separator = abs.includes('?') ? '&' : '?';
28
27
  const query = [
29
- w ? `w=${Math.floor(w)}` : '',
28
+ w ? `w=${Math.floor(w)}` : '',
30
29
  h ? `h=${Math.floor(h)}` : ''
31
30
  ].filter(Boolean).join('&');
32
31
  return `${abs}${separator}${query}`;