@coze-arch/cli 0.0.35 → 0.0.36-alpha.102c95

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 (146) hide show
  1. package/README.md +66 -104
  2. package/docs/deploy.md +172 -0
  3. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +74 -18
  4. package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +1 -1
  5. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +1 -1
  6. package/lib/__templates__/expo/client/metro.config.js +3 -1
  7. package/lib/__templates__/expo/pnpm-lock.yaml +5 -5
  8. package/lib/__templates__/expo/server/package.json +2 -2
  9. package/lib/__templates__/expo/server/src/index.ts +1 -1
  10. package/lib/__templates__/expo/template.config.js +11 -2
  11. package/lib/__templates__/native-static/.coze +2 -0
  12. package/lib/__templates__/native-static/scripts/serve.ps1 +7 -0
  13. package/lib/__templates__/nextjs/.coze +5 -0
  14. package/lib/__templates__/nextjs/scripts/build.ps1 +16 -0
  15. package/lib/__templates__/nextjs/scripts/dev.ps1 +63 -0
  16. package/lib/__templates__/nextjs/scripts/dev.sh +83 -2
  17. package/lib/__templates__/nextjs/scripts/prepare.ps1 +18 -0
  18. package/lib/__templates__/nextjs/scripts/start.ps1 +11 -0
  19. package/lib/__templates__/nextjs/scripts/validate.ps1 +8 -0
  20. package/lib/__templates__/nextjs/template.config.js +3 -1
  21. package/lib/__templates__/nuxt-vue/.coze +5 -0
  22. package/lib/__templates__/nuxt-vue/scripts/build.ps1 +12 -0
  23. package/lib/__templates__/nuxt-vue/scripts/dev.ps1 +63 -0
  24. package/lib/__templates__/nuxt-vue/scripts/dev.sh +82 -1
  25. package/lib/__templates__/nuxt-vue/scripts/prepare.ps1 +12 -0
  26. package/lib/__templates__/nuxt-vue/scripts/start.ps1 +11 -0
  27. package/lib/__templates__/nuxt-vue/scripts/validate.ps1 +8 -0
  28. package/lib/__templates__/phaser/.coze +18 -0
  29. package/lib/__templates__/phaser/README.md +45 -0
  30. package/lib/__templates__/phaser/_gitignore +23 -0
  31. package/lib/__templates__/phaser/_npmrc +14 -0
  32. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
  33. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
  34. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
  35. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
  36. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
  37. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
  38. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
  39. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
  40. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
  41. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
  42. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
  43. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
  44. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
  45. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
  46. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
  47. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
  48. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
  49. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
  50. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
  51. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
  52. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
  53. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
  54. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
  55. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
  56. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/manifest.json +11 -0
  57. package/lib/__templates__/phaser/debug-runtime/flow-graph.json +20 -0
  58. package/lib/__templates__/phaser/index.html +12 -0
  59. package/lib/__templates__/phaser/package.json +31 -0
  60. package/lib/__templates__/phaser/pnpm-lock.yaml +661 -0
  61. package/lib/__templates__/phaser/scripts/build.ps1 +12 -0
  62. package/lib/__templates__/phaser/scripts/build.sh +8 -0
  63. package/lib/__templates__/phaser/scripts/dev.ps1 +49 -0
  64. package/lib/__templates__/phaser/scripts/dev.sh +82 -0
  65. package/lib/__templates__/phaser/scripts/prepare.ps1 +8 -0
  66. package/lib/__templates__/phaser/scripts/prepare.sh +7 -0
  67. package/lib/__templates__/phaser/scripts/spawn-detached.cjs +29 -0
  68. package/lib/__templates__/phaser/scripts/start.ps1 +49 -0
  69. package/lib/__templates__/phaser/scripts/start.sh +82 -0
  70. package/lib/__templates__/phaser/scripts/validate.ps1 +7 -0
  71. package/lib/__templates__/phaser/scripts/validate.sh +7 -0
  72. package/lib/__templates__/phaser/src/assets.ts +15 -0
  73. package/lib/__templates__/phaser/src/global.d.ts +39 -0
  74. package/lib/__templates__/phaser/src/main.ts +28 -0
  75. package/lib/__templates__/phaser/src/scene/BootScene.ts +213 -0
  76. package/lib/__templates__/phaser/src/scene/DevLoadingScene.ts +69 -0
  77. package/lib/__templates__/phaser/src/style.css +28 -0
  78. package/lib/__templates__/phaser/src/types.ts +32 -0
  79. package/lib/__templates__/phaser/src/utils/asset-loader.ts +319 -0
  80. package/lib/__templates__/phaser/src/utils/index.ts +2 -0
  81. package/lib/__templates__/phaser/src/utils/mark-editable.ts +13 -0
  82. package/lib/__templates__/phaser/template.config.js +43 -0
  83. package/lib/__templates__/phaser/tsconfig.json +23 -0
  84. package/lib/__templates__/phaser/vite.config.ts +96 -0
  85. package/lib/__templates__/phaser-static/.coze +15 -0
  86. package/lib/__templates__/phaser-static/README.md +40 -0
  87. package/lib/__templates__/phaser-static/_gitignore +6 -0
  88. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
  89. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
  90. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
  91. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
  92. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
  93. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
  94. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
  95. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
  96. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
  97. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
  98. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
  99. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
  100. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
  101. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
  102. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
  103. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
  104. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
  105. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
  106. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
  107. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
  108. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
  109. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
  110. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
  111. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
  112. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/manifest.json +11 -0
  113. package/lib/__templates__/phaser-static/debug-runtime/flow-graph.json +20 -0
  114. package/lib/__templates__/phaser-static/index.html +17 -0
  115. package/lib/__templates__/phaser-static/scripts/serve.ps1 +7 -0
  116. package/lib/__templates__/phaser-static/src/assets.js +15 -0
  117. package/lib/__templates__/phaser-static/src/main.js +26 -0
  118. package/lib/__templates__/phaser-static/src/phaser.js +7 -0
  119. package/lib/__templates__/phaser-static/src/scene/BootScene.js +205 -0
  120. package/lib/__templates__/phaser-static/src/scene/DevLoadingScene.js +67 -0
  121. package/lib/__templates__/phaser-static/src/style.css +28 -0
  122. package/lib/__templates__/phaser-static/src/utils/asset-loader.js +267 -0
  123. package/lib/__templates__/phaser-static/src/utils/index.js +2 -0
  124. package/lib/__templates__/phaser-static/src/utils/mark-editable.js +3 -0
  125. package/lib/__templates__/phaser-static/template.config.js +35 -0
  126. package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +1 -1
  127. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +150 -68
  128. package/lib/__templates__/taro/AGENTS.md +11 -7
  129. package/lib/__templates__/taro/README.md +4 -4
  130. package/lib/__templates__/taro/config/index.ts +10 -2
  131. package/lib/__templates__/taro/pnpm-lock.yaml +5 -5
  132. package/lib/__templates__/taro/server/package.json +1 -1
  133. package/lib/__templates__/taro/server/src/main.ts +8 -2
  134. package/lib/__templates__/templates.json +51 -1
  135. package/lib/__templates__/vite/.coze +5 -0
  136. package/lib/__templates__/vite/scripts/build.ps1 +16 -0
  137. package/lib/__templates__/vite/scripts/dev.ps1 +63 -0
  138. package/lib/__templates__/vite/scripts/dev.sh +82 -1
  139. package/lib/__templates__/vite/scripts/prepare.ps1 +18 -0
  140. package/lib/__templates__/vite/scripts/start.ps1 +11 -0
  141. package/lib/__templates__/vite/scripts/validate.ps1 +8 -0
  142. package/lib/__templates__/vite/template.config.js +3 -1
  143. package/lib/cli.js +3503 -214
  144. package/lib/deploy/package-project.js +244 -0
  145. package/lib/deploy/package-project.py +183 -0
  146. package/package.json +5 -4
@@ -0,0 +1,7 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $port = if ($env:DEPLOY_RUN_PORT) { $env:DEPLOY_RUN_PORT } else { "8000" }
4
+
5
+ Write-Host "Starting static server on port $port..."
6
+ & python -m http.server $port --bind 0.0.0.0
7
+ exit $LASTEXITCODE
@@ -4,11 +4,16 @@ project_type = "web"
4
4
 
5
5
  [dev]
6
6
  build = ["bash", "./scripts/prepare.sh"]
7
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/prepare.ps1"]
7
8
  run = ["bash", "./scripts/dev.sh"]
9
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/dev.ps1"]
8
10
  validate = ["bash", "./scripts/validate.sh"]
11
+ validate_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/validate.ps1"]
9
12
  deps = ["git"] # -> apt install git
10
13
 
11
14
  [deploy]
12
15
  build = ["bash","./scripts/build.sh"]
16
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/build.ps1"]
13
17
  run = ["bash","./scripts/start.sh"]
18
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/start.ps1"]
14
19
  deps = ["git"] # -> apt install git
@@ -0,0 +1,16 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Installing dependencies..."
7
+ & pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
8
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
9
+
10
+ Write-Host "Building the Next.js project..."
11
+ & pnpm next build
12
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
13
+
14
+ Write-Host "Bundling server with tsup..."
15
+ & pnpm tsup src/server.ts --format cjs --platform node --target node20 --outDir dist --no-splitting --no-minify
16
+ exit $LASTEXITCODE
@@ -0,0 +1,63 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ function Get-WorkspacePath {
4
+ if ($env:COZE_WORKSPACE_PATH) {
5
+ return $env:COZE_WORKSPACE_PATH
6
+ }
7
+ return (Get-Location).Path
8
+ }
9
+
10
+ function Stop-ProcessTree([int] $processId) {
11
+ if ($processId -gt 0 -and (Get-Process -Id $processId -ErrorAction SilentlyContinue)) {
12
+ & taskkill.exe /PID $processId /T /F *> $null
13
+ }
14
+ }
15
+
16
+ function Stop-ListeningProcess([int] $port) {
17
+ $connections = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
18
+ $connections | Select-Object -ExpandProperty OwningProcess -Unique | ForEach-Object {
19
+ Stop-ProcessTree $_
20
+ }
21
+ }
22
+
23
+ $workspace = Get-WorkspacePath
24
+ $defaultPort = <%= port %>
25
+ $port = if ($env:DEPLOY_RUN_PORT) { [int] $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { [int] $env:PORT } else { $defaultPort }
26
+ Set-Location $workspace
27
+ Stop-ListeningProcess $port
28
+
29
+ <% if (process.env.NODE_ENV === 'test') { %>
30
+ $env:PORT = "$port"
31
+ & pnpm tsx watch src/server.ts
32
+ exit $LASTEXITCODE
33
+ <% } else { %>
34
+ $logDirectory = if ($env:COZE_LOG_DIR) { $env:COZE_LOG_DIR } else { Join-Path $workspace "logs" }
35
+ $logFile = Join-Path $logDirectory "server.log"
36
+ $errorLogFile = Join-Path $logDirectory "server-error.log"
37
+ $pidFile = Join-Path $logDirectory "server.pid"
38
+ New-Item -ItemType Directory -Force -Path $logDirectory | Out-Null
39
+
40
+ if (Test-Path $pidFile) {
41
+ Stop-ProcessTree ([int] (Get-Content $pidFile -Raw))
42
+ Remove-Item $pidFile -Force
43
+ }
44
+
45
+ $previousPort = $env:PORT
46
+ $env:PORT = "$port"
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
49
+ } finally {
50
+ if ($null -eq $previousPort) { Remove-Item Env:PORT -ErrorAction SilentlyContinue } else { $env:PORT = $previousPort }
51
+ }
52
+
53
+ $process.Id | Set-Content $pidFile
54
+ Start-Sleep -Seconds 1
55
+ if ($process.HasExited) {
56
+ Get-Content $errorLogFile -Tail 20 -ErrorAction SilentlyContinue
57
+ Remove-Item $pidFile -Force -ErrorAction SilentlyContinue
58
+ exit 1
59
+ }
60
+
61
+ Write-Host "Dev server started (PID: $($process.Id))."
62
+ Write-Host "Log file: $logFile"
63
+ <% } %>
@@ -7,7 +7,7 @@ PORT="${PORT:-<%= port %>}"
7
7
  COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
8
8
  DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
9
9
  <% } else { %>
10
- PORT=<%= port %>
10
+ PORT="${DEPLOY_RUN_PORT:-${PORT:-<%= port %>}}"
11
11
  COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
12
12
  DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
13
13
  <% } %>
@@ -32,8 +32,89 @@ kill_port_if_listening() {
32
32
  fi
33
33
  }
34
34
 
35
+ <% if (process.env.NODE_ENV === 'test') { %>
36
+ echo "Clearing port ${DEPLOY_RUN_PORT} before start."
37
+ kill_port_if_listening
38
+ echo "Starting HTTP service on port ${DEPLOY_RUN_PORT} for dev..."
39
+
40
+ # 测试环境保持服务为前台进程,便于 e2e 收集输出并停止进程。
41
+ exec env PORT="${DEPLOY_RUN_PORT}" pnpm tsx watch src/server.ts
42
+ <% } else { %>
43
+ LOG_DIR="${COZE_LOG_DIR:-${COZE_WORKSPACE_PATH}/logs}"
44
+ LOG_FILE="${LOG_DIR}/server.log"
45
+ PID_FILE="${LOG_DIR}/server.pid"
46
+
47
+ # coze-daemon 会在 runtime shell 退出时清理原进程组。
48
+ # 通过 Node detached spawn 创建独立 session/进程组,并将 stdio 直接写入日志。
49
+ spawn_detached() {
50
+ local cwd="$1"
51
+ local log_file="$2"
52
+ shift 2
53
+
54
+ node - "$cwd" "$log_file" "$@" <<'NODE'
55
+ const fs = require('node:fs');
56
+ const { spawn } = require('node:child_process');
57
+
58
+ const [cwd, logFile, command, ...args] = process.argv.slice(2);
59
+ if (!cwd || !logFile || !command) {
60
+ throw new Error('spawn_detached 缺少 cwd、log_file 或 command');
61
+ }
62
+
63
+ const logFd = fs.openSync(logFile, 'a');
64
+ try {
65
+ const child = spawn(command, args, {
66
+ cwd,
67
+ detached: true,
68
+ env: process.env,
69
+ stdio: ['ignore', logFd, logFd],
70
+ });
71
+ child.unref();
72
+ process.stdout.write(String(child.pid));
73
+ } finally {
74
+ fs.closeSync(logFd);
75
+ }
76
+ NODE
77
+ }
78
+
79
+ stop_detached() {
80
+ local pid="${1:-}"
81
+ if [[ -z "${pid}" ]]; then
82
+ return
83
+ fi
84
+
85
+ kill -TERM -- "-${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null || true
86
+ sleep 1
87
+ kill -KILL -- "-${pid}" 2>/dev/null || true
88
+ }
89
+
90
+ # 监听端口的是孙进程(pnpm -> tsx -> node),只清端口会漏掉上层 pnpm/tsx,
91
+ # 所以先按上次记录的 PID 把整个进程组回收掉。
92
+ if [[ -f "${PID_FILE}" ]]; then
93
+ stop_detached "$(cat "${PID_FILE}" 2>/dev/null || true)"
94
+ rm -f "${PID_FILE}"
95
+ fi
96
+
35
97
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
36
98
  kill_port_if_listening
37
99
  echo "Starting HTTP service on port ${DEPLOY_RUN_PORT} for dev..."
38
100
 
39
- PORT=${DEPLOY_RUN_PORT} pnpm tsx watch src/server.ts
101
+ mkdir -p "${LOG_DIR}"
102
+ : > "${LOG_FILE}"
103
+
104
+ export PORT="${DEPLOY_RUN_PORT}"
105
+ server_pid="$(spawn_detached "${COZE_WORKSPACE_PATH}" "${LOG_FILE}" \
106
+ "$(command -v pnpm)" tsx watch src/server.ts)"
107
+ echo "${server_pid}" > "${PID_FILE}"
108
+
109
+ sleep 1
110
+ if [[ -z "${server_pid}" ]] || ! kill -0 "${server_pid}" 2>/dev/null; then
111
+ echo "Dev server failed to start. See ${LOG_FILE}." >&2
112
+ tail -n 20 "${LOG_FILE}" >&2 || true
113
+ rm -f "${PID_FILE}"
114
+ exit 1
115
+ fi
116
+
117
+ echo "Dev server started (PID: ${server_pid})."
118
+ echo "Log file: ${LOG_FILE}"
119
+ echo "PID file: ${PID_FILE}"
120
+ <% } %>
@@ -0,0 +1,18 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Installing dependencies..."
7
+ & pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
8
+ if ($LASTEXITCODE -ne 0) {
9
+ exit $LASTEXITCODE
10
+ }
11
+
12
+ if (Get-Command coze-dev -ErrorAction SilentlyContinue) {
13
+ & coze-dev check-bins --help *> $null
14
+ if ($LASTEXITCODE -eq 0) {
15
+ & coze-dev check-bins --fix
16
+ exit $LASTEXITCODE
17
+ }
18
+ }
@@ -0,0 +1,11 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ $defaultPort = <%= port %>
5
+ $port = if ($env:DEPLOY_RUN_PORT) { $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { $env:PORT } else { $defaultPort }
6
+ Set-Location $workspace
7
+
8
+ Write-Host "Starting HTTP service on port $port for deploy..."
9
+ $env:PORT = "$port"
10
+ & node dist/server.js
11
+ exit $LASTEXITCODE
@@ -0,0 +1,8 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Running validate..."
7
+ & pnpm validate
8
+ exit $LASTEXITCODE
@@ -3,6 +3,7 @@
3
3
  import { spawn } from 'child_process';
4
4
  import { resolve, join, basename } from 'path';
5
5
  import { appendFileSync, openSync, closeSync, mkdirSync } from 'fs';
6
+ import { homedir } from 'os';
6
7
 
7
8
 
8
9
 
@@ -74,7 +75,8 @@ const config = {
74
75
  const projectRoot = resolve(outputPath);
75
76
 
76
77
  // Determine log directory
77
- const logDir = process.env.COZE_LOG_DIR || resolve(__dirname, '../.log');
78
+ const cozeHome = process.env.COZE_HOME || join(homedir(), '.coze');
79
+ const logDir = process.env.COZE_LOG_DIR || join(cozeHome, 'logs');
78
80
  mkdirSync(logDir, { recursive: true });
79
81
 
80
82
  // Use project name in log file to avoid conflicts
@@ -4,11 +4,16 @@ project_type = "web"
4
4
 
5
5
  [dev]
6
6
  build = ["bash", "./scripts/prepare.sh"]
7
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/prepare.ps1"]
7
8
  run = ["bash", "./scripts/dev.sh"]
9
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/dev.ps1"]
8
10
  validate = ["bash", "./scripts/validate.sh"]
11
+ validate_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/validate.ps1"]
9
12
  deps = ["git"] # -> apt install git
10
13
 
11
14
  [deploy]
12
15
  build = ["bash","./scripts/build.sh"]
16
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/build.ps1"]
13
17
  run = ["bash","./scripts/start.sh"]
18
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/start.ps1"]
14
19
  deps = ["git"] # -> apt install git
@@ -0,0 +1,12 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Installing dependencies..."
7
+ & pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
8
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
9
+
10
+ Write-Host "Building the Nuxt.js project..."
11
+ & pnpm nuxt build
12
+ exit $LASTEXITCODE
@@ -0,0 +1,63 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ function Get-WorkspacePath {
4
+ if ($env:COZE_WORKSPACE_PATH) {
5
+ return $env:COZE_WORKSPACE_PATH
6
+ }
7
+ return (Get-Location).Path
8
+ }
9
+
10
+ function Stop-ProcessTree([int] $processId) {
11
+ if ($processId -gt 0 -and (Get-Process -Id $processId -ErrorAction SilentlyContinue)) {
12
+ & taskkill.exe /PID $processId /T /F *> $null
13
+ }
14
+ }
15
+
16
+ function Stop-ListeningProcess([int] $port) {
17
+ $connections = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
18
+ $connections | Select-Object -ExpandProperty OwningProcess -Unique | ForEach-Object {
19
+ Stop-ProcessTree $_
20
+ }
21
+ }
22
+
23
+ $workspace = Get-WorkspacePath
24
+ $defaultPort = <%= port %>
25
+ $port = if ($env:DEPLOY_RUN_PORT) { [int] $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { [int] $env:PORT } else { $defaultPort }
26
+ Set-Location $workspace
27
+ Stop-ListeningProcess $port
28
+
29
+ <% if (process.env.NODE_ENV === 'test') { %>
30
+ $env:PORT = "$port"
31
+ & pnpm nuxt dev
32
+ exit $LASTEXITCODE
33
+ <% } else { %>
34
+ $logDirectory = if ($env:COZE_LOG_DIR) { $env:COZE_LOG_DIR } else { Join-Path $workspace "logs" }
35
+ $logFile = Join-Path $logDirectory "server.log"
36
+ $errorLogFile = Join-Path $logDirectory "server-error.log"
37
+ $pidFile = Join-Path $logDirectory "server.pid"
38
+ New-Item -ItemType Directory -Force -Path $logDirectory | Out-Null
39
+
40
+ if (Test-Path $pidFile) {
41
+ Stop-ProcessTree ([int] (Get-Content $pidFile -Raw))
42
+ Remove-Item $pidFile -Force
43
+ }
44
+
45
+ $previousPort = $env:PORT
46
+ $env:PORT = "$port"
47
+ try {
48
+ $process = Start-Process -FilePath $env:ComSpec -ArgumentList @("/d", "/s", "/c", "pnpm nuxt dev") -WorkingDirectory $workspace -RedirectStandardOutput $logFile -RedirectStandardError $errorLogFile -PassThru
49
+ } finally {
50
+ if ($null -eq $previousPort) { Remove-Item Env:PORT -ErrorAction SilentlyContinue } else { $env:PORT = $previousPort }
51
+ }
52
+
53
+ $process.Id | Set-Content $pidFile
54
+ Start-Sleep -Seconds 1
55
+ if ($process.HasExited) {
56
+ Get-Content $errorLogFile -Tail 20 -ErrorAction SilentlyContinue
57
+ Remove-Item $pidFile -Force -ErrorAction SilentlyContinue
58
+ exit 1
59
+ }
60
+
61
+ Write-Host "Nuxt dev server started (PID: $($process.Id))."
62
+ Write-Host "Log file: $logFile"
63
+ <% } %>
@@ -32,8 +32,89 @@ kill_port_if_listening() {
32
32
  fi
33
33
  }
34
34
 
35
+ <% if (process.env.NODE_ENV === 'test') { %>
36
+ echo "Clearing port ${DEPLOY_RUN_PORT} before start."
37
+ kill_port_if_listening
38
+ echo "Starting Nuxt dev server on port ${DEPLOY_RUN_PORT}..."
39
+
40
+ # 测试环境保持服务为前台进程,便于 e2e 收集输出并停止进程。
41
+ exec env PORT="${DEPLOY_RUN_PORT}" pnpm nuxt dev
42
+ <% } else { %>
43
+ LOG_DIR="${COZE_LOG_DIR:-${COZE_WORKSPACE_PATH}/logs}"
44
+ LOG_FILE="${LOG_DIR}/server.log"
45
+ PID_FILE="${LOG_DIR}/server.pid"
46
+
47
+ # coze-daemon 会在 runtime shell 退出时清理原进程组。
48
+ # 通过 Node detached spawn 创建独立 session/进程组,并将 stdio 直接写入日志。
49
+ spawn_detached() {
50
+ local cwd="$1"
51
+ local log_file="$2"
52
+ shift 2
53
+
54
+ node - "$cwd" "$log_file" "$@" <<'NODE'
55
+ const fs = require('node:fs');
56
+ const { spawn } = require('node:child_process');
57
+
58
+ const [cwd, logFile, command, ...args] = process.argv.slice(2);
59
+ if (!cwd || !logFile || !command) {
60
+ throw new Error('spawn_detached 缺少 cwd、log_file 或 command');
61
+ }
62
+
63
+ const logFd = fs.openSync(logFile, 'a');
64
+ try {
65
+ const child = spawn(command, args, {
66
+ cwd,
67
+ detached: true,
68
+ env: process.env,
69
+ stdio: ['ignore', logFd, logFd],
70
+ });
71
+ child.unref();
72
+ process.stdout.write(String(child.pid));
73
+ } finally {
74
+ fs.closeSync(logFd);
75
+ }
76
+ NODE
77
+ }
78
+
79
+ stop_detached() {
80
+ local pid="${1:-}"
81
+ if [[ -z "${pid}" ]]; then
82
+ return
83
+ fi
84
+
85
+ kill -TERM -- "-${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null || true
86
+ sleep 1
87
+ kill -KILL -- "-${pid}" 2>/dev/null || true
88
+ }
89
+
90
+ # 监听端口的是孙进程(pnpm -> nuxt -> node),只清端口会漏掉上层 pnpm/nuxt,
91
+ # 所以先按上次记录的 PID 把整个进程组回收掉。
92
+ if [[ -f "${PID_FILE}" ]]; then
93
+ stop_detached "$(cat "${PID_FILE}" 2>/dev/null || true)"
94
+ rm -f "${PID_FILE}"
95
+ fi
96
+
35
97
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
36
98
  kill_port_if_listening
37
99
  echo "Starting Nuxt dev server on port ${DEPLOY_RUN_PORT}..."
38
100
 
39
- PORT=${DEPLOY_RUN_PORT} pnpm nuxt dev
101
+ mkdir -p "${LOG_DIR}"
102
+ : > "${LOG_FILE}"
103
+
104
+ export PORT="${DEPLOY_RUN_PORT}"
105
+ server_pid="$(spawn_detached "${COZE_WORKSPACE_PATH}" "${LOG_FILE}" \
106
+ "$(command -v pnpm)" nuxt dev)"
107
+ echo "${server_pid}" > "${PID_FILE}"
108
+
109
+ sleep 1
110
+ if [[ -z "${server_pid}" ]] || ! kill -0 "${server_pid}" 2>/dev/null; then
111
+ echo "Dev server failed to start. See ${LOG_FILE}." >&2
112
+ tail -n 20 "${LOG_FILE}" >&2 || true
113
+ rm -f "${PID_FILE}"
114
+ exit 1
115
+ fi
116
+
117
+ echo "Dev server started (PID: ${server_pid})."
118
+ echo "Log file: ${LOG_FILE}"
119
+ echo "PID file: ${PID_FILE}"
120
+ <% } %>
@@ -0,0 +1,12 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Installing dependencies..."
7
+ & pnpm install --prefer-frozen-lockfile --prefer-offline
8
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
9
+
10
+ Write-Host "Preparing Nuxt..."
11
+ & pnpm exec nuxt prepare
12
+ exit $LASTEXITCODE
@@ -0,0 +1,11 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ $defaultPort = <%= port %>
5
+ $port = if ($env:DEPLOY_RUN_PORT) { $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { $env:PORT } else { $defaultPort }
6
+ Set-Location $workspace
7
+
8
+ Write-Host "Starting Nuxt.js service on port $port for production..."
9
+ $env:PORT = "$port"
10
+ & node .output/server/index.mjs
11
+ exit $LASTEXITCODE
@@ -0,0 +1,8 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Running validate..."
7
+ & pnpm validate
8
+ exit $LASTEXITCODE
@@ -0,0 +1,18 @@
1
+ [project]
2
+ requires = ["nodejs-24"]
3
+ project_type = "game"
4
+ game_type = "phaser"
5
+
6
+ [dev]
7
+ build = ["bash", "./scripts/prepare.sh"]
8
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/prepare.ps1"]
9
+ run = ["bash", "./scripts/dev.sh"]
10
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/dev.ps1"]
11
+ validate = ["bash", "./scripts/validate.sh"]
12
+ validate_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/validate.ps1"]
13
+
14
+ [deploy]
15
+ build = ["bash", "./scripts/build.sh"]
16
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/build.ps1"]
17
+ run = ["bash", "./scripts/start.sh"]
18
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/start.ps1"]
@@ -0,0 +1,45 @@
1
+ # <%= appName %>
2
+
3
+ 这是一个基于 Phaser、Vite 和 TypeScript 的 2D 游戏项目,由扣子编程 CLI 创建。
4
+
5
+ ## 快速开始
6
+
7
+ ```bash
8
+ coze-dev dev
9
+ ```
10
+
11
+ 开发服务器默认运行在 [http://127.0.0.1:<%= port %>](http://127.0.0.1:<%= port %>)。
12
+
13
+ ```bash
14
+ coze-dev validate # TypeScript 类型检查
15
+ coze-dev build # 生产构建
16
+ coze-dev start # 预览生产构建
17
+ ```
18
+
19
+ ## 文件结构
20
+
21
+ ```text
22
+ ├── assets/ # 图片、序列帧、视频和音频
23
+ ├── debug-runtime/ # 调试 Flow
24
+ ├── src/assets.ts # 素材 key 与路径
25
+ ├── src/main.ts # 游戏入口
26
+ ├── src/scene/BootScene.ts # 启动与全量加载
27
+ ├── src/utils/asset-loader.ts # 批量和单素材加载
28
+ ├── src/types.ts # 类型定义
29
+ └── vite.config.ts # Bridge 注入与素材目录映射
30
+ ```
31
+
32
+ - 素材按类型放在 `assets/`,并登记到 `src/assets.ts` 对应的分类表。
33
+ - 序列帧只登记文件夹;Loader 从 `manifest.json` 读取帧数和帧率。
34
+ - `BootScene` 加载游戏素材;运行时可用 `loadAsset(this, key)` 单独加载。
35
+ - 开发和生产都使用稳定的 `assets/...` 路径,生产构建原样复制素材目录。
36
+
37
+ `IMAGES`、`IMAGE_SEQUENCES`、`VIDEOS` 和 `AUDIOS` 是四个素材分类表。
38
+
39
+ ## 可视化编辑标识
40
+
41
+ 用 `markEditable` 标记可在编辑器中调整的对象;第三个参数可选,仅用于编辑器展示名称:
42
+
43
+ ```ts
44
+ markEditable('ui.start-button', button, { label: '开始按钮' });
45
+ ```
@@ -0,0 +1,23 @@
1
+ node_modules/
2
+ dist/
3
+ coverage/
4
+
5
+ .env
6
+ .env.*
7
+ !.env.example
8
+
9
+ *.log
10
+ *.tsbuildinfo
11
+ logs/
12
+ .vite/
13
+ .cache/
14
+ node-compile-cache/
15
+
16
+ .DS_Store
17
+ ._*
18
+ .idea/
19
+ .vscode/
20
+
21
+ .coze-logs/
22
+ .codegraph/
23
+ .preview/
@@ -0,0 +1,14 @@
1
+ loglevel=error
2
+ registry=https://registry.npmmirror.com
3
+
4
+ strictStorePkgContentCheck=false
5
+ verifyStoreIntegrity=false
6
+ network-concurrency=16
7
+ fetch-retries=3
8
+ fetch-timeout=60000
9
+ strict-peer-dependencies=false
10
+ auto-install-peers=true
11
+ lockfile=true
12
+ prefer-frozen-lockfile=true
13
+ resolution-mode=highest
14
+ update-notifier=false