-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add converter for form patches to mutate patches (#44)
- Loading branch information
Showing
5 changed files
with
228 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import {expectTypeOf, test} from 'vitest' | ||
|
||
import {type Path} from '../../path' | ||
import {type CompatPath} from './form-patch-types' | ||
|
||
test('compat paths', () => { | ||
expectTypeOf<Path>().toMatchTypeOf<CompatPath | Readonly<CompatPath>>() | ||
expectTypeOf<CompatPath>().toMatchTypeOf<Path>() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import {at} from '../../mutations/creators' | ||
import { | ||
diffMatchPatch, | ||
insert, | ||
set, | ||
setIfMissing, | ||
unset, | ||
} from '../../mutations/operations/creators' | ||
import {type NodePatch} from '../../mutations/types' | ||
import {type KeyedPathElement} from '../../path' | ||
import { | ||
type CompatPath, | ||
type FormPatchLike, | ||
type FormPatchPath, | ||
} from './form-patch-types' | ||
|
||
function assertCompatible(formPatchPath: FormPatchPath): CompatPath { | ||
if (formPatchPath.length === 0) { | ||
return formPatchPath as never[] | ||
} | ||
for (const element of formPatchPath) { | ||
if (Array.isArray(element)) { | ||
throw new Error('Form patch paths cannot include arrays') | ||
} | ||
} | ||
return formPatchPath as CompatPath | ||
} | ||
|
||
/** | ||
* Convert a Sanity form patch (ie emitted from an input component) to a {@link NodePatch} | ||
* Note the lack of encodeMutation here. Sanity forms never emit *mutations*, only patches | ||
* @param patches - Array of {@link FormPatchLike} | ||
* @internal | ||
*/ | ||
export function encodePatches(patches: FormPatchLike[]): NodePatch[] { | ||
return patches.map(formPatch => { | ||
const path = assertCompatible(formPatch.path) | ||
if (formPatch.type === 'unset') { | ||
return at(path, unset()) | ||
} | ||
if (formPatch.type === 'set') { | ||
return at(path, set(formPatch.value)) | ||
} | ||
if (formPatch.type === 'setIfMissing') { | ||
return at(path, setIfMissing(formPatch.value)) | ||
} | ||
if (formPatch.type === 'insert') { | ||
const arrayPath = path.slice(0, -1) | ||
const itemRef = formPatch.path[formPatch.path.length - 1] | ||
return at( | ||
arrayPath, | ||
insert( | ||
formPatch.items, | ||
formPatch.position, | ||
itemRef as number | KeyedPathElement, | ||
), | ||
) | ||
} | ||
if (formPatch.type === 'diffMatchPatch') { | ||
return at(path, diffMatchPatch(formPatch.value)) | ||
} | ||
// @ts-expect-error - should be exhaustive | ||
throw new Error(`Unknown patch type ${formPatch.type}`) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/** | ||
* Inlined from the 'sanity' package | ||
*/ | ||
import {type ElementType} from '../../path' | ||
|
||
/** | ||
* @deprecated | ||
*/ | ||
export type FormPatchPathKeyedSegment = {_key: string} | ||
/** | ||
* @deprecated | ||
*/ | ||
export type FormPatchPathIndexTuple = [number | '', number | ''] | ||
|
||
/** | ||
* @deprecated | ||
*/ | ||
export type FormPatchPathSegment = | ||
| string | ||
| number | ||
| FormPatchPathKeyedSegment | ||
| FormPatchPathIndexTuple | ||
|
||
/** | ||
* @deprecated | ||
*/ | ||
export type FormPatchPath = FormPatchPathSegment[] | ||
|
||
/** | ||
* A variant of the FormPath type that never contains index tupes | ||
*/ | ||
export type CompatPath = Exclude< | ||
ElementType<FormPatchPath>, | ||
FormPatchPathIndexTuple | ||
>[] | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export type FormPatchJSONValue = | ||
| number | ||
| string | ||
| boolean | ||
| {[key: string]: FormPatchJSONValue} | ||
| FormPatchJSONValue[] | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export type FormPatchOrigin = 'remote' | 'local' | 'internal' | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export interface FormSetPatch { | ||
path: FormPatchPath | ||
type: 'set' | ||
value: FormPatchJSONValue | ||
} | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export interface FormIncPatch { | ||
path: FormPatchPath | ||
type: 'inc' | ||
value: FormPatchJSONValue | ||
} | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export interface FormDecPatch { | ||
path: FormPatchPath | ||
type: 'dec' | ||
value: FormPatchJSONValue | ||
} | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export interface FormSetIfMissingPatch { | ||
path: FormPatchPath | ||
type: 'setIfMissing' | ||
value: FormPatchJSONValue | ||
} | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export interface FormUnsetPatch { | ||
path: FormPatchPath | ||
type: 'unset' | ||
} | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export type FormInsertPatchPosition = 'before' | 'after' | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export interface FormInsertPatch { | ||
path: FormPatchPath | ||
type: 'insert' | ||
position: FormInsertPatchPosition | ||
items: FormPatchJSONValue[] | ||
} | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export interface FormDiffMatchPatch { | ||
path: FormPatchPath | ||
type: 'diffMatchPatch' | ||
value: string | ||
} | ||
|
||
/** | ||
* | ||
* @internal | ||
* @deprecated | ||
*/ | ||
export type FormPatchLike = | ||
| FormSetPatch | ||
| FormSetIfMissingPatch | ||
| FormUnsetPatch | ||
| FormInsertPatch | ||
| FormDiffMatchPatch |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export {encodePatches} from './encode' | ||
export * from './form-patch-types' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters