@sanity/mutate
Version:
Experimental toolkit for working with Sanity mutations in JavaScript & TypeScript
242 lines (241 loc) • 7.35 kB
JavaScript
;
var parse = require("./parse.cjs"), stringify = require("./stringify.cjs");
function isCreateIfNotExistsMutation(sanityMutation) {
return "createIfNotExists" in sanityMutation;
}
function isCreateOrReplaceMutation(sanityMutation) {
return "createOrReplace" in sanityMutation;
}
function isCreateMutation(sanityMutation) {
return "create" in sanityMutation;
}
function isDeleteMutation(sanityMutation) {
return "delete" in sanityMutation;
}
function isPatchMutation(sanityMutation) {
return "patch" in sanityMutation;
}
function isSetPatch(sanityPatch) {
return "set" in sanityPatch;
}
function isSetIfMissingPatch(sanityPatch) {
return "setIfMissing" in sanityPatch;
}
function isDiffMatchPatch(sanityPatch) {
return "diffMatchPatch" in sanityPatch;
}
function isUnsetPatch(sanityPatch) {
return "unset" in sanityPatch;
}
function isIncPatch(sanityPatch) {
return "inc" in sanityPatch;
}
function isDecPatch(sanityPatch) {
return "inc" in sanityPatch;
}
function isInsertPatch(sanityPatch) {
return "insert" in sanityPatch;
}
function decodeAll(sanityMutations) {
return sanityMutations.map(decodeMutation);
}
function decode(encodedMutation) {
return decodeMutation(encodedMutation);
}
function decodeMutation(encodedMutation) {
if (isCreateIfNotExistsMutation(encodedMutation))
return {
type: "createIfNotExists",
document: encodedMutation.createIfNotExists
};
if (isCreateOrReplaceMutation(encodedMutation))
return {
type: "createOrReplace",
document: encodedMutation.createOrReplace
};
if (isCreateMutation(encodedMutation))
return { type: "create", document: encodedMutation.create };
if (isDeleteMutation(encodedMutation))
return { id: encodedMutation.delete.id, type: "delete" };
if (isPatchMutation(encodedMutation))
return {
type: "patch",
id: encodedMutation.patch.id,
patches: decodeNodePatches(encodedMutation.patch)
};
throw new Error(`Unknown mutation: ${JSON.stringify(encodedMutation)}`);
}
const POSITION_KEYS = ["before", "replace", "after"];
function getInsertPosition(insert) {
const positions = POSITION_KEYS.filter((k) => k in insert);
if (positions.length > 1)
throw new Error(
`Insert patch is ambiguous. Should only contain one of: ${POSITION_KEYS.join(
", "
)}, instead found ${positions.join(", ")}`
);
return positions[0];
}
function decodeNodePatches(patch) {
return [
...getSetPatches(patch),
...getSetIfMissingPatches(patch),
...getUnsetPatches(patch),
...getIncPatches(patch),
...getDecPatches(patch),
...getInsertPatches(patch),
...getDiffMatchPatchPatches(patch)
];
}
function getSetPatches(patch) {
return isSetPatch(patch) ? Object.keys(patch.set).map((path) => ({
path: parse.parse(path),
op: { type: "set", value: patch.set[path] }
})) : [];
}
function getSetIfMissingPatches(patch) {
return isSetIfMissingPatch(patch) ? Object.keys(patch.setIfMissing).map((path) => ({
path: parse.parse(path),
op: { type: "setIfMissing", value: patch.setIfMissing[path] }
})) : [];
}
function getDiffMatchPatchPatches(patch) {
return isDiffMatchPatch(patch) ? Object.keys(patch.diffMatchPatch).map((path) => ({
path: parse.parse(path),
op: { type: "diffMatchPatch", value: patch.diffMatchPatch[path] }
})) : [];
}
function getUnsetPatches(patch) {
return isUnsetPatch(patch) ? patch.unset.map((path) => ({
path: parse.parse(path),
op: { type: "unset" }
})) : [];
}
function getIncPatches(patch) {
return isIncPatch(patch) ? Object.keys(patch.inc).map((path) => ({
path: parse.parse(path),
op: { type: "inc", amount: patch.inc[path] }
})) : [];
}
function getDecPatches(patch) {
return isDecPatch(patch) ? Object.keys(patch.dec).map((path) => ({
path: parse.parse(path),
op: { type: "dec", amount: patch.dec[path] }
})) : [];
}
function getInsertPatches(patch) {
if (!isInsertPatch(patch))
return [];
const position = getInsertPosition(patch.insert);
if (!position)
throw new Error("Insert patch missing position");
const path = parse.parse(patch.insert[position]), referenceItem = path.pop(), op = position === "replace" ? {
type: "insert",
position,
referenceItem,
items: patch.insert.items
} : {
type: "insert",
position,
referenceItem,
items: patch.insert.items
};
return [{ path, op }];
}
function encode(mutation) {
return encodeMutation(mutation);
}
function encodeAll(mutations) {
return mutations.flatMap(encode);
}
function encodeTransaction(transaction) {
return {
transactionId: transaction.id,
mutations: encodeAll(transaction.mutations)
};
}
function encodeMutation(mutation) {
if (mutation.type === "create" || mutation.type === "createIfNotExists" || mutation.type === "createOrReplace")
return { [mutation.type]: mutation.document };
if (mutation.type === "delete")
return {
delete: { id: mutation.id }
};
const ifRevisionID = mutation.options?.ifRevision;
return mutation.patches.map((patch) => ({
patch: {
id: mutation.id,
...ifRevisionID && { ifRevisionID },
...patchToSanity(patch)
}
}));
}
function patchToSanity(patch) {
const { path, op } = patch;
if (op.type === "unset")
return { unset: [stringify.stringify(path)] };
if (op.type === "insert")
return {
insert: {
[op.position]: stringify.stringify([...path, op.referenceItem]),
items: op.items
}
};
if (op.type === "diffMatchPatch")
return { diffMatchPatch: { [stringify.stringify(path)]: op.value } };
if (op.type === "inc")
return { inc: { [stringify.stringify(path)]: op.amount } };
if (op.type === "dec")
return { dec: { [stringify.stringify(path)]: op.amount } };
if (op.type === "set" || op.type === "setIfMissing")
return { [op.type]: { [stringify.stringify(path)]: op.value } };
if (op.type === "truncate") {
const range = [
op.startIndex,
typeof op.endIndex == "number" ? op.endIndex : ""
].join(":");
return { unset: [`${stringify.stringify(path)}[${range}]`] };
}
if (op.type === "upsert")
return {
unset: op.items.map(
(item) => stringify.stringify([...path, { _key: item._key }])
),
insert: {
[op.position]: stringify.stringify([...path, op.referenceItem]),
items: op.items
}
};
if (op.type === "assign")
return {
set: Object.fromEntries(
Object.keys(op.value).map((key) => [
stringify.stringify(path.concat(key)),
op.value[key]
])
)
};
if (op.type === "unassign")
return {
unset: op.keys.map((key) => stringify.stringify(path.concat(key)))
};
if (op.type === "replace")
return {
insert: {
replace: stringify.stringify(path.concat(op.referenceItem)),
items: op.items
}
};
if (op.type === "remove")
return {
unset: [stringify.stringify(path.concat(op.referenceItem))]
};
throw new Error(`Unknown operation type ${op.type}`);
}
exports.decode = decode;
exports.decodeAll = decodeAll;
exports.encode = encode;
exports.encodeAll = encodeAll;
exports.encodeMutation = encodeMutation;
exports.encodeTransaction = encodeTransaction;
//# sourceMappingURL=encode.cjs.map