@coze-arch/cli 0.1.8-alpha.382639 → 0.1.8-alpha.53dd57

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.
@@ -1,9 +1,18 @@
1
1
  import type { NextConfig } from 'next';
2
+ import path from 'path';
2
3
 
3
4
  const nextConfig: NextConfig = {
4
5
  // outputFileTracingRoot: path.resolve(__dirname, '../../'), // Uncomment and add 'import path from "path"' if needed
5
6
  /* config options here */
6
7
  serverExternalPackages: ['coze-coding-dev-sdk'],
8
+ webpack: (config, { dev }) => {
9
+ if (dev && config.cache && config.cache.type === 'filesystem') {
10
+ config.cache.cacheDirectory = path.resolve(
11
+ 'node_modules/.cache/next-webpack',
12
+ );
13
+ }
14
+ return config;
15
+ },
7
16
  allowedDevOrigins: ['*.dev.coze.site'],
8
17
  images: {
9
18
  remotePatterns: [
@@ -8,7 +8,7 @@ Write-Host "Installing dependencies..."
8
8
  if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
9
9
 
10
10
  Write-Host "Building the Next.js project..."
11
- & pnpm next build
11
+ & pnpm next build --webpack
12
12
  if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
13
13
 
14
14
  Write-Host "Bundling server with tsup..."
@@ -9,7 +9,7 @@ echo "Installing dependencies..."
9
9
  pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
10
10
 
11
11
  echo "Building the Next.js project..."
12
- pnpm next build
12
+ pnpm next build --webpack
13
13
 
14
14
  echo "Bundling server with tsup..."
15
15
  pnpm tsup src/server.ts --format cjs --platform node --target node20 --outDir dist --no-splitting --no-minify
@@ -28,7 +28,7 @@ Stop-ListeningProcess $port
28
28
 
29
29
  <% if (process.env.NODE_ENV === 'test') { %>
30
30
  $env:PORT = "$port"
31
- & pnpm next dev --hostname 0.0.0.0 --port $port
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 next dev --hostname 0.0.0.0 --port $port") -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
  }
@@ -58,17 +58,37 @@ kill_port_if_listening() {
58
58
  echo "Port ${DEPLOY_RUN_PORT} cleared."
59
59
  }
60
60
 
61
+ # Next 的路由清单由 watchpack 每次启动重新扫 src 下的 app/pages 目录现算,而 watchpack
62
+ # 不会进入软链目录,软链子树里的 page/route 会被静默跳过:既不注册路由,也不打任何日志,
63
+ # 表现为该路由一直 404 而 .next 里没有它的产物。这里只做提示,不改动源码。
64
+ warn_source_symlinks() {
65
+ local source_dir="${COZE_WORKSPACE_PATH}/src"
66
+ local links link
67
+ if [[ ! -e "${source_dir}" ]]; then
68
+ return
69
+ fi
70
+ links=$(find "${source_dir}" -type l 2>/dev/null || true)
71
+ if [[ -z "${links}" ]]; then
72
+ return
73
+ fi
74
+ echo "Warning: 以下路径是软链,Next 不会进入其中,里面的 page/route 不会被编译:" >&2
75
+ while IFS= read -r link; do
76
+ echo " ${link}" >&2
77
+ done <<< "${links}"
78
+ }
79
+
61
80
  <% if (process.env.NODE_ENV === 'test') { %>
62
81
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
63
82
  kill_port_if_listening
64
83
  if [[ "${COZE_WEB_LOCAL_MIRROR:-}" != "1" ]]; then
65
- pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
84
+ COZE_REUSE_NODE_MODULES=1 bash "${COZE_WORKSPACE_PATH}/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
66
85
  fi
86
+ warn_source_symlinks
67
87
  echo "Starting HTTP service on port ${DEPLOY_RUN_PORT} for dev..."
68
88
 
69
89
  # 测试环境保持服务为前台进程,便于 e2e 收集输出并停止进程。
70
90
  # 开发环境直接使用 Next 的 dev CLI,避免云盘文件事件在 custom server 链路中丢失。
71
- exec node "${SCRIPT_DIR}/local-workspace.cjs" watch pnpm next dev --hostname 0.0.0.0 --port "${DEPLOY_RUN_PORT}"
91
+ exec node "${SCRIPT_DIR}/local-workspace.cjs" watch pnpm next dev --webpack --hostname 0.0.0.0 --port "${DEPLOY_RUN_PORT}"
72
92
  <% } else { %>
73
93
  LOG_DIR="${COZE_LOG_DIR:-${COZE_WORKSPACE_PATH}/logs}"
74
94
  LOG_FILE="${LOG_DIR}/app.log"
@@ -256,8 +276,9 @@ fi
256
276
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
257
277
  kill_port_if_listening
258
278
  if [[ "${COZE_WEB_LOCAL_MIRROR:-}" != "1" ]]; then
259
- pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
279
+ COZE_REUSE_NODE_MODULES=1 bash "${COZE_WORKSPACE_PATH}/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
260
280
  fi
281
+ warn_source_symlinks
261
282
  echo "Starting HTTP service on port ${DEPLOY_RUN_PORT} for dev..."
262
283
 
263
284
  mkdir -p "${LOG_DIR}"
@@ -265,7 +286,7 @@ mkdir -p "${LOG_DIR}"
265
286
 
266
287
  export PORT="${DEPLOY_RUN_PORT}"
267
288
  server_pid="$(spawn_detached "${COZE_WORKSPACE_PATH}" "${LOG_FILE}" \
268
- "$(command -v node)" "${SCRIPT_DIR}/local-workspace.cjs" watch "$(command -v pnpm)" next dev --hostname 0.0.0.0 --port "${DEPLOY_RUN_PORT}")"
289
+ "$(command -v node)" "${SCRIPT_DIR}/local-workspace.cjs" watch "$(command -v pnpm)" next dev --webpack --hostname 0.0.0.0 --port "${DEPLOY_RUN_PORT}")"
269
290
  if [[ -z "${server_pid}" ]]; then
270
291
  echo "Dev server failed to start: 未获取到后台进程 PID。" >&2
271
292
  dump_log
@@ -0,0 +1,380 @@
1
+ #!/usr/bin/env bash
2
+ # Install dependencies on local disk and expose them to the source tree by symlink.
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
6
+ if [ "$(basename "$(dirname "$SCRIPT_DIR")")" = ".cozeproj" ]; then
7
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd -P)"
8
+ else
9
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
10
+ fi
11
+
12
+ command -v pnpm >/dev/null 2>&1 || {
13
+ echo "[node_modules] pnpm is required" >&2
14
+ exit 1
15
+ }
16
+
17
+ DRIVE_ROOT="${COZE_DRIVE_ROOT:-/Coze/Drive}"
18
+ if [ -d "$DRIVE_ROOT" ]; then
19
+ DRIVE_ROOT="$(cd "$DRIVE_ROOT" && pwd -P)"
20
+ else
21
+ DRIVE_ROOT="${DRIVE_ROOT%/}"
22
+ fi
23
+ case "$PROJECT_ROOT" in
24
+ "$DRIVE_ROOT"|"$DRIVE_ROOT"/*) ;;
25
+ *)
26
+ (cd "$PROJECT_ROOT" && pnpm install "$@")
27
+ exit 0
28
+ ;;
29
+ esac
30
+
31
+ NM_ROOT="/tmp/nm"
32
+ PROJECT_ID="$(basename "$PROJECT_ROOT")-$(printf '%s' "$PROJECT_ROOT" | cksum | awk '{print $1}')"
33
+ mkdir -p "$NM_ROOT"
34
+ WORK_DIR="$NM_ROOT/$PROJECT_ID"
35
+ case "$WORK_DIR" in
36
+ "$DRIVE_ROOT"|"$DRIVE_ROOT"/*)
37
+ echo "[node_modules] local dependency directory must not be on Coze Drive: $WORK_DIR" >&2
38
+ exit 1
39
+ ;;
40
+ esac
41
+
42
+ LOCK_DIR="$NM_ROOT/$PROJECT_ID.lock"
43
+ LOCK_TIMEOUT_SECONDS="${COZE_NODE_MODULES_LOCK_TIMEOUT_SECONDS:-120}"
44
+ case "$LOCK_TIMEOUT_SECONDS" in
45
+ ''|*[!0-9]*|0)
46
+ echo "[node_modules] COZE_NODE_MODULES_LOCK_TIMEOUT_SECONDS must be a positive integer" >&2
47
+ exit 1
48
+ ;;
49
+ esac
50
+
51
+ lock_owner_is_alive() {
52
+ local owner_pid=""
53
+ [ -f "$LOCK_DIR/pid" ] || return 1
54
+ IFS= read -r owner_pid < "$LOCK_DIR/pid" || return 1
55
+ case "$owner_pid" in
56
+ ''|*[!0-9]*) return 1 ;;
57
+ esac
58
+ kill -0 "$owner_pid" 2>/dev/null
59
+ }
60
+
61
+ release_lock() {
62
+ local owner_pid=""
63
+ [ -f "$LOCK_DIR/pid" ] || return 0
64
+ IFS= read -r owner_pid < "$LOCK_DIR/pid" || true
65
+ if [ "$owner_pid" = "$$" ]; then
66
+ rm -f "$LOCK_DIR/pid"
67
+ rmdir "$LOCK_DIR" 2>/dev/null || true
68
+ fi
69
+ }
70
+
71
+ lock_started_at="$(date +%s)"
72
+ missing_owner_checks=0
73
+ while ! mkdir "$LOCK_DIR" 2>/dev/null; do
74
+ if lock_owner_is_alive; then
75
+ missing_owner_checks=0
76
+ else
77
+ missing_owner_checks=$((missing_owner_checks + 1))
78
+ if [ "$missing_owner_checks" -ge 2 ]; then
79
+ stale_lock_dir="$LOCK_DIR.stale.$$"
80
+ if mv "$LOCK_DIR" "$stale_lock_dir" 2>/dev/null; then
81
+ echo "[node_modules] Recovering stale dependency preparation lock."
82
+ rm -rf "$stale_lock_dir"
83
+ fi
84
+ missing_owner_checks=0
85
+ continue
86
+ fi
87
+ fi
88
+
89
+ lock_now="$(date +%s)"
90
+ if [ $((lock_now - lock_started_at)) -ge "$LOCK_TIMEOUT_SECONDS" ]; then
91
+ echo "[node_modules] Timed out waiting ${LOCK_TIMEOUT_SECONDS}s for dependency preparation lock: $LOCK_DIR" >&2
92
+ exit 1
93
+ fi
94
+ echo "[node_modules] Waiting for another dependency preparation for this project..."
95
+ sleep 1
96
+ done
97
+ printf '%s\n' "$$" > "$LOCK_DIR/pid"
98
+ trap release_lock EXIT
99
+
100
+ mkdir -p "$WORK_DIR"
101
+ INSTALL_STATE_FILE="$WORK_DIR/.install-state"
102
+
103
+ # Previous versions mirrored the whole project into WORK_DIR. That gives pnpm
104
+ # and framework dev servers two paths for the same source tree, which breaks
105
+ # file watching and on-demand compilation. Keep only managed local outputs.
106
+ cleanup_legacy_workspace() {
107
+ local workspace_dir="$1" entry name
108
+ if [ -L "$workspace_dir" ] || { [ -e "$workspace_dir" ] && [ ! -d "$workspace_dir" ]; }; then
109
+ rm -rf "$workspace_dir"
110
+ return
111
+ fi
112
+ if [ ! -d "$workspace_dir" ]; then
113
+ return 0
114
+ fi
115
+
116
+ while IFS= read -r -d '' entry; do
117
+ name="$(basename "$entry")"
118
+ [ "$name" = "node_modules" ] || rm -rf "$entry"
119
+ done < <(find "$workspace_dir" -mindepth 1 -maxdepth 1 -print0)
120
+ }
121
+
122
+ # Preserve existing project caches during dependency preparation.
123
+ cleanup_legacy_shadow_project() {
124
+ local entry name
125
+ while IFS= read -r -d '' entry; do
126
+ name="$(basename "$entry")"
127
+ case "$name" in
128
+ node_modules|client|server|caches|.install-state) continue ;;
129
+ esac
130
+ rm -rf "$entry"
131
+ done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
132
+
133
+ for workspace in client server; do
134
+ cleanup_legacy_workspace "$WORK_DIR/$workspace"
135
+ done
136
+ }
137
+
138
+ link_install_entry() {
139
+ local source_path="$1" target_path="$2"
140
+ rm -rf "$target_path"
141
+ if [ -e "$source_path" ]; then
142
+ ln -s "$source_path" "$target_path"
143
+ fi
144
+ }
145
+
146
+ hash_install_input() {
147
+ if command -v sha256sum >/dev/null 2>&1; then
148
+ sha256sum | awk '{print $1}'
149
+ elif command -v shasum >/dev/null 2>&1; then
150
+ shasum -a 256 | awk '{print $1}'
151
+ else
152
+ cksum | awk '{print $1 "-" $2}'
153
+ fi
154
+ }
155
+
156
+ append_file_to_install_fingerprint() {
157
+ local relative_path="$1"
158
+ local source_path="$PROJECT_ROOT/$relative_path"
159
+ printf 'path=%s\n' "$relative_path"
160
+ if [ -f "$source_path" ]; then
161
+ cat "$source_path"
162
+ else
163
+ printf '<missing>\n'
164
+ fi
165
+ }
166
+
167
+ append_directory_to_install_fingerprint() {
168
+ local relative_path="$1"
169
+ local source_path="$PROJECT_ROOT/$relative_path"
170
+ local file
171
+ printf 'path=%s\n' "$relative_path"
172
+ if [ ! -d "$source_path" ]; then
173
+ printf '<missing>\n'
174
+ return
175
+ fi
176
+
177
+ while IFS= read -r file; do
178
+ printf 'file=%s\n' "${file#"${PROJECT_ROOT}/"}"
179
+ cat "$file"
180
+ done < <(find -P "$source_path" -type f -print | LC_ALL=C sort)
181
+ }
182
+
183
+ # Everything that can change the resolved dependency tree. The leading version marker
184
+ # invalidates every stored state when this scheme itself changes.
185
+ calculate_install_fingerprint() {
186
+ local filename workspace argument
187
+ {
188
+ printf 'prepare-node-modules-install-state=1\n'
189
+ printf 'node-version=%s\n' "$(node --version)"
190
+ printf 'pnpm-version=%s\n' "$(pnpm --version)"
191
+ printf 'node-env=%s\n' "${NODE_ENV:-}"
192
+ printf 'npm-config-production=%s\n' "${npm_config_production:-}"
193
+ printf 'npm-config-production-upper=%s\n' "${NPM_CONFIG_PRODUCTION:-}"
194
+ printf 'pnpm-config-production=%s\n' "${PNPM_CONFIG_PRODUCTION:-}"
195
+ for argument in "$@"; do
196
+ printf 'install-argument=%s\n' "$argument"
197
+ done
198
+ for filename in package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc; do
199
+ append_file_to_install_fingerprint "$filename"
200
+ done
201
+ for workspace in client server; do
202
+ append_file_to_install_fingerprint "$workspace/package.json"
203
+ done
204
+ append_directory_to_install_fingerprint patches
205
+ } | hash_install_input
206
+ }
207
+
208
+ install_requires_refresh() {
209
+ local argument
210
+ for argument in "$@"; do
211
+ case "$argument" in
212
+ --force|-f|--lockfile-only|--fix-lockfile) return 0 ;;
213
+ esac
214
+ done
215
+ return 1
216
+ }
217
+
218
+ # Reuse skips pnpm install entirely, so it must not skip side effects that live outside
219
+ # node_modules. preinstall is exempt: it only guards which package manager may run, and
220
+ # there is no install to guard when the tree is already in place.
221
+ package_has_install_lifecycle() {
222
+ local package_path="$1"
223
+ node - "$package_path" <<'NODE'
224
+ const fs = require('node:fs');
225
+ const [packagePath] = process.argv.slice(2);
226
+
227
+ try {
228
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
229
+ const scripts = packageJson && typeof packageJson.scripts === 'object' && packageJson.scripts
230
+ ? packageJson.scripts
231
+ : {};
232
+ const hasLifecycle = ['install', 'postinstall', 'prepare'].some(
233
+ name => typeof scripts[name] === 'string' && scripts[name].trim() !== '',
234
+ );
235
+
236
+ process.exit(hasLifecycle ? 0 : 1);
237
+ } catch {
238
+ process.exit(0);
239
+ }
240
+ NODE
241
+ }
242
+
243
+ install_reuse_is_safe() {
244
+ local workspace package_path
245
+ for package_path in "$PROJECT_ROOT/.pnpmfile.cjs" "$PROJECT_ROOT/.pnpmfile.js"; do
246
+ if [ -e "$package_path" ]; then
247
+ echo "[node_modules] Reinstalling because pnpm hooks are present: $package_path"
248
+ return 1
249
+ fi
250
+ done
251
+
252
+ if [ -f "$PROJECT_ROOT/.npmrc" ] && grep -Eq '^[[:space:]]*pnpmfile[[:space:]]*=' "$PROJECT_ROOT/.npmrc"; then
253
+ echo "[node_modules] Reinstalling because .npmrc configures a pnpm hook."
254
+ return 1
255
+ fi
256
+
257
+ for workspace in . client server; do
258
+ package_path="$PROJECT_ROOT/$workspace/package.json"
259
+ [ -f "$package_path" ] || continue
260
+ if package_has_install_lifecycle "$package_path"; then
261
+ echo "[node_modules] Reinstalling because $package_path has an install lifecycle script."
262
+ return 1
263
+ fi
264
+ done
265
+ return 0
266
+ }
267
+
268
+ dependencies_are_ready() {
269
+ local workspace
270
+ [ -f "$WORK_DIR/node_modules/.modules.yaml" ] || return 1
271
+ for workspace in client server; do
272
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ] &&
273
+ [ ! -f "$WORK_DIR/$workspace/node_modules/.modules.yaml" ]; then
274
+ return 1
275
+ fi
276
+ done
277
+ return 0
278
+ }
279
+
280
+ # 判断顺序按代价从小到大排。指纹要读云盘上的 lockfile 和整个 patches/,所以放最后:只有其余
281
+ # 条件都满足、确实可能复用时才付这份开销。build.sh 和 prepare.sh 不设开关,第一行就返回了。
282
+ install_can_be_reused() {
283
+ local installed_fingerprint=""
284
+
285
+ [ "${COZE_REUSE_NODE_MODULES:-}" = "1" ] || return 1
286
+ install_requires_refresh "$@" && return 1
287
+ [ -f "$INSTALL_STATE_FILE" ] || return 1
288
+ IFS= read -r installed_fingerprint < "$INSTALL_STATE_FILE" || return 1
289
+ dependencies_are_ready || return 1
290
+ install_reuse_is_safe || return 1
291
+ [ "$installed_fingerprint" = "$(calculate_install_fingerprint "$@")" ] || return 1
292
+ return 0
293
+ }
294
+
295
+ write_install_state() {
296
+ local fingerprint="$1" temporary_state
297
+ temporary_state="$(mktemp "$WORK_DIR/.install-state.XXXXXX")"
298
+ printf '%s\n' "$fingerprint" > "$temporary_state"
299
+ mv -f "$temporary_state" "$INSTALL_STATE_FILE"
300
+ }
301
+
302
+ copy_install_metadata() {
303
+ local filename source_file target_file workspace
304
+ for filename in pnpm-lock.yaml pnpm-workspace.yaml .npmrc; do
305
+ source_file="$PROJECT_ROOT/$filename"
306
+ target_file="$WORK_DIR/$filename"
307
+ rm -f "$target_file"
308
+ if [ -f "$source_file" ]; then
309
+ cp "$source_file" "$target_file"
310
+ fi
311
+ done
312
+
313
+ link_install_entry "$PROJECT_ROOT/package.json" "$WORK_DIR/package.json"
314
+ link_install_entry "$PROJECT_ROOT/patches" "$WORK_DIR/patches"
315
+ link_install_entry "$PROJECT_ROOT/scripts" "$WORK_DIR/scripts"
316
+
317
+ for workspace in client server; do
318
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
319
+ mkdir -p "$WORK_DIR/$workspace"
320
+ link_install_entry "$PROJECT_ROOT/$workspace/package.json" "$WORK_DIR/$workspace/package.json"
321
+ link_install_entry "$PROJECT_ROOT/$workspace/scripts" "$WORK_DIR/$workspace/scripts"
322
+ else
323
+ rm -rf "$WORK_DIR/$workspace"
324
+ fi
325
+ done
326
+ }
327
+
328
+ link_node_modules() {
329
+ local source_dir="$1" target_dir="$2"
330
+ local current=""
331
+ mkdir -p "$target_dir"
332
+ if [ -L "$source_dir/node_modules" ]; then
333
+ current="$(readlink "$source_dir/node_modules")"
334
+ case "$current" in
335
+ "$NM_ROOT"/*/node_modules|"$NM_ROOT"/*/*/node_modules) ;;
336
+ *)
337
+ echo "[node_modules] refusing to replace unmanaged symlink: $source_dir/node_modules" >&2
338
+ exit 1
339
+ ;;
340
+ esac
341
+ rm "$source_dir/node_modules"
342
+ elif [ -e "$source_dir/node_modules" ]; then
343
+ rm -rf "$source_dir/node_modules"
344
+ fi
345
+ ln -s "$target_dir" "$source_dir/node_modules"
346
+ }
347
+
348
+ cleanup_legacy_shadow_project
349
+ copy_install_metadata
350
+
351
+ if install_can_be_reused "$@"; then
352
+ echo "[node_modules] Reusing unchanged dependencies in $WORK_DIR"
353
+ else
354
+ # A stale state file must not survive a failed install.
355
+ rm -f "$INSTALL_STATE_FILE"
356
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
357
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
358
+ exit 1
359
+ fi
360
+
361
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
362
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
363
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
364
+ chmod 0644 "$temporary_lockfile"
365
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
366
+ fi
367
+
368
+ # pnpm may have rewritten the lockfile, so record the fingerprint of the tree as it
369
+ # now stands. Otherwise the next run would see a changed input and reinstall.
370
+ write_install_state "$(calculate_install_fingerprint "$@")"
371
+ fi
372
+
373
+ link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
374
+ for workspace in client server; do
375
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
376
+ link_node_modules "$PROJECT_ROOT/$workspace" "$WORK_DIR/$workspace/node_modules"
377
+ fi
378
+ done
379
+
380
+ echo "[node_modules] Dependencies ready"
@@ -13,5 +13,5 @@ cd "${COZE_WORKSPACE_PATH}"
13
13
 
14
14
  echo "Installing dependencies..."
15
15
  if [[ "${COZE_WEB_LOCAL_MIRROR:-}" != "1" ]]; then
16
- pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
16
+ bash "$COZE_WORKSPACE_PATH/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
17
17
  fi
@@ -7,7 +7,7 @@ const hostname = process.env.HOSTNAME || 'localhost';
7
7
  const port = parseInt(process.env.PORT || '<%= port %>', 10);
8
8
 
9
9
  // Create Next.js app
10
- const app = next({ dev, hostname, port });
10
+ const app = next({ dev, hostname, port, webpack: true });
11
11
  const handle = app.getRequestHandler();
12
12
 
13
13
  app.prepare().then(() => {