Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/function/update_variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ function extractJsonPatch(patch: any): Command[] {
const pathParts = _.toPath(path);
const lastPart = pathParts[pathParts.length - 1];
const containerPath = pathParts.slice(0, -1).join('.');
// 保留 JSON Patch 的 "-" 特殊 token,交给执行阶段结合目标集合类型解释。
const keyOrIndexArg = /^\d+$/.test(lastPart) ? lastPart : `'${lastPart}'`;
translated_commands.push({
type: 'insert',
Expand Down Expand Up @@ -978,16 +979,23 @@ export async function updateVariables(
? targetSchema.template
: undefined;

if (Array.isArray(collection) && typeof keyOrIndex === 'number') {
if (
Array.isArray(collection) &&
(typeof keyOrIndex === 'number' || keyOrIndex === '-')
) {
// 目标是数组且索引是数字,插入到指定位置
// JSON Patch 中的 "-" 表示追加到数组末尾,而不是字面量键名。
const insertIndex = keyOrIndex === '-' ? collection.length : keyOrIndex;
const positionLabel =
keyOrIndex === '-' || keyOrIndex === -1 ? 'tail' : keyOrIndex;
valueToAssign = applyTemplate(
valueToAssign,
template,
strict_template,
concat_template_array
);
collection.splice(keyOrIndex, 0, valueToAssign);
display_str = `ASSIGNED ${JSON.stringify(valueToAssign)} into '${path}' at index ${keyOrIndex} ${reason_str}`;
collection.splice(insertIndex, 0, valueToAssign);
display_str = `ASSIGNED ${JSON.stringify(valueToAssign)} into '${path}' at index ${positionLabel} ${reason_str}`;
successful = true;
} else if (_.isObject(collection)) {
// 目标是对象,设置指定键
Expand Down
29 changes: 28 additions & 1 deletion tests/json_patch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ describe('JSON Patch fixtures', () => {
const statData = _.cloneDeep(testCase.doc);
const schema = generateSchema(_.cloneDeep(testCase.doc));
relaxSchema(schema);
if (_label.includes('16')) return; //对于 A16. 场景,不支持符号 - 的特殊含义

const variables: MvuData = {
stat_data: statData,
Expand Down Expand Up @@ -133,4 +132,32 @@ describe('执行测试', () => {

expect(variables.stat_data).toEqual({ 测试: 20 });
});

test('json patch insert with /- appends to array tail', async () => {
const statData = {
主角: {
持有物品: [{ name: '木钥匙' }, { name: '银钥匙' }],
},
};
const schema = generateSchema(_.cloneDeep(statData));
relaxSchema(schema);

const variables: MvuData = {
stat_data: statData,
display_data: {},
delta_data: {},
schema: schema as any,
};

const message =
'<JsonPatch>[{"op":"insert","path":"/主角/持有物品/-","value":{"name":"铜钥匙","description":"古铜色小钥匙"}}]</JsonPatch>';

await updateVariables(message, variables);

expect(variables.stat_data.主角.持有物品).toEqual([
{ name: '木钥匙' },
{ name: '银钥匙' },
{ name: '铜钥匙', description: '古铜色小钥匙' },
]);
});
});
Loading