Skip to content

Commit f17eaf5

Browse files
committed
fix(playground): support root json patch replace
1 parent 02abcfe commit f17eaf5

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

sites/playground/web/src/components/genui-template/template-chat-utils/json-patch-format.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ function toStandardPatchOp(item: IFormattedJsonPatchOperation): JsonPatchOp {
2424
return standardOp as JsonPatchOp;
2525
}
2626

27+
function replaceObjectRoot(target: Record<string, unknown>, value: unknown): void {
28+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
29+
throw new Error('root replace value must be an object');
30+
}
31+
32+
Object.keys(target).forEach((key) => {
33+
delete target[key];
34+
});
35+
Object.assign(target, clonePlainJson(value as Record<string, unknown>));
36+
}
37+
38+
function applyStandardPatchOp(target: Record<string, unknown>, operation: JsonPatchOp): void {
39+
if (operation.op === 'replace' && operation.path === '') {
40+
replaceObjectRoot(target, operation.value);
41+
return;
42+
}
43+
44+
jsonPatchFormatter.patch(target, [operation]);
45+
}
46+
2747
export function clonePlainJson<T>(value: T | null | undefined): T | null {
2848
if (value === undefined || value === null) {
2949
return null;
@@ -71,7 +91,7 @@ function resolvePositionedOp(
7191
}
7292

7393
function finalizeAbsolutePath(templeSchema: any, item: IFormattedJsonPatchOperation): boolean {
74-
if (typeof item.path !== 'string' || !item.path.startsWith('/')) {
94+
if (typeof item.path !== 'string' || (item.path !== '' && !item.path.startsWith('/'))) {
7595
return false;
7696
}
7797
try {
@@ -133,6 +153,8 @@ export const formatJsonPatch = (
133153
} else if (item.path) {
134154
item.relativePath = item.path;
135155
item.path = componentPath === '/' ? item.path : `${componentPath}${item.path}`;
156+
} else if (item.op === 'replace' && componentPath === '/') {
157+
item.path = '';
136158
} else {
137159
item.path = componentPath;
138160
}
@@ -142,7 +164,7 @@ export const formatJsonPatch = (
142164
return item;
143165
}
144166

145-
jsonPatchFormatter.patch(templeSchema, [toStandardPatchOp(item)]);
167+
applyStandardPatchOp(templeSchema, toStandardPatchOp(item));
146168
if (!regenerateCopiedNodeIds(templeSchema, item)) {
147169
item.idToPath = null;
148170
}
@@ -170,7 +192,7 @@ export function applyJsonPatchOperations(
170192
if (!target) {
171193
return null;
172194
}
173-
jsonPatchFormatter.patch(target, standardOperations);
195+
standardOperations.forEach((operation) => applyStandardPatchOp(target, operation));
174196
if (standardOperations.some((op) => op.op === 'copy')) {
175197
generateIdForComponents(target);
176198
}

0 commit comments

Comments
 (0)