cardbuddy 0.24.0 → 0.25.0
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.
- package/README.md +2 -2
- package/dist/init.js +9 -2
- package/dist/preview-editor/assets/{index-BumNBo-n.js → index-DL4ZCJCA.js} +13 -13
- package/dist/preview-editor/index.html +1 -1
- package/dist/skills-upgrade.js +59 -0
- package/dist/vendored/server/core/browser.js +7 -4
- package/dist/vendored/skills/dsl-card-generator/references/generation_pitfalls.md +1 -1
- package/dist/vendored/skills/mbank-design-gen/tools/screenshot.mjs +15 -7
- package/dist/vendored/skills/platform-card-sync/scripts/api_batch_sync.mjs +12 -4
- package/dist/vendored/skills/platform-session-navigator/scripts/package-lock.json +1 -16
- package/dist/vendored/skills/platform-session-navigator/scripts/package.json +2 -2
- package/dist/vendored/skills/platform-session-navigator/scripts/platform_login.mjs +12 -1
- package/dist/vendored/skills/platform-session-navigator/scripts/session-manager.mjs +1 -1
- package/package.json +2 -4
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16-Cg6Nrosk.png" />
|
|
9
9
|
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32-B_1744sp.png" />
|
|
10
10
|
<link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon-BQcES9QK.png" />
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-DL4ZCJCA.js"></script>
|
|
12
12
|
<link rel="stylesheet" crossorigin href="/assets/index-MWKPP9nd.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
package/dist/skills-upgrade.js
CHANGED
|
@@ -18,12 +18,16 @@
|
|
|
18
18
|
* 交互环境外(非 TTY)无法确认时,必须带 --force 才能升级,否则明确拒绝并提示(不再
|
|
19
19
|
* 静默跳过、假装升级成功)。
|
|
20
20
|
* 标志:--force/-y 跳过确认直接覆盖;--prune 额外删除 ORPHAN;--dry-run 只报告不落盘。
|
|
21
|
+
* 依赖检查:升级后探测 skills/ 内 package.json 声明的依赖能否从工程解析,缺失的
|
|
22
|
+
* 显式给出 `npm install <pkg>` 补装指引(升级不自动装依赖——是否动工程 node_modules
|
|
23
|
+
* 由用户决定;解析探测与脚本运行时的 Node 解析链一致)。
|
|
21
24
|
* 同步后写 skills/.synced-from = 当前装包版本,供下次 drift 检测与启动提示。
|
|
22
25
|
*/
|
|
23
26
|
import fs from 'node:fs'
|
|
24
27
|
import path from 'node:path'
|
|
25
28
|
import readline from 'node:readline/promises'
|
|
26
29
|
import { fileURLToPath } from 'node:url'
|
|
30
|
+
import { createRequire } from 'node:module'
|
|
27
31
|
import chalk from 'chalk'
|
|
28
32
|
import { loadConfig } from './config.js'
|
|
29
33
|
|
|
@@ -75,6 +79,38 @@ function walkFiles(dir, base = dir, out = []) {
|
|
|
75
79
|
return out
|
|
76
80
|
}
|
|
77
81
|
|
|
82
|
+
/**
|
|
83
|
+
* 收集 skills/ 内各 package.json 声明的依赖中「从其所在目录无法解析」的包名。
|
|
84
|
+
* 技能脚本运行时按 Node 规则从脚本位置向上找 node_modules(先 skill 自身,再工程根),
|
|
85
|
+
* 这里用 createRequire 从该 package.json 所在目录模拟同一解析链;解析不到的即缺口——
|
|
86
|
+
* 升级只拷文件不装依赖,缺口必须显式提示用户补装(0.83.x 事故的教训:
|
|
87
|
+
* playwright 曾是 optional 依赖静默缺失,脚本运行时才报 Cannot find package)。
|
|
88
|
+
* @param {string} destSkills 工程内 skills/ 目录
|
|
89
|
+
* @returns {string[]} 形如 "playwright-core(platform-session-navigator/scripts/package.json)"
|
|
90
|
+
*/
|
|
91
|
+
function collectMissingSkillDeps(destSkills) {
|
|
92
|
+
const missing = []
|
|
93
|
+
for (const rel of walkFiles(destSkills)) {
|
|
94
|
+
if (path.posix.basename(rel) !== 'package.json') continue
|
|
95
|
+
const pkgPath = path.join(destSkills, rel)
|
|
96
|
+
let deps
|
|
97
|
+
try {
|
|
98
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
|
|
99
|
+
deps = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
100
|
+
} catch {
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
for (const name of Object.keys(deps)) {
|
|
104
|
+
try {
|
|
105
|
+
createRequire(path.join(pkgPath, 'index.js')).resolve(name)
|
|
106
|
+
} catch {
|
|
107
|
+
missing.push(`${name}(${rel})`)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return missing
|
|
112
|
+
}
|
|
113
|
+
|
|
78
114
|
/**
|
|
79
115
|
* 比对源/目标技能树(内容比对)。
|
|
80
116
|
* @returns {{ added:string[], same:string[], modified:string[], orphan:string[] }}
|
|
@@ -153,6 +189,25 @@ export async function runSkillsUpgrade({
|
|
|
153
189
|
const warn = (m) => say(chalk.yellow(`• ${m}`))
|
|
154
190
|
const dim = (m) => say(chalk.dim(`• ${m}`))
|
|
155
191
|
|
|
192
|
+
// 依赖在位检查(升级只同步文件、不装依赖,但必须把缺口显式暴露出来):
|
|
193
|
+
// 逐个解析 skills/ 内 package.json 声明的依赖,解析不到的给出补装命令。
|
|
194
|
+
const reportDeps = () => {
|
|
195
|
+
let missing
|
|
196
|
+
try {
|
|
197
|
+
missing = collectMissingSkillDeps(destSkills)
|
|
198
|
+
} catch {
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
if (!missing.length) {
|
|
202
|
+
dim('技能依赖在位:skills/ 内 package.json 声明的依赖均可从工程解析')
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
const names = [...new Set(missing.map((m) => m.slice(0, m.indexOf('('))))]
|
|
206
|
+
warn(`⚠ 检测到 ${missing.length} 个技能依赖无法解析(新版本技能可能带来新依赖):`)
|
|
207
|
+
for (const m of missing) say(chalk.yellow(` ${m}`))
|
|
208
|
+
say(chalk.yellow(` 请在工程根执行:npm install ${names.join(' ')}`))
|
|
209
|
+
}
|
|
210
|
+
|
|
156
211
|
if (dryRun) say(chalk.yellow('(dry-run:只报告将要做的事,不落盘)'))
|
|
157
212
|
|
|
158
213
|
if (!src || !fs.existsSync(src)) {
|
|
@@ -169,6 +224,7 @@ export async function runSkillsUpgrade({
|
|
|
169
224
|
|
|
170
225
|
if (!diff.added.length && !diff.modified.length && !diff.orphan.length && fs.existsSync(destSkills)) {
|
|
171
226
|
dim(`skills 已是最新(cardbuddy@${version},无新增 / 修改 / 孤儿)`)
|
|
227
|
+
reportDeps()
|
|
172
228
|
return 0
|
|
173
229
|
}
|
|
174
230
|
|
|
@@ -240,6 +296,9 @@ export async function runSkillsUpgrade({
|
|
|
240
296
|
}
|
|
241
297
|
}
|
|
242
298
|
|
|
299
|
+
// 依赖在位检查(dry-run 也报,作为升级后的预期状态)
|
|
300
|
+
reportDeps()
|
|
301
|
+
|
|
243
302
|
// 汇总
|
|
244
303
|
log('')
|
|
245
304
|
say(chalk.green(dryRun ? 'dry-run 完成(未落盘)' : 'skills 升级完成'))
|
|
@@ -35,8 +35,11 @@ let chromiumMod = null
|
|
|
35
35
|
|
|
36
36
|
/** 取(惰性启动的)单例浏览器;启动失败会把 browserPromise 复位并抛出 */
|
|
37
37
|
async function getBrowser() {
|
|
38
|
-
// 动态 import playwright:避免其进入 vite.config
|
|
39
|
-
|
|
38
|
+
// 动态 import playwright-core:避免其进入 vite.config 加载图(见文件头注释)。
|
|
39
|
+
// 用 playwright-core 而非 playwright:浏览器走系统 Chrome(channel: 'chrome'),
|
|
40
|
+
// 只需 JS API;playwright 的 postinstall 浏览器下载作为 optional 依赖失败时会被
|
|
41
|
+
// npm 静默跳过,导致 vendored 发布态运行时报 Cannot find package(0.83.x 事故)。
|
|
42
|
+
if (!chromiumMod) chromiumMod = await import('playwright-core')
|
|
40
43
|
if (!browserPromise) {
|
|
41
44
|
browserPromise = chromiumMod.chromium
|
|
42
45
|
.launch({ channel: 'chrome', headless: true })
|
|
@@ -98,9 +101,9 @@ function serialize(task) {
|
|
|
98
101
|
|
|
99
102
|
/**
|
|
100
103
|
* 打开卡片渲染页(chrome=off 纯净模式)并等待首帧稳定。
|
|
101
|
-
* @param {import('playwright').BrowserContext} context
|
|
104
|
+
* @param {import('playwright-core').BrowserContext} context
|
|
102
105
|
* @param {string} id 卡片 id
|
|
103
|
-
* @returns {Promise<{ page: import('playwright').Page, screen: import('playwright').ElementHandle | null }>}
|
|
106
|
+
* @returns {Promise<{ page: import('playwright-core').Page, screen: import('playwright-core').ElementHandle | null }>}
|
|
104
107
|
*/
|
|
105
108
|
async function openCardScreen(context, id) {
|
|
106
109
|
const page = await context.newPage()
|
|
@@ -169,7 +169,7 @@ node skills/dsl-card-generator/scripts/render_card.mjs --id <id> --width 375 --o
|
|
|
169
169
|
```js
|
|
170
170
|
// 仅当需要自定义页面交互/逐样式断言且宿主 dev server(5180) 已启动时使用;
|
|
171
171
|
// 本 skill 的离线 render_card.mjs 不提供任意页面交互,复制 skill 到其他项目后该配方按需自建。
|
|
172
|
-
import { chromium } from 'playwright';
|
|
172
|
+
import { chromium } from 'playwright-core';
|
|
173
173
|
const ts = Date.now();
|
|
174
174
|
const url = `http://localhost:5180/?card=<id>&t=${ts}`;
|
|
175
175
|
const browser = await chromium.launch({ channel: 'chrome', args: ['--no-sandbox'] });
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// MBank mockup 截图工具:把 375×812 的 mockup HTML 导出为 750×1624 @2x PNG。
|
|
3
3
|
// 用法:node <skill>/tools/screenshot.mjs <input.html> [output.png] [--full]
|
|
4
4
|
// --full 整页截图(长页 mockup 用;默认 812pt 视口截断)
|
|
5
|
-
// 依赖 playwright
|
|
5
|
+
// 依赖 playwright-core(免浏览器下载的纯 JS API,从自身位置向上解析)。
|
|
6
|
+
// 浏览器优先走系统 Chrome(channel: 'chrome',仓库约定),未找到时才尝试内置浏览器。
|
|
6
7
|
import { createRequire } from 'node:module';
|
|
7
8
|
import { dirname, resolve } from 'node:path';
|
|
8
9
|
import { fileURLToPath } from 'node:url';
|
|
@@ -10,7 +11,15 @@ import { pathToFileURL } from 'node:url';
|
|
|
10
11
|
|
|
11
12
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
12
13
|
const require = createRequire(import.meta.url);
|
|
13
|
-
|
|
14
|
+
let chromium;
|
|
15
|
+
try {
|
|
16
|
+
({ chromium } = require('playwright-core'));
|
|
17
|
+
} catch {
|
|
18
|
+
console.error(
|
|
19
|
+
'[screenshot] 缺少依赖 playwright-core:请在本工程根执行 npm install(cardbuddy 依赖会带上),或手动 npm i playwright-core。',
|
|
20
|
+
);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
14
23
|
|
|
15
24
|
const args = process.argv.slice(2);
|
|
16
25
|
const full = args.includes('--full');
|
|
@@ -22,15 +31,14 @@ if (!input) {
|
|
|
22
31
|
}
|
|
23
32
|
const output = positional[1] || input.replace(/\.html$/i, '') + '.png';
|
|
24
33
|
|
|
25
|
-
//
|
|
26
|
-
// 与仓库「Playwright + 系统 Chrome 验证」约定一致,避免强依赖 npx playwright install。
|
|
34
|
+
// 优先用系统 Chrome(channel: 'chrome',仓库约定);不可用时回退内置浏览器。
|
|
27
35
|
let browser;
|
|
28
36
|
try {
|
|
29
|
-
browser = await chromium.launch();
|
|
37
|
+
browser = await chromium.launch({ channel: 'chrome' });
|
|
30
38
|
} catch (err) {
|
|
31
39
|
if (!/Executable doesn't exist/.test(String(err?.message ?? err))) throw err;
|
|
32
|
-
console.error('[screenshot]
|
|
33
|
-
browser = await chromium.launch(
|
|
40
|
+
console.error('[screenshot] 未找到系统 Chrome,回退 Playwright 内置浏览器');
|
|
41
|
+
browser = await chromium.launch();
|
|
34
42
|
}
|
|
35
43
|
const page = await browser.newPage({
|
|
36
44
|
viewport: { width: 375, height: 812 },
|
|
@@ -29,10 +29,18 @@ const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
|
29
29
|
const skillDir = path.resolve(scriptDir, '..');
|
|
30
30
|
// skill now lives under <repo-root>/skills/<name>: repo root is two levels up from skillDir
|
|
31
31
|
const workspace = path.resolve(skillDir, '..', '..');
|
|
32
|
-
// 与 platform_login.mjs 保持一致的解析方式:用裸标识符让 Node 从项目根 node_modules
|
|
33
|
-
// playwright
|
|
34
|
-
//
|
|
35
|
-
|
|
32
|
+
// 与 platform_login.mjs 保持一致的解析方式:用裸标识符让 Node 从项目根 node_modules 解析。
|
|
33
|
+
// 用 playwright-core(免浏览器下载的纯 JS API):浏览器走系统 Chrome + CDP,
|
|
34
|
+
// 不需要 playwright 自带浏览器;playwright 作为 optional 依赖安装失败时会被 npm
|
|
35
|
+
// 静默跳过,导致运行时报 Cannot find package(0.83.x 事故)。
|
|
36
|
+
let chromium;
|
|
37
|
+
try {
|
|
38
|
+
({ chromium } = await import('playwright-core'));
|
|
39
|
+
} catch {
|
|
40
|
+
throw new Error(
|
|
41
|
+
'缺少依赖 playwright-core:请在本工程根执行 npm install(cardbuddy 依赖会带上 playwright-core),或手动 npm i playwright-core。',
|
|
42
|
+
);
|
|
43
|
+
}
|
|
36
44
|
|
|
37
45
|
// 统一日志美化(容错:缺 server/core/logger 时回退极简实现,保证 demo / 老项目不崩)。
|
|
38
46
|
// 实时项目与 build 后的 dist/server-core 均含该模块;demo 等缺少 server/ 目录的场景走 fallback。
|
|
@@ -8,22 +8,7 @@
|
|
|
8
8
|
"name": "platform-session-navigator-scripts",
|
|
9
9
|
"version": "1.0.0",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"playwright": "^1.62.1"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"node_modules/playwright": {
|
|
15
|
-
"version": "1.64.1",
|
|
16
|
-
"resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.64.1.tgz",
|
|
17
|
-
"integrity": "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==",
|
|
18
|
-
"license": "Apache-2.0",
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"playwright-core": "1.64.1"
|
|
21
|
-
},
|
|
22
|
-
"bin": {
|
|
23
|
-
"playwright": "cli.js"
|
|
24
|
-
},
|
|
25
|
-
"engines": {
|
|
26
|
-
"node": ">=20"
|
|
11
|
+
"playwright-core": "^1.62.1"
|
|
27
12
|
}
|
|
28
13
|
},
|
|
29
14
|
"node_modules/playwright-core": {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "playwright-core-based 远端自动登录脚本(纯 JS API,浏览器走系统 Chrome + CDP)",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"playwright": "^1.62.1"
|
|
8
|
+
"playwright-core": "^1.62.1"
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
// 依赖只取 playwright 的 JS API(浏览器由本脚本 spawn 系统 Chrome + connectOverCDP 连接,
|
|
2
|
+
// 不需要 playwright 自带浏览器),因此用免下载的 playwright-core:它是 cardbuddy 与工程
|
|
3
|
+
// devDependencies 里的普通依赖,npm install 即落地;不用 playwright(postinstall 下载
|
|
4
|
+
// 数百 MB 浏览器,作为 optionalDependency 安装失败时会被 npm 静默跳过,错误延迟到运行时)。
|
|
5
|
+
let chromium;
|
|
6
|
+
try {
|
|
7
|
+
({ chromium } = await import("playwright-core"));
|
|
8
|
+
} catch {
|
|
9
|
+
throw new Error(
|
|
10
|
+
"缺少依赖 playwright-core:请在本工程根执行 npm install(cardbuddy 依赖会带上 playwright-core),或手动 npm i playwright-core。",
|
|
11
|
+
);
|
|
12
|
+
}
|
|
2
13
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
3
14
|
import { existsSync } from "node:fs";
|
|
4
15
|
import { spawn } from "node:child_process";
|
|
@@ -58,7 +58,7 @@ let _sessionCache = null; // { browser, login, at }
|
|
|
58
58
|
* @param {object} [options]
|
|
59
59
|
* @param {number} [options.debugPort=SYNC_PORT]
|
|
60
60
|
* @param {boolean} [options.headless=true]
|
|
61
|
-
* @returns {Promise<{ browser: import('playwright').Browser, login: object }>}
|
|
61
|
+
* @returns {Promise<{ browser: import('playwright-core').Browser, login: object }>}
|
|
62
62
|
*/
|
|
63
63
|
export async function ensurePlatformSession({ debugPort = SYNC_PORT, headless = true } = {}) {
|
|
64
64
|
// 热路径:进程内缓存未过期且 CDP 仍连通 → 直接复用(跳过 runPlatformLogin 的
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cardbuddy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Local dev service for the CardBuddy card editor — decouples card CRUD (sync/save/validate/render-status/screenshot) from the static public editor, so the editor can be deployed to any static host while each developer runs a local service against their own card source.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,14 +30,12 @@
|
|
|
30
30
|
"codejar": "^4.3.0",
|
|
31
31
|
"connect": "^3.7.0",
|
|
32
32
|
"dotenv": "^18.0.9",
|
|
33
|
+
"playwright-core": "^1.62.1",
|
|
33
34
|
"pngjs": "^7.0.0",
|
|
34
35
|
"prismjs": "^1.30.0",
|
|
35
36
|
"qrcode": "^1.5.4",
|
|
36
37
|
"selfsigned": "^4.0.1",
|
|
37
38
|
"vite": "^8.2.0",
|
|
38
39
|
"vue": "^3.5.40"
|
|
39
|
-
},
|
|
40
|
-
"optionalDependencies": {
|
|
41
|
-
"playwright": "^1.62.1"
|
|
42
40
|
}
|
|
43
41
|
}
|