@coze-arch/cli 0.1.2 → 0.1.3-alpha.32023e

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.
@@ -6,7 +6,7 @@ COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
6
6
  cd "${COZE_WORKSPACE_PATH}"
7
7
 
8
8
  echo "Installing dependencies..."
9
- pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
9
+ bash "$COZE_WORKSPACE_PATH/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
10
10
 
11
11
  echo "Building the Next.js project..."
12
12
  pnpm next build
@@ -0,0 +1,142 @@
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
+ COZE_ROOT="${COZE_DIR_PATH:-${HOME}/Coze/tmp}"
32
+ PROJECT_ID="$(basename "$PROJECT_ROOT")-$(printf '%s' "$PROJECT_ROOT" | cksum | awk '{print $1}')"
33
+ mkdir -p "$COZE_ROOT/nm"
34
+ COZE_ROOT="$(cd "$COZE_ROOT" && pwd -P)"
35
+ WORK_DIR="$COZE_ROOT/nm/$PROJECT_ID"
36
+ mkdir -p "$WORK_DIR"
37
+ case "$WORK_DIR" in
38
+ "$DRIVE_ROOT"|"$DRIVE_ROOT"/*)
39
+ echo "[node_modules] local dependency directory must not be on Coze Drive: $WORK_DIR" >&2
40
+ exit 1
41
+ ;;
42
+ esac
43
+
44
+ # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
45
+ # workspace directories stay real too, so pnpm never writes them to Drive.
46
+ mirror_root() {
47
+ local entry name
48
+ while IFS= read -r -d '' entry; do
49
+ name="$(basename "$entry")"
50
+ case "$name" in
51
+ node_modules|pnpm-lock.yaml) continue ;;
52
+ client|server)
53
+ [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
54
+ ;;
55
+ esac
56
+ rm -rf "$entry"
57
+ done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
58
+
59
+ while IFS= read -r -d '' entry; do
60
+ name="$(basename "$entry")"
61
+ case "$name" in
62
+ node_modules|pnpm-lock.yaml) continue ;;
63
+ client|server)
64
+ [ -f "$entry/package.json" ] && continue
65
+ ;;
66
+ esac
67
+ ln -s "$entry" "$WORK_DIR/$name"
68
+ done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
69
+ }
70
+
71
+ mirror_workspace() {
72
+ local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
73
+ local entry name
74
+ if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
75
+ rm -rf "$work_dir"
76
+ fi
77
+ mkdir -p "$work_dir"
78
+
79
+ while IFS= read -r -d '' entry; do
80
+ [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
81
+ done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
82
+
83
+ while IFS= read -r -d '' entry; do
84
+ name="$(basename "$entry")"
85
+ [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
86
+ done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
87
+ }
88
+
89
+ mirror_root
90
+ for workspace in client server; do
91
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
92
+ mirror_workspace "$workspace"
93
+ fi
94
+ done
95
+
96
+ # pnpm refuses to update a symlinked lockfile, so install against a local copy.
97
+ rm -rf "$WORK_DIR/pnpm-lock.yaml"
98
+ if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
99
+ cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
100
+ fi
101
+
102
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
103
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
104
+ rm -f "$WORK_DIR/pnpm-lock.yaml"
105
+ exit 1
106
+ fi
107
+
108
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
109
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
110
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
111
+ chmod 0644 "$temporary_lockfile"
112
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
113
+ fi
114
+
115
+ link_node_modules() {
116
+ local source_dir="$1" target_dir="$2"
117
+ local current=""
118
+ mkdir -p "$target_dir"
119
+ if [ -L "$source_dir/node_modules" ]; then
120
+ current="$(readlink "$source_dir/node_modules")"
121
+ case "$current" in
122
+ "$COZE_ROOT"/nm/*/node_modules|"$COZE_ROOT"/nm/*/*/node_modules) ;;
123
+ *)
124
+ echo "[node_modules] refusing to replace unmanaged symlink: $source_dir/node_modules" >&2
125
+ exit 1
126
+ ;;
127
+ esac
128
+ rm "$source_dir/node_modules"
129
+ elif [ -e "$source_dir/node_modules" ]; then
130
+ rm -rf "$source_dir/node_modules"
131
+ fi
132
+ ln -s "$target_dir" "$source_dir/node_modules"
133
+ }
134
+
135
+ link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
136
+ for workspace in client server; do
137
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
138
+ link_node_modules "$PROJECT_ROOT/$workspace" "$WORK_DIR/$workspace/node_modules"
139
+ fi
140
+ done
141
+
142
+ echo "[node_modules] Dependencies ready"
@@ -6,7 +6,4 @@ COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
6
6
  cd "${COZE_WORKSPACE_PATH}"
7
7
 
8
8
  echo "Installing dependencies..."
9
- pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
10
- if command -v coze-dev > /dev/null 2>&1 && coze-dev check-bins --help > /dev/null 2>&1; then
11
- coze-dev check-bins --fix
12
- fi
9
+ bash "$COZE_WORKSPACE_PATH/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
@@ -1,9 +1,5 @@
1
1
 
2
2
 
3
- import { spawn } from 'child_process';
4
- import { resolve, join, basename } from 'path';
5
- import { appendFileSync, openSync, closeSync, mkdirSync } from 'fs';
6
- import { homedir } from 'os';
7
3
 
8
4
 
9
5
 
@@ -57,61 +53,6 @@ const config = {
57
53
  onAfterRender: async (_context, _outputPath) => {
58
54
  // 输出由 init 命令统一处理
59
55
  },
60
-
61
- onComplete: async (_context, outputPath) => {
62
- // Skip pnpm update in test environment to avoid monorepo workspace issues
63
- if (process.env.NODE_ENV === 'test') {
64
- console.log('⊘ Skipping dependency update in test environment');
65
- return;
66
- }
67
-
68
- const cmd = 'pnpm';
69
- const args = ['update', 'coze-coding-dev-sdk@^0.7.25'];
70
- console.log(
71
- `\nTriggering: ${cmd} ${args.join(' ')} (running in background)`,
72
- );
73
-
74
- try {
75
- const projectRoot = resolve(outputPath);
76
-
77
- // Determine log directory
78
- const cozeHome = process.env.COZE_HOME || join(homedir(), '.coze');
79
- const logDir = process.env.COZE_LOG_DIR || join(cozeHome, 'logs');
80
- mkdirSync(logDir, { recursive: true });
81
-
82
- // Use project name in log file to avoid conflicts
83
- const projectName = basename(projectRoot);
84
- const logFile = join(logDir, `${projectName}-init.log`);
85
-
86
- // Write log header
87
- const timestamp = new Date().toISOString();
88
- appendFileSync(
89
- logFile,
90
- `\n=== [${timestamp}] ${cmd} ${args.join(' ')} ===\n`,
91
- );
92
-
93
- // Open log file for appending
94
- const logFd = openSync(logFile, 'a');
95
-
96
- // Spawn in detached mode
97
- const child = spawn(cmd, args, {
98
- cwd: projectRoot,
99
- detached: true,
100
- stdio: ['ignore', logFd, logFd],
101
- });
102
-
103
- child.unref();
104
- closeSync(logFd);
105
-
106
- console.log(
107
- '✓ coze-coding-dev-sdk update triggered (running in background)',
108
- );
109
- console.log(` Log file: ${logFile}`);
110
- } catch (error) {
111
- console.error('✗ Failed to trigger coze-coding-dev-sdk update:', error);
112
- console.log(' You can manually run: pnpm update coze-coding-dev-sdk');
113
- }
114
- },
115
56
  };
116
57
 
117
58
  export default config;
@@ -6,7 +6,7 @@ COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
6
6
  cd "${COZE_WORKSPACE_PATH}"
7
7
 
8
8
  echo "Installing dependencies..."
9
- pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
9
+ bash "$COZE_WORKSPACE_PATH/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
10
10
 
11
11
  echo "Building the Nuxt.js project..."
12
12
  pnpm nuxt build
@@ -0,0 +1,142 @@
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
+ COZE_ROOT="${COZE_DIR_PATH:-${HOME}/Coze/tmp}"
32
+ PROJECT_ID="$(basename "$PROJECT_ROOT")-$(printf '%s' "$PROJECT_ROOT" | cksum | awk '{print $1}')"
33
+ mkdir -p "$COZE_ROOT/nm"
34
+ COZE_ROOT="$(cd "$COZE_ROOT" && pwd -P)"
35
+ WORK_DIR="$COZE_ROOT/nm/$PROJECT_ID"
36
+ mkdir -p "$WORK_DIR"
37
+ case "$WORK_DIR" in
38
+ "$DRIVE_ROOT"|"$DRIVE_ROOT"/*)
39
+ echo "[node_modules] local dependency directory must not be on Coze Drive: $WORK_DIR" >&2
40
+ exit 1
41
+ ;;
42
+ esac
43
+
44
+ # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
45
+ # workspace directories stay real too, so pnpm never writes them to Drive.
46
+ mirror_root() {
47
+ local entry name
48
+ while IFS= read -r -d '' entry; do
49
+ name="$(basename "$entry")"
50
+ case "$name" in
51
+ node_modules|pnpm-lock.yaml) continue ;;
52
+ client|server)
53
+ [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
54
+ ;;
55
+ esac
56
+ rm -rf "$entry"
57
+ done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
58
+
59
+ while IFS= read -r -d '' entry; do
60
+ name="$(basename "$entry")"
61
+ case "$name" in
62
+ node_modules|pnpm-lock.yaml) continue ;;
63
+ client|server)
64
+ [ -f "$entry/package.json" ] && continue
65
+ ;;
66
+ esac
67
+ ln -s "$entry" "$WORK_DIR/$name"
68
+ done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
69
+ }
70
+
71
+ mirror_workspace() {
72
+ local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
73
+ local entry name
74
+ if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
75
+ rm -rf "$work_dir"
76
+ fi
77
+ mkdir -p "$work_dir"
78
+
79
+ while IFS= read -r -d '' entry; do
80
+ [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
81
+ done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
82
+
83
+ while IFS= read -r -d '' entry; do
84
+ name="$(basename "$entry")"
85
+ [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
86
+ done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
87
+ }
88
+
89
+ mirror_root
90
+ for workspace in client server; do
91
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
92
+ mirror_workspace "$workspace"
93
+ fi
94
+ done
95
+
96
+ # pnpm refuses to update a symlinked lockfile, so install against a local copy.
97
+ rm -rf "$WORK_DIR/pnpm-lock.yaml"
98
+ if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
99
+ cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
100
+ fi
101
+
102
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
103
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
104
+ rm -f "$WORK_DIR/pnpm-lock.yaml"
105
+ exit 1
106
+ fi
107
+
108
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
109
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
110
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
111
+ chmod 0644 "$temporary_lockfile"
112
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
113
+ fi
114
+
115
+ link_node_modules() {
116
+ local source_dir="$1" target_dir="$2"
117
+ local current=""
118
+ mkdir -p "$target_dir"
119
+ if [ -L "$source_dir/node_modules" ]; then
120
+ current="$(readlink "$source_dir/node_modules")"
121
+ case "$current" in
122
+ "$COZE_ROOT"/nm/*/node_modules|"$COZE_ROOT"/nm/*/*/node_modules) ;;
123
+ *)
124
+ echo "[node_modules] refusing to replace unmanaged symlink: $source_dir/node_modules" >&2
125
+ exit 1
126
+ ;;
127
+ esac
128
+ rm "$source_dir/node_modules"
129
+ elif [ -e "$source_dir/node_modules" ]; then
130
+ rm -rf "$source_dir/node_modules"
131
+ fi
132
+ ln -s "$target_dir" "$source_dir/node_modules"
133
+ }
134
+
135
+ link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
136
+ for workspace in client server; do
137
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
138
+ link_node_modules "$PROJECT_ROOT/$workspace" "$WORK_DIR/$workspace/node_modules"
139
+ fi
140
+ done
141
+
142
+ echo "[node_modules] Dependencies ready"
@@ -6,10 +6,7 @@ COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
6
6
  cd "${COZE_WORKSPACE_PATH}"
7
7
 
8
8
  echo "Installing dependencies..."
9
- pnpm install --prefer-frozen-lockfile --prefer-offline
10
- if command -v coze-dev > /dev/null 2>&1 && coze-dev check-bins --help > /dev/null 2>&1; then
11
- coze-dev check-bins --fix
12
- fi
9
+ bash "$COZE_WORKSPACE_PATH/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline
13
10
 
14
11
  echo "Preparing Nuxt project..."
15
12
  pnpm exec nuxt prepare
@@ -1,7 +1,8 @@
1
1
  #!/bin/bash
2
2
  set -Eeuo pipefail
3
3
 
4
- cd "${COZE_WORKSPACE_PATH}"
4
+ ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
5
+ cd "$ROOT_DIR"
5
6
  if [ -f "./.cozeproj/scripts/init_env.sh" ]; then
6
7
  echo "⚙️ Initializing environment..."
7
8
  # 使用 bash 执行,确保即使没有 x 权限也能跑
@@ -11,7 +12,7 @@ else
11
12
  fi
12
13
  echo "Installing dependencies..."
13
14
  # 安装所有依赖(包含 Taro 核心和 React)
14
- pnpm install
15
+ bash "$ROOT_DIR/.cozeproj/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline
15
16
 
16
17
  echo "Building the Taro project..."
17
18
  pnpm build
@@ -1,2 +1,5 @@
1
1
  #!/bin/bash
2
2
  set -Eeuo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
5
+ bash "$ROOT_DIR/.cozeproj/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline
@@ -194,7 +194,7 @@ cleanup_previous_run() {
194
194
  # ---------------------------------------------------------
195
195
  echo "📦 Installing dependencies..."
196
196
  PNPM_BIN="$(command -v pnpm)"
197
- "${PNPM_BIN}" install
197
+ bash "$ROOT_DIR/.cozeproj/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline
198
198
  echo "✅ Dependencies installed successfully!"
199
199
 
200
200
  # ---------------------------------------------------------
@@ -0,0 +1,142 @@
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
+ COZE_ROOT="${COZE_DIR_PATH:-${HOME}/Coze/tmp}"
32
+ PROJECT_ID="$(basename "$PROJECT_ROOT")-$(printf '%s' "$PROJECT_ROOT" | cksum | awk '{print $1}')"
33
+ mkdir -p "$COZE_ROOT/nm"
34
+ COZE_ROOT="$(cd "$COZE_ROOT" && pwd -P)"
35
+ WORK_DIR="$COZE_ROOT/nm/$PROJECT_ID"
36
+ mkdir -p "$WORK_DIR"
37
+ case "$WORK_DIR" in
38
+ "$DRIVE_ROOT"|"$DRIVE_ROOT"/*)
39
+ echo "[node_modules] local dependency directory must not be on Coze Drive: $WORK_DIR" >&2
40
+ exit 1
41
+ ;;
42
+ esac
43
+
44
+ # Mirror the project with symlinks. node_modules stays real in WORK_DIR;
45
+ # workspace directories stay real too, so pnpm never writes them to Drive.
46
+ mirror_root() {
47
+ local entry name
48
+ while IFS= read -r -d '' entry; do
49
+ name="$(basename "$entry")"
50
+ case "$name" in
51
+ node_modules|pnpm-lock.yaml) continue ;;
52
+ client|server)
53
+ [ -f "$PROJECT_ROOT/$name/package.json" ] && continue
54
+ ;;
55
+ esac
56
+ rm -rf "$entry"
57
+ done < <(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -print0)
58
+
59
+ while IFS= read -r -d '' entry; do
60
+ name="$(basename "$entry")"
61
+ case "$name" in
62
+ node_modules|pnpm-lock.yaml) continue ;;
63
+ client|server)
64
+ [ -f "$entry/package.json" ] && continue
65
+ ;;
66
+ esac
67
+ ln -s "$entry" "$WORK_DIR/$name"
68
+ done < <(find "$PROJECT_ROOT" -mindepth 1 -maxdepth 1 -print0)
69
+ }
70
+
71
+ mirror_workspace() {
72
+ local workspace="$1" source_dir="$PROJECT_ROOT/$1" work_dir="$WORK_DIR/$1"
73
+ local entry name
74
+ if [ -L "$work_dir" ] || { [ -e "$work_dir" ] && [ ! -d "$work_dir" ]; }; then
75
+ rm -rf "$work_dir"
76
+ fi
77
+ mkdir -p "$work_dir"
78
+
79
+ while IFS= read -r -d '' entry; do
80
+ [ "$(basename "$entry")" = "node_modules" ] || rm -rf "$entry"
81
+ done < <(find "$work_dir" -mindepth 1 -maxdepth 1 -print0)
82
+
83
+ while IFS= read -r -d '' entry; do
84
+ name="$(basename "$entry")"
85
+ [ "$name" = "node_modules" ] || ln -s "$entry" "$work_dir/$name"
86
+ done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0)
87
+ }
88
+
89
+ mirror_root
90
+ for workspace in client server; do
91
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
92
+ mirror_workspace "$workspace"
93
+ fi
94
+ done
95
+
96
+ # pnpm refuses to update a symlinked lockfile, so install against a local copy.
97
+ rm -rf "$WORK_DIR/pnpm-lock.yaml"
98
+ if [ -f "$PROJECT_ROOT/pnpm-lock.yaml" ]; then
99
+ cp "$PROJECT_ROOT/pnpm-lock.yaml" "$WORK_DIR/pnpm-lock.yaml"
100
+ fi
101
+
102
+ echo "[node_modules] Installing dependencies in $WORK_DIR"
103
+ if ! (cd "$WORK_DIR" && pnpm install "$@"); then
104
+ rm -f "$WORK_DIR/pnpm-lock.yaml"
105
+ exit 1
106
+ fi
107
+
108
+ if [ -f "$WORK_DIR/pnpm-lock.yaml" ]; then
109
+ temporary_lockfile="$(mktemp "$PROJECT_ROOT/.pnpm-lock.yaml.XXXXXX")"
110
+ cp "$WORK_DIR/pnpm-lock.yaml" "$temporary_lockfile"
111
+ chmod 0644 "$temporary_lockfile"
112
+ mv -f "$temporary_lockfile" "$PROJECT_ROOT/pnpm-lock.yaml"
113
+ fi
114
+
115
+ link_node_modules() {
116
+ local source_dir="$1" target_dir="$2"
117
+ local current=""
118
+ mkdir -p "$target_dir"
119
+ if [ -L "$source_dir/node_modules" ]; then
120
+ current="$(readlink "$source_dir/node_modules")"
121
+ case "$current" in
122
+ "$COZE_ROOT"/nm/*/node_modules|"$COZE_ROOT"/nm/*/*/node_modules) ;;
123
+ *)
124
+ echo "[node_modules] refusing to replace unmanaged symlink: $source_dir/node_modules" >&2
125
+ exit 1
126
+ ;;
127
+ esac
128
+ rm "$source_dir/node_modules"
129
+ elif [ -e "$source_dir/node_modules" ]; then
130
+ rm -rf "$source_dir/node_modules"
131
+ fi
132
+ ln -s "$target_dir" "$source_dir/node_modules"
133
+ }
134
+
135
+ link_node_modules "$PROJECT_ROOT" "$WORK_DIR/node_modules"
136
+ for workspace in client server; do
137
+ if [ -f "$PROJECT_ROOT/$workspace/package.json" ]; then
138
+ link_node_modules "$PROJECT_ROOT/$workspace" "$WORK_DIR/$workspace/node_modules"
139
+ fi
140
+ done
141
+
142
+ echo "[node_modules] Dependencies ready"
@@ -6,7 +6,7 @@ COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
6
6
  cd "${COZE_WORKSPACE_PATH}"
7
7
 
8
8
  echo "Installing dependencies..."
9
- pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
9
+ bash "$COZE_WORKSPACE_PATH/scripts/prepare-node-modules.sh" --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
10
10
 
11
11
  echo "Building frontend with Vite..."
12
12
  pnpm vite build