cardbuddy 0.12.0 → 0.12.1

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.
@@ -272,13 +272,14 @@ const CARD_PATCH_TOOL = {
272
272
  type: 'function',
273
273
  function: {
274
274
  name: 'card_patch',
275
- description: '按 JSON 点路径(数组用数字段)对卡片 schema/data 做最小修改并写回;大卡必用本工具,禁止用 card_write 整包重写。路径必须先用 card_grep 拿真实路径——schema 的节点树是 view.components[].slots[].components[](不是 view.children)。路径中段不存在会直接报错(不再静默新建分支),确要新建传 create:true。仓库根下走 card_write 管线(带历史快照与校验)。',
275
+ description: '按 JSON 点路径(数组用数字段)对卡片 schema/data 做最小修改并写回;大卡必用本工具,禁止用 card_write 整包重写。路径必须先用 card_grep 拿真实路径——schema 的节点树是 view.components[].slots[].components[](不是 view.children)。路径中段不存在会直接报错(不再静默新建分支),确要新建传 create:true。patches(改/增)与 deletes(删)至少给一个,可只删不改(清理无用样式项、多余节点)。仓库根下走 card_write 管线(带历史快照与校验)。',
276
276
  parameters: {
277
277
  type: 'object',
278
278
  properties: {
279
279
  id: { type: 'string', description: '卡片 id' },
280
280
  patches: {
281
281
  type: 'array',
282
+ description: '要写入的 {path,value} 列表;只删除时可省略(此时必须给 deletes)',
282
283
  items: {
283
284
  type: 'object',
284
285
  properties: {
@@ -288,11 +289,11 @@ const CARD_PATCH_TOOL = {
288
289
  required: ['path', 'value'],
289
290
  },
290
291
  },
291
- deletes: { type: 'array', items: { type: 'string' }, description: '要删除的 JSON 点路径' },
292
+ deletes: { type: 'array', items: { type: 'string' }, description: '要删除的 JSON 点路径;可单独使用(只删不改)' },
292
293
  target: { type: 'string', enum: ['schema', 'data'], description: '默认 schema' },
293
294
  create: { type: 'boolean', description: '路径中段不存在时是否新建分支(默认 false = 响亮报错)' },
294
295
  },
295
- required: ['id', 'patches'],
296
+ required: ['id'],
296
297
  },
297
298
  },
298
299
  }
@@ -352,12 +353,38 @@ function applyByPath(doc, p, setter, { create = false } = {}) {
352
353
 
353
354
  async function cardPatch(root, args, dispatch, { allowDispatch = false } = {}) {
354
355
  const { id, patches = [], deletes = [], target = 'schema' } = args || {}
355
- if (!Array.isArray(patches) || !patches.length) throw new Error('缺少 patches')
356
+ if (!Array.isArray(patches)) throw new Error('patches 必须是数组')
357
+ if (!Array.isArray(deletes)) throw new Error('deletes 必须是数组')
358
+ // 「只删不改」是合法操作(清理无用样式项 / 多余节点);真正的错误是两个都空 —— 空补丁什么都不做,
359
+ // 却会照样走一遍 card_write 管线、平白多存一份历史快照,所以在这里响亮拒掉。
360
+ if (!patches.length && !deletes.length) throw new Error('patches 与 deletes 至少给一个(空补丁无意义)')
356
361
  const file = path.join(root, 'src', 'cards', String(id || ''), target === 'data' ? 'data.json' : 'schema.json')
357
362
  const doc = JSON.parse(fs.readFileSync(file, 'utf8'))
358
363
  const create = args.create === true
359
364
  for (const pt of patches) applyByPath(doc, pt.path, (obj, k) => (obj[k] = pt.value), { create })
360
- for (const d of deletes) applyByPath(doc, d, (obj, k) => delete obj[k], { create })
365
+ // 删数组元素必须 splice:早先用 delete obj[k],在数组上只留一个 null 空洞
366
+ // (properties 变成 [null, {...}]),补丁报「成功」却把 schema 写成稀疏数组,渲染与校验随后就崩。
367
+ // 同一父数组里删多项时按原始下标从大到小删 —— splice 会让后面的索引左移,升序删会误删邻居。
368
+ const orderedDeletes = [...deletes].sort((a, b) => {
369
+ const sa = String(a).split('.')
370
+ const sb = String(b).split('.')
371
+ const pa = sa.slice(0, -1).join('.')
372
+ const pb = sb.slice(0, -1).join('.')
373
+ if (pa !== pb) return pa < pb ? -1 : 1
374
+ const na = Number(sa[sa.length - 1])
375
+ const nb = Number(sb[sb.length - 1])
376
+ return Number.isFinite(na) && Number.isFinite(nb) ? nb - na : 0
377
+ })
378
+ for (const d of orderedDeletes)
379
+ applyByPath(
380
+ doc,
381
+ d,
382
+ (obj, k) => {
383
+ if (Array.isArray(obj)) obj.splice(Number(k), 1)
384
+ else delete obj[k]
385
+ },
386
+ { create },
387
+ )
361
388
  // 工程根:走 card_write 管线(历史快照 + validate/render_status);其它根(测试/自定义)直接落盘。
362
389
  // 仓库内运行由「root === 仓库根」判定;cardbuddy 发布态快照根在包内、永不等于工程根,
363
390
  // 故由宿主显式 allowDispatch 开启(它已把 CARD_ROOT 指到同一个工程根,dispatch 落点一致)。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cardbuddy",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
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": {