@coze-arch/cli 0.1.4-alpha.b8ffd5 → 0.1.4-alpha.d384e3

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.
@@ -48,77 +48,62 @@ trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT
48
48
 
49
49
  mkdir -p "$WORK_DIR"
50
50
 
51
- # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
52
- # workspace directories stay real too, so pnpm never writes them to Drive.
53
- mirror_root() {
51
+ # Previous versions mirrored the whole project into WORK_DIR. That gives pnpm
52
+ # and framework dev servers two paths for the same source tree, which breaks
53
+ # file watching and on-demand compilation. Keep only managed local outputs.
54
+ cleanup_legacy_workspace() {
55
+ local workspace_dir="$1" entry name
56
+ if [ -L "$workspace_dir" ] || { [ -e "$workspace_dir" ] && [ ! -d "$workspace_dir" ]; }; then
57
+ rm -rf "$workspace_dir"
58
+ return
59
+ fi
60
+ if [ ! -d "$workspace_dir" ]; then
61
+ return 0
62
+ fi
63
+
64
+ while IFS= read -r -d '' entry; do
65
+ name="$(basename "$entry")"
66
+ [ "$name" = "node_modules" ] || rm -rf "$entry"
67
+ done < <(find "$workspace_dir" -mindepth 1 -maxdepth 1 -print0)
68
+ }
69
+
70
+ cleanup_legacy_shadow_project() {
54
71
  local entry name
55
72
  while IFS= read -r -d '' entry; do
56
73
  name="$(basename "$entry")"
57
74
  case "$name" in
58
- node_modules|pnpm-lock.yaml) continue ;;
59
- client|server)
60
- [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
61
- ;;
75
+ node_modules|client|server) continue ;;
62
76
  esac
63
77
  rm -rf "$entry"
64
78
  done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
65
79
 
66
- while IFS= read -r -d '' entry; do
67
- name="$(basename "$entry")"
68
- case "$name" in
69
- node_modules|pnpm-lock.yaml) continue ;;
70
- client|server)
71
- [ -f "$entry/package.json" ] && continue
72
- ;;
73
- esac
74
- ln -s "$entry" "$WORK_DIR/$name"
75
- done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
80
+ for workspace in client server; do
81
+ cleanup_legacy_workspace "$WORK_DIR/$workspace"
82
+ done
76
83
  }
77
84
 
78
- mirror_workspace() {
79
- local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
80
- local entry name
81
- if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
82
- rm -rf "$work_dir"
83
- fi
84
- mkdir -p "$work_dir"
85
-
86
- while IFS= read -r -d '' entry; do
87
- [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
88
- done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
89
-
90
- while IFS= read -r -d '' entry; do
91
- name="$(basename "$entry")"
92
- [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
93
- done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
85
+ copy_install_metadata() {
86
+ local filename source_file target_file workspace
87
+ for filename in package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc; do
88
+ source_file="$PROJECT_ROOT/$filename"
89
+ target_file="$WORK_DIR/$filename"
90
+ rm -f "$target_file"
91
+ if [ -f "$source_file" ]; then
92
+ cp "$source_file" "$target_file"
93
+ fi
94
+ done
95
+
96
+ for workspace in client server; do
97
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
98
+ mkdir -p "$WORK_DIR/$workspace"
99
+ rm -f "$WORK_DIR/$workspace/package.json"
100
+ cp "$PROJECT_ROOT/$workspace/package.json" "$WORK_DIR/$workspace/package.json"
101
+ else
102
+ rm -rf "$WORK_DIR/$workspace"
103
+ fi
104
+ done
94
105
  }
95
106
 
96
- mirror_root
97
- for workspace in client server; do
98
- if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
99
- mirror_workspace "$workspace"
100
- fi
101
- done
102
-
103
- # pnpm refuses to update a symlinked lockfile, so install against a local copy.
104
- rm -rf "$WORK_DIR/pnpm-lock.yaml"
105
- if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
106
- cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
107
- fi
108
-
109
- echo "[node_modules] Installing dependencies in $WORK_DIR"
110
- if ! (cd "$WORK_DIR" && pnpm install "$@"); then
111
- rm -f "$WORK_DIR/pnpm-lock.yaml"
112
- exit 1
113
- fi
114
-
115
- if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
116
- temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
117
- cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
118
- chmod 0644 "$temporary_lockfile"
119
- mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
120
- fi
121
-
122
107
  link_node_modules() {
123
108
  local source_dir="$1" target_dir="$2"
124
109
  local current=""
@@ -139,6 +124,21 @@ link_node_modules() {
139
124
  ln -s "$target_dir" "$source_dir/node_modules"
140
125
  }
141
126
 
127
+ cleanup_legacy_shadow_project
128
+ copy_install_metadata
129
+
130
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
131
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
132
+ exit 1
133
+ fi
134
+
135
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
136
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
137
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
138
+ chmod 0644 "$temporary_lockfile"
139
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
140
+ fi
141
+
142
142
  link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
143
143
  for workspace in client server; do
144
144
  if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
@@ -7,7 +7,6 @@ cd "${COZE_WORKSPACE_PATH}"
7
7
 
8
8
  echo "Installing dependencies..."
9
9
  bash "$COZE_WORKSPACE_PATH/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
10
- bash "$COZE_WORKSPACE_PATH/scripts/prepare-next-output.sh"
11
10
 
12
11
  echo "Building the Next.js project..."
13
12
  pnpm next build --webpack
@@ -28,7 +28,7 @@ Stop-ListeningProcess $port
28
28
 
29
29
  <% if (process.env.NODE_ENV === 'test') { %>
30
30
  $env:PORT = "$port"
31
- & pnpm tsx watch src/server.ts
31
+ & pnpm next dev --webpack --hostname 0.0.0.0 --port $port
32
32
  exit $LASTEXITCODE
33
33
  <% } else { %>
34
34
  $logDirectory = if ($env:COZE_LOG_DIR) { $env:COZE_LOG_DIR } else { Join-Path $workspace "logs" }
@@ -45,7 +45,7 @@ if (Test-Path $pidFile) {
45
45
  $previousPort = $env:PORT
46
46
  $env:PORT = "$port"
47
47
  try {
48
- $process = Start-Process -FilePath $env:ComSpec -ArgumentList @("/d", "/s", "/c", "pnpm tsx watch src/server.ts") -WorkingDirectory $workspace -RedirectStandardOutput $logFile -RedirectStandardError $errorLogFile -PassThru
48
+ $process = Start-Process -FilePath $env:ComSpec -ArgumentList @("/d", "/s", "/c", "pnpm next dev --webpack --hostname 0.0.0.0 --port $port") -WorkingDirectory $workspace -RedirectStandardOutput $logFile -RedirectStandardError $errorLogFile -PassThru
49
49
  } finally {
50
50
  if ($null -eq $previousPort) { Remove-Item Env:PORT -ErrorAction SilentlyContinue } else { $env:PORT = $previousPort }
51
51
  }
@@ -52,14 +52,62 @@ kill_port_if_listening() {
52
52
  echo "Port ${DEPLOY_RUN_PORT} cleared."
53
53
  }
54
54
 
55
+ # Next 的路由清单由 watchpack 每次启动重新扫 src 下的 app/pages 目录现算,而 watchpack
56
+ # 不会进入软链目录,软链子树里的 page/route 会被静默跳过:既不注册路由,也不打任何日志,
57
+ # 表现为该路由一直 404 而 .next 里没有它的产物。这里只做提示,不改动源码。
58
+ warn_source_symlinks() {
59
+ local source_dir="${COZE_WORKSPACE_PATH}/src"
60
+ local links link
61
+ if [[ ! -e "${source_dir}" ]]; then
62
+ return
63
+ fi
64
+ links=$(find "${source_dir}" -type l 2>/dev/null || true)
65
+ if [[ -z "${links}" ]]; then
66
+ return
67
+ fi
68
+ echo "Warning: 以下路径是软链,Next 不会进入其中,里面的 page/route 不会被编译:" >&2
69
+ while IFS= read -r link; do
70
+ echo " ${link}" >&2
71
+ done <<< "${links}"
72
+ }
73
+
74
+ # 云盘挂载偶尔会把新建文件的 mtime 设为 Unix epoch。Watchpack 会因此把路由文件当作
75
+ # 启动前的旧状态,导致 Next 的首轮扫描漏掉 route/page。只在云盘项目启动前刷新 app/pages
76
+ # 的目录和普通文件时间戳;不跟随软链、不改文件内容。
77
+ refresh_drive_route_mtimes() {
78
+ local drive_root="${COZE_DRIVE_ROOT:-/Coze/Drive}"
79
+ local project_root route_dir
80
+ project_root="$(pwd -P)"
81
+ if [[ -d "${drive_root}" ]]; then
82
+ drive_root="$(cd "${drive_root}" && pwd -P)"
83
+ else
84
+ drive_root="${drive_root%/}"
85
+ fi
86
+
87
+ case "${project_root}" in
88
+ "${drive_root}"|"${drive_root}"/*) ;;
89
+ *) return ;;
90
+ esac
91
+
92
+ for route_dir in "${COZE_WORKSPACE_PATH}/src/app" "${COZE_WORKSPACE_PATH}/src/pages"; do
93
+ [[ -d "${route_dir}" ]] || continue
94
+ if ! find -P "${route_dir}" \( -type f -o -type d \) -exec touch {} + 2>/dev/null; then
95
+ echo "Warning: failed to refresh Next route timestamps in ${route_dir}." >&2
96
+ fi
97
+ done
98
+ }
99
+
55
100
  <% if (process.env.NODE_ENV === 'test') { %>
56
101
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
57
102
  kill_port_if_listening
58
- bash "${COZE_WORKSPACE_PATH}/scripts/prepare-next-output.sh"
103
+ bash "${COZE_WORKSPACE_PATH}/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
104
+ warn_source_symlinks
105
+ refresh_drive_route_mtimes
59
106
  echo "Starting HTTP service on port ${DEPLOY_RUN_PORT} for dev..."
60
107
 
61
108
  # 测试环境保持服务为前台进程,便于 e2e 收集输出并停止进程。
62
- exec env PORT="${DEPLOY_RUN_PORT}" pnpm tsx watch src/server.ts
109
+ # 开发环境直接使用 Next dev CLI,避免云盘文件事件在 custom server 链路中丢失。
110
+ exec pnpm next dev --webpack --hostname 0.0.0.0 --port "${DEPLOY_RUN_PORT}"
63
111
  <% } else { %>
64
112
  LOG_DIR="${COZE_LOG_DIR:-${COZE_WORKSPACE_PATH}/logs}"
65
113
  LOG_FILE="${LOG_DIR}/app.log"
@@ -69,7 +117,7 @@ PID_FILE="${LOG_DIR}/server.pid"
69
117
  MAX_RUNTIME_SECONDS=1200
70
118
 
71
119
  # 真正被 detach 的是这层 bash wrapper:它是进程组 leader,组内 watchdog 到点回收整组
72
- # (wrapper -> pnpm -> tsx -> node);被包的进程自己先退出时也顺手清空进程组,不留残余。
120
+ # (wrapper -> pnpm -> next -> node);被包的进程自己先退出时也顺手清空进程组,不留残余。
73
121
  RUN_WITH_TIMEOUT='
74
122
  timeout_seconds=$1
75
123
  shift
@@ -145,6 +193,21 @@ dump_log() {
145
193
  echo "---- end of ${LOG_FILE} ----" >&2
146
194
  }
147
195
 
196
+ # 服务刚就绪时 app-paths-manifest.json 还是空的(dev 按需编译,没请求就没产物),
197
+ # 但 .next/dev/types/routes.d.ts 已经写出了本次启动发现到的全部路由。把它落进日志,
198
+ # 排查时才能区分“路由没被发现”和“路由发现了但还没编译”。
199
+ dump_discovered_routes() {
200
+ local route_types="${COZE_WORKSPACE_PATH}/.next/dev/types/routes.d.ts"
201
+ if [[ ! -f "${route_types}" ]]; then
202
+ return
203
+ fi
204
+ {
205
+ echo "---- discovered routes (${route_types}) ----"
206
+ grep -E '^type (AppRoutes|AppRouteHandlerRoutes|PageRoutes) ' "${route_types}" || true
207
+ echo "---- end of discovered routes ----"
208
+ } >> "${LOG_FILE}"
209
+ }
210
+
148
211
  # 仅用于无 ss/lsof 时的兜底探测。服务可能只 bind IPv4 loopback、只 bind IPv6 loopback
149
212
  # (server.listen(port, 'localhost') 会变成 ::1 独占),或 bind 双栈通配地址,
150
213
  port_connectable() {
@@ -218,7 +281,7 @@ wait_for_ready() {
218
281
  return 2
219
282
  }
220
283
 
221
- # 监听端口的是孙进程(pnpm -> tsx -> node),只清端口会漏掉上层 pnpm/tsx
284
+ # 监听端口的是孙进程(pnpm -> next -> node),只清端口会漏掉上层 pnpm/next
222
285
  # 所以先按上次记录的 PID 把整个进程组回收掉。
223
286
  if [[ -f "${PID_FILE}" ]]; then
224
287
  stop_detached "$(cat "${PID_FILE}" 2>/dev/null || true)"
@@ -227,7 +290,9 @@ fi
227
290
 
228
291
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
229
292
  kill_port_if_listening
230
- bash "${COZE_WORKSPACE_PATH}/scripts/prepare-next-output.sh"
293
+ bash "${COZE_WORKSPACE_PATH}/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
294
+ warn_source_symlinks
295
+ refresh_drive_route_mtimes
231
296
  echo "Starting HTTP service on port ${DEPLOY_RUN_PORT} for dev..."
232
297
 
233
298
  mkdir -p "${LOG_DIR}"
@@ -235,7 +300,7 @@ mkdir -p "${LOG_DIR}"
235
300
 
236
301
  export PORT="${DEPLOY_RUN_PORT}"
237
302
  server_pid="$(spawn_detached "${COZE_WORKSPACE_PATH}" "${LOG_FILE}" \
238
- "$(command -v pnpm)" tsx watch src/server.ts)"
303
+ "$(command -v pnpm)" next dev --webpack --hostname 0.0.0.0 --port "${DEPLOY_RUN_PORT}")"
239
304
  if [[ -z "${server_pid}" ]]; then
240
305
  echo "Dev server failed to start: 未获取到后台进程 PID。" >&2
241
306
  dump_log
@@ -262,6 +327,8 @@ if [[ "${ready_status}" -ne 0 ]]; then
262
327
  exit 1
263
328
  fi
264
329
 
330
+ dump_discovered_routes
331
+
265
332
  echo "Dev server started (PID: ${server_pid}), listening on port ${DEPLOY_RUN_PORT}."
266
333
  echo "Auto stop after ${MAX_RUNTIME_SECONDS}s."
267
334
  echo "Log file: ${LOG_FILE}"
@@ -48,77 +48,62 @@ trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT
48
48
 
49
49
  mkdir -p "$WORK_DIR"
50
50
 
51
- # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
52
- # workspace directories stay real too, so pnpm never writes them to Drive.
53
- mirror_root() {
51
+ # Previous versions mirrored the whole project into WORK_DIR. That gives pnpm
52
+ # and framework dev servers two paths for the same source tree, which breaks
53
+ # file watching and on-demand compilation. Keep only managed local outputs.
54
+ cleanup_legacy_workspace() {
55
+ local workspace_dir="$1" entry name
56
+ if [ -L "$workspace_dir" ] || { [ -e "$workspace_dir" ] && [ ! -d "$workspace_dir" ]; }; then
57
+ rm -rf "$workspace_dir"
58
+ return
59
+ fi
60
+ if [ ! -d "$workspace_dir" ]; then
61
+ return 0
62
+ fi
63
+
64
+ while IFS= read -r -d '' entry; do
65
+ name="$(basename "$entry")"
66
+ [ "$name" = "node_modules" ] || rm -rf "$entry"
67
+ done < <(find "$workspace_dir" -mindepth 1 -maxdepth 1 -print0)
68
+ }
69
+
70
+ cleanup_legacy_shadow_project() {
54
71
  local entry name
55
72
  while IFS= read -r -d '' entry; do
56
73
  name="$(basename "$entry")"
57
74
  case "$name" in
58
- node_modules|pnpm-lock.yaml) continue ;;
59
- client|server)
60
- [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
61
- ;;
75
+ node_modules|client|server) continue ;;
62
76
  esac
63
77
  rm -rf "$entry"
64
78
  done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
65
79
 
66
- while IFS= read -r -d '' entry; do
67
- name="$(basename "$entry")"
68
- case "$name" in
69
- node_modules|pnpm-lock.yaml) continue ;;
70
- client|server)
71
- [ -f "$entry/package.json" ] && continue
72
- ;;
73
- esac
74
- ln -s "$entry" "$WORK_DIR/$name"
75
- done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
80
+ for workspace in client server; do
81
+ cleanup_legacy_workspace "$WORK_DIR/$workspace"
82
+ done
76
83
  }
77
84
 
78
- mirror_workspace() {
79
- local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
80
- local entry name
81
- if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
82
- rm -rf "$work_dir"
83
- fi
84
- mkdir -p "$work_dir"
85
-
86
- while IFS= read -r -d '' entry; do
87
- [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
88
- done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
89
-
90
- while IFS= read -r -d '' entry; do
91
- name="$(basename "$entry")"
92
- [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
93
- done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
85
+ copy_install_metadata() {
86
+ local filename source_file target_file workspace
87
+ for filename in package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc; do
88
+ source_file="$PROJECT_ROOT/$filename"
89
+ target_file="$WORK_DIR/$filename"
90
+ rm -f "$target_file"
91
+ if [ -f "$source_file" ]; then
92
+ cp "$source_file" "$target_file"
93
+ fi
94
+ done
95
+
96
+ for workspace in client server; do
97
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
98
+ mkdir -p "$WORK_DIR/$workspace"
99
+ rm -f "$WORK_DIR/$workspace/package.json"
100
+ cp "$PROJECT_ROOT/$workspace/package.json" "$WORK_DIR/$workspace/package.json"
101
+ else
102
+ rm -rf "$WORK_DIR/$workspace"
103
+ fi
104
+ done
94
105
  }
95
106
 
96
- mirror_root
97
- for workspace in client server; do
98
- if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
99
- mirror_workspace "$workspace"
100
- fi
101
- done
102
-
103
- # pnpm refuses to update a symlinked lockfile, so install against a local copy.
104
- rm -rf "$WORK_DIR/pnpm-lock.yaml"
105
- if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
106
- cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
107
- fi
108
-
109
- echo "[node_modules] Installing dependencies in $WORK_DIR"
110
- if ! (cd "$WORK_DIR" && pnpm install "$@"); then
111
- rm -f "$WORK_DIR/pnpm-lock.yaml"
112
- exit 1
113
- fi
114
-
115
- if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
116
- temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
117
- cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
118
- chmod 0644 "$temporary_lockfile"
119
- mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
120
- fi
121
-
122
107
  link_node_modules() {
123
108
  local source_dir="$1" target_dir="$2"
124
109
  local current=""
@@ -139,6 +124,21 @@ link_node_modules() {
139
124
  ln -s "$target_dir" "$source_dir/node_modules"
140
125
  }
141
126
 
127
+ cleanup_legacy_shadow_project
128
+ copy_install_metadata
129
+
130
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
131
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
132
+ exit 1
133
+ fi
134
+
135
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
136
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
137
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
138
+ chmod 0644 "$temporary_lockfile"
139
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
140
+ fi
141
+
142
142
  link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
143
143
  for workspace in client server; do
144
144
  if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
@@ -48,77 +48,62 @@ trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT
48
48
 
49
49
  mkdir -p "$WORK_DIR"
50
50
 
51
- # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
52
- # workspace directories stay real too, so pnpm never writes them to Drive.
53
- mirror_root() {
51
+ # Previous versions mirrored the whole project into WORK_DIR. That gives pnpm
52
+ # and framework dev servers two paths for the same source tree, which breaks
53
+ # file watching and on-demand compilation. Keep only managed local outputs.
54
+ cleanup_legacy_workspace() {
55
+ local workspace_dir="$1" entry name
56
+ if [ -L "$workspace_dir" ] || { [ -e "$workspace_dir" ] && [ ! -d "$workspace_dir" ]; }; then
57
+ rm -rf "$workspace_dir"
58
+ return
59
+ fi
60
+ if [ ! -d "$workspace_dir" ]; then
61
+ return 0
62
+ fi
63
+
64
+ while IFS= read -r -d '' entry; do
65
+ name="$(basename "$entry")"
66
+ [ "$name" = "node_modules" ] || rm -rf "$entry"
67
+ done < <(find "$workspace_dir" -mindepth 1 -maxdepth 1 -print0)
68
+ }
69
+
70
+ cleanup_legacy_shadow_project() {
54
71
  local entry name
55
72
  while IFS= read -r -d '' entry; do
56
73
  name="$(basename "$entry")"
57
74
  case "$name" in
58
- node_modules|pnpm-lock.yaml) continue ;;
59
- client|server)
60
- [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
61
- ;;
75
+ node_modules|client|server) continue ;;
62
76
  esac
63
77
  rm -rf "$entry"
64
78
  done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
65
79
 
66
- while IFS= read -r -d '' entry; do
67
- name="$(basename "$entry")"
68
- case "$name" in
69
- node_modules|pnpm-lock.yaml) continue ;;
70
- client|server)
71
- [ -f "$entry/package.json" ] && continue
72
- ;;
73
- esac
74
- ln -s "$entry" "$WORK_DIR/$name"
75
- done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
80
+ for workspace in client server; do
81
+ cleanup_legacy_workspace "$WORK_DIR/$workspace"
82
+ done
76
83
  }
77
84
 
78
- mirror_workspace() {
79
- local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
80
- local entry name
81
- if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
82
- rm -rf "$work_dir"
83
- fi
84
- mkdir -p "$work_dir"
85
-
86
- while IFS= read -r -d '' entry; do
87
- [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
88
- done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
89
-
90
- while IFS= read -r -d '' entry; do
91
- name="$(basename "$entry")"
92
- [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
93
- done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
85
+ copy_install_metadata() {
86
+ local filename source_file target_file workspace
87
+ for filename in package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc; do
88
+ source_file="$PROJECT_ROOT/$filename"
89
+ target_file="$WORK_DIR/$filename"
90
+ rm -f "$target_file"
91
+ if [ -f "$source_file" ]; then
92
+ cp "$source_file" "$target_file"
93
+ fi
94
+ done
95
+
96
+ for workspace in client server; do
97
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
98
+ mkdir -p "$WORK_DIR/$workspace"
99
+ rm -f "$WORK_DIR/$workspace/package.json"
100
+ cp "$PROJECT_ROOT/$workspace/package.json" "$WORK_DIR/$workspace/package.json"
101
+ else
102
+ rm -rf "$WORK_DIR/$workspace"
103
+ fi
104
+ done
94
105
  }
95
106
 
96
- mirror_root
97
- for workspace in client server; do
98
- if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
99
- mirror_workspace "$workspace"
100
- fi
101
- done
102
-
103
- # pnpm refuses to update a symlinked lockfile, so install against a local copy.
104
- rm -rf "$WORK_DIR/pnpm-lock.yaml"
105
- if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
106
- cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
107
- fi
108
-
109
- echo "[node_modules] Installing dependencies in $WORK_DIR"
110
- if ! (cd "$WORK_DIR" && pnpm install "$@"); then
111
- rm -f "$WORK_DIR/pnpm-lock.yaml"
112
- exit 1
113
- fi
114
-
115
- if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
116
- temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
117
- cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
118
- chmod 0644 "$temporary_lockfile"
119
- mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
120
- fi
121
-
122
107
  link_node_modules() {
123
108
  local source_dir="$1" target_dir="$2"
124
109
  local current=""
@@ -139,6 +124,21 @@ link_node_modules() {
139
124
  ln -s "$target_dir" "$source_dir/node_modules"
140
125
  }
141
126
 
127
+ cleanup_legacy_shadow_project
128
+ copy_install_metadata
129
+
130
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
131
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
132
+ exit 1
133
+ fi
134
+
135
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
136
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
137
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
138
+ chmod 0644 "$temporary_lockfile"
139
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
140
+ fi
141
+
142
142
  link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
143
143
  for workspace in client server; do
144
144
  if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
@@ -48,77 +48,62 @@ trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT
48
48
 
49
49
  mkdir -p "$WORK_DIR"
50
50
 
51
- # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
52
- # workspace directories stay real too, so pnpm never writes them to Drive.
53
- mirror_root() {
51
+ # Previous versions mirrored the whole project into WORK_DIR. That gives pnpm
52
+ # and framework dev servers two paths for the same source tree, which breaks
53
+ # file watching and on-demand compilation. Keep only managed local outputs.
54
+ cleanup_legacy_workspace() {
55
+ local workspace_dir="$1" entry name
56
+ if [ -L "$workspace_dir" ] || { [ -e "$workspace_dir" ] && [ ! -d "$workspace_dir" ]; }; then
57
+ rm -rf "$workspace_dir"
58
+ return
59
+ fi
60
+ if [ ! -d "$workspace_dir" ]; then
61
+ return 0
62
+ fi
63
+
64
+ while IFS= read -r -d '' entry; do
65
+ name="$(basename "$entry")"
66
+ [ "$name" = "node_modules" ] || rm -rf "$entry"
67
+ done < <(find "$workspace_dir" -mindepth 1 -maxdepth 1 -print0)
68
+ }
69
+
70
+ cleanup_legacy_shadow_project() {
54
71
  local entry name
55
72
  while IFS= read -r -d '' entry; do
56
73
  name="$(basename "$entry")"
57
74
  case "$name" in
58
- node_modules|pnpm-lock.yaml) continue ;;
59
- client|server)
60
- [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
61
- ;;
75
+ node_modules|client|server) continue ;;
62
76
  esac
63
77
  rm -rf "$entry"
64
78
  done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
65
79
 
66
- while IFS= read -r -d '' entry; do
67
- name="$(basename "$entry")"
68
- case "$name" in
69
- node_modules|pnpm-lock.yaml) continue ;;
70
- client|server)
71
- [ -f "$entry/package.json" ] && continue
72
- ;;
73
- esac
74
- ln -s "$entry" "$WORK_DIR/$name"
75
- done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
80
+ for workspace in client server; do
81
+ cleanup_legacy_workspace "$WORK_DIR/$workspace"
82
+ done
76
83
  }
77
84
 
78
- mirror_workspace() {
79
- local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
80
- local entry name
81
- if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
82
- rm -rf "$work_dir"
83
- fi
84
- mkdir -p "$work_dir"
85
-
86
- while IFS= read -r -d '' entry; do
87
- [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
88
- done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
89
-
90
- while IFS= read -r -d '' entry; do
91
- name="$(basename "$entry")"
92
- [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
93
- done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
85
+ copy_install_metadata() {
86
+ local filename source_file target_file workspace
87
+ for filename in package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc; do
88
+ source_file="$PROJECT_ROOT/$filename"
89
+ target_file="$WORK_DIR/$filename"
90
+ rm -f "$target_file"
91
+ if [ -f "$source_file" ]; then
92
+ cp "$source_file" "$target_file"
93
+ fi
94
+ done
95
+
96
+ for workspace in client server; do
97
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
98
+ mkdir -p "$WORK_DIR/$workspace"
99
+ rm -f "$WORK_DIR/$workspace/package.json"
100
+ cp "$PROJECT_ROOT/$workspace/package.json" "$WORK_DIR/$workspace/package.json"
101
+ else
102
+ rm -rf "$WORK_DIR/$workspace"
103
+ fi
104
+ done
94
105
  }
95
106
 
96
- mirror_root
97
- for workspace in client server; do
98
- if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
99
- mirror_workspace "$workspace"
100
- fi
101
- done
102
-
103
- # pnpm refuses to update a symlinked lockfile, so install against a local copy.
104
- rm -rf "$WORK_DIR/pnpm-lock.yaml"
105
- if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
106
- cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
107
- fi
108
-
109
- echo "[node_modules] Installing dependencies in $WORK_DIR"
110
- if ! (cd "$WORK_DIR" && pnpm install "$@"); then
111
- rm -f "$WORK_DIR/pnpm-lock.yaml"
112
- exit 1
113
- fi
114
-
115
- if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
116
- temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
117
- cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
118
- chmod 0644 "$temporary_lockfile"
119
- mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
120
- fi
121
-
122
107
  link_node_modules() {
123
108
  local source_dir="$1" target_dir="$2"
124
109
  local current=""
@@ -139,6 +124,21 @@ link_node_modules() {
139
124
  ln -s "$target_dir" "$source_dir/node_modules"
140
125
  }
141
126
 
127
+ cleanup_legacy_shadow_project
128
+ copy_install_metadata
129
+
130
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
131
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
132
+ exit 1
133
+ fi
134
+
135
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
136
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
137
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
138
+ chmod 0644 "$temporary_lockfile"
139
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
140
+ fi
141
+
142
142
  link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
143
143
  for workspace in client server; do
144
144
  if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
@@ -48,77 +48,62 @@ trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT
48
48
 
49
49
  mkdir -p "$WORK_DIR"
50
50
 
51
- # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
52
- # workspace directories stay real too, so pnpm never writes them to Drive.
53
- mirror_root() {
51
+ # Previous versions mirrored the whole project into WORK_DIR. That gives pnpm
52
+ # and framework dev servers two paths for the same source tree, which breaks
53
+ # file watching and on-demand compilation. Keep only managed local outputs.
54
+ cleanup_legacy_workspace() {
55
+ local workspace_dir="$1" entry name
56
+ if [ -L "$workspace_dir" ] || { [ -e "$workspace_dir" ] && [ ! -d "$workspace_dir" ]; }; then
57
+ rm -rf "$workspace_dir"
58
+ return
59
+ fi
60
+ if [ ! -d "$workspace_dir" ]; then
61
+ return 0
62
+ fi
63
+
64
+ while IFS= read -r -d '' entry; do
65
+ name="$(basename "$entry")"
66
+ [ "$name" = "node_modules" ] || rm -rf "$entry"
67
+ done < <(find "$workspace_dir" -mindepth 1 -maxdepth 1 -print0)
68
+ }
69
+
70
+ cleanup_legacy_shadow_project() {
54
71
  local entry name
55
72
  while IFS= read -r -d '' entry; do
56
73
  name="$(basename "$entry")"
57
74
  case "$name" in
58
- node_modules|pnpm-lock.yaml) continue ;;
59
- client|server)
60
- [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
61
- ;;
75
+ node_modules|client|server) continue ;;
62
76
  esac
63
77
  rm -rf "$entry"
64
78
  done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
65
79
 
66
- while IFS= read -r -d '' entry; do
67
- name="$(basename "$entry")"
68
- case "$name" in
69
- node_modules|pnpm-lock.yaml) continue ;;
70
- client|server)
71
- [ -f "$entry/package.json" ] && continue
72
- ;;
73
- esac
74
- ln -s "$entry" "$WORK_DIR/$name"
75
- done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
80
+ for workspace in client server; do
81
+ cleanup_legacy_workspace "$WORK_DIR/$workspace"
82
+ done
76
83
  }
77
84
 
78
- mirror_workspace() {
79
- local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
80
- local entry name
81
- if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
82
- rm -rf "$work_dir"
83
- fi
84
- mkdir -p "$work_dir"
85
-
86
- while IFS= read -r -d '' entry; do
87
- [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
88
- done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
89
-
90
- while IFS= read -r -d '' entry; do
91
- name="$(basename "$entry")"
92
- [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
93
- done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
85
+ copy_install_metadata() {
86
+ local filename source_file target_file workspace
87
+ for filename in package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc; do
88
+ source_file="$PROJECT_ROOT/$filename"
89
+ target_file="$WORK_DIR/$filename"
90
+ rm -f "$target_file"
91
+ if [ -f "$source_file" ]; then
92
+ cp "$source_file" "$target_file"
93
+ fi
94
+ done
95
+
96
+ for workspace in client server; do
97
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
98
+ mkdir -p "$WORK_DIR/$workspace"
99
+ rm -f "$WORK_DIR/$workspace/package.json"
100
+ cp "$PROJECT_ROOT/$workspace/package.json" "$WORK_DIR/$workspace/package.json"
101
+ else
102
+ rm -rf "$WORK_DIR/$workspace"
103
+ fi
104
+ done
94
105
  }
95
106
 
96
- mirror_root
97
- for workspace in client server; do
98
- if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
99
- mirror_workspace "$workspace"
100
- fi
101
- done
102
-
103
- # pnpm refuses to update a symlinked lockfile, so install against a local copy.
104
- rm -rf "$WORK_DIR/pnpm-lock.yaml"
105
- if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
106
- cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
107
- fi
108
-
109
- echo "[node_modules] Installing dependencies in $WORK_DIR"
110
- if ! (cd "$WORK_DIR" && pnpm install "$@"); then
111
- rm -f "$WORK_DIR/pnpm-lock.yaml"
112
- exit 1
113
- fi
114
-
115
- if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
116
- temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
117
- cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
118
- chmod 0644 "$temporary_lockfile"
119
- mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
120
- fi
121
-
122
107
  link_node_modules() {
123
108
  local source_dir="$1" target_dir="$2"
124
109
  local current=""
@@ -139,6 +124,21 @@ link_node_modules() {
139
124
  ln -s "$target_dir" "$source_dir/node_modules"
140
125
  }
141
126
 
127
+ cleanup_legacy_shadow_project
128
+ copy_install_metadata
129
+
130
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
131
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
132
+ exit 1
133
+ fi
134
+
135
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
136
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
137
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
138
+ chmod 0644 "$temporary_lockfile"
139
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
140
+ fi
141
+
142
142
  link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
143
143
  for workspace in client server; do
144
144
  if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
package/lib/cli.js CHANGED
@@ -2114,7 +2114,7 @@ const EventBuilder = {
2114
2114
  };
2115
2115
 
2116
2116
  var name = "@coze-arch/cli";
2117
- var version = "0.1.4-alpha.b8ffd5";
2117
+ var version = "0.1.4-alpha.d384e3";
2118
2118
  var description = "coze coding devtools cli";
2119
2119
  var license = "MIT";
2120
2120
  var author = "fanwenjie.fe@bytedance.com";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coze-arch/cli",
3
- "version": "0.1.4-alpha.b8ffd5",
3
+ "version": "0.1.4-alpha.d384e3",
4
4
  "private": false,
5
5
  "description": "coze coding devtools cli",
6
6
  "license": "MIT",
@@ -1,44 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Keep Next.js compiler output off Coze Drive while leaving source files in place.
3
- set -euo pipefail
4
-
5
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
6
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
7
-
8
- DRIVE_ROOT="${COZE_DRIVE_ROOT:-/Coze/Drive}"
9
- if [ -d "$DRIVE_ROOT" ]; then
10
- DRIVE_ROOT="$(cd "$DRIVE_ROOT" && pwd -P)"
11
- else
12
- DRIVE_ROOT="${DRIVE_ROOT%/}"
13
- fi
14
- case "$PROJECT_ROOT" in
15
- "$DRIVE_ROOT"|"$DRIVE_ROOT"/*) ;;
16
- *) exit 0 ;;
17
- esac
18
-
19
- NM_ROOT="/tmp/nm"
20
- PROJECT_ID="$(basename "$PROJECT_ROOT")-$(printf '%s' "$PROJECT_ROOT" | cksum | awk '{print $1}')"
21
- NEXT_DIR="$NM_ROOT/next/$PROJECT_ID"
22
- mkdir -p "$NEXT_DIR"
23
-
24
- if [ -L "$PROJECT_ROOT/.next" ]; then
25
- current="$(readlink "$PROJECT_ROOT/.next")"
26
- if [ "$current" = "$NEXT_DIR" ]; then
27
- exit 0
28
- fi
29
- echo "[next] refusing to replace unmanaged symlink: $PROJECT_ROOT/.next" >&2
30
- exit 1
31
- fi
32
-
33
- if [ -e "$PROJECT_ROOT/.next" ]; then
34
- rm -rf "$PROJECT_ROOT/.next"
35
- fi
36
-
37
- if ! ln -s "$NEXT_DIR" "$PROJECT_ROOT/.next"; then
38
- if [ ! -L "$PROJECT_ROOT/.next" ] || [ "$(readlink "$PROJECT_ROOT/.next")" != "$NEXT_DIR" ]; then
39
- echo "[next] failed to link $PROJECT_ROOT/.next to $NEXT_DIR" >&2
40
- exit 1
41
- fi
42
- fi
43
-
44
- echo "[next] Compiler output ready at $NEXT_DIR"