@sanity/import
Version:
Import documents to a Sanity dataset
112 lines (111 loc) • 3.98 kB
JavaScript
import { extractWithPath } from '@sanity/mutator';
import debug from 'debug';
import pMap from 'p-map';
import { serializePath } from './serializePath.js';
import { deepGet } from './util/deepGet.js';
import { progressStepper } from './util/progressStepper.js';
import { retryOnFailure } from './util/retryOnFailure.js';
import { suffixTag } from './util/suffixTag.js';
const logger = debug('sanity:import');
const STRENGTHEN_CONCURRENCY = 30;
const STRENGTHEN_BATCH_SIZE = 30;
export function getStrongRefs(doc) {
const refs = findStrongRefs(doc).map((item)=>serializePath(item));
if (refs.length > 0) {
return {
documentId: doc._id,
references: refs
};
}
return null;
}
// Note: mutates in-place
export function weakenStrongRefs(doc) {
const refs = findStrongRefs(doc);
for (const item of refs){
item.ref._weak = true;
}
return doc;
}
// Note: mutates in-place
export function cleanupReferences(doc, options) {
const { skipCrossDatasetReferences, targetProjectId } = options;
const refPathItems = extractWithPath('..[_ref]', doc).map((match)=>match.path.slice(0, -1)).map((path)=>({
path,
ref: deepGet(doc, path)
}));
for (const item of refPathItems){
// We may want to skip cross-dataset references, eg when importing to other projects
if (skipCrossDatasetReferences && '_dataset' in item.ref) {
const leaf = item.path.at(-1);
const parent = item.path.length > 1 ? deepGet(doc, item.path.slice(0, -1)) : doc;
if (typeof leaf === 'string' || typeof leaf === 'number') {
delete parent[leaf];
}
continue;
}
// Apply missing _type on references
if (item.ref._type === undefined) {
;
item.ref._type = 'reference';
}
// Ensure cross-dataset references point to the same project ID as being imported to
const refWithProjectId = item.ref;
if (refWithProjectId._projectId !== undefined) {
refWithProjectId._projectId = targetProjectId;
}
}
return doc;
}
function findStrongRefs(doc) {
return extractWithPath('..[_ref]', doc).map((match)=>match.path.slice(0, -1)).map((path)=>({
path,
ref: deepGet(doc, path)
})).filter((item)=>item.ref._weak !== true);
}
export function strengthenReferences(strongRefs, options) {
const { client, tag } = options;
const batches = [];
for(let i = 0; i < strongRefs.length; i += STRENGTHEN_BATCH_SIZE){
batches.push(strongRefs.slice(i, i + STRENGTHEN_BATCH_SIZE));
}
if (batches.length === 0) {
return Promise.resolve([
0
]);
}
const progress = progressStepper(options.onProgress, {
step: 'Strengthening references',
total: batches.length
});
const mapOptions = {
concurrency: STRENGTHEN_CONCURRENCY
};
return pMap(batches, unsetWeakBatch.bind(null, client, progress, tag), mapOptions);
}
function unsetWeakBatch(client, progress, tag, batch) {
logger('Strengthening batch of %d documents', batch.length);
return retryOnFailure(()=>{
let trx = client.transaction();
for (const task of batch){
trx = reducePatch(trx, task);
}
return trx.commit({
tag: suffixTag(tag, 'ref.strengthen'),
visibility: 'async'
}).then((res)=>{
progress();
return res.results.length;
}).catch((err)=>{
const apiError = err;
apiError.step = 'strengthen-references';
throw apiError;
});
}, {
isRetriable: (err)=>!err.statusCode || err.statusCode !== 409
});
}
function reducePatch(trx, task) {
return trx.patch(task.documentId, (patch)=>patch.unset(task.references.map((path)=>`${path}._weak`)));
}
//# sourceMappingURL=references.js.map