@@ -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+
2747export 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
7393function 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