UNPKG

@sanity/import

Version:

Import documents to a Sanity dataset

120 lines (100 loc) 3.49 kB
const {extractWithPath} = require('@sanity/mutator') const debug = require('debug')('sanity:import') const {get} = require('lodash') const pMap = require('p-map') const serializePath = require('./serializePath') const progressStepper = require('./util/progressStepper') const retryOnFailure = require('./util/retryOnFailure') const suffixTag = require('./util/suffixTag') const STRENGTHEN_CONCURRENCY = 30 const STRENGTHEN_BATCH_SIZE = 30 function getStrongRefs(doc) { const refs = findStrongRefs(doc).map(serializePath) if (refs.length) { return { documentId: doc._id, references: refs, } } return null } // Note: mutates in-place function weakenStrongRefs(doc) { const refs = findStrongRefs(doc) refs.forEach((item) => { item.ref._weak = true }) return doc } // Note: mutates in-place function cleanupReferences(doc, options) { const {targetProjectId, skipCrossDatasetReferences} = options extractWithPath('..[_ref]', doc) .map((match) => match.path.slice(0, -1)) .map((path) => ({path, ref: get(doc, path)})) .forEach((item) => { // We may want to skip cross-dataset references, eg when importing to other projects if (skipCrossDatasetReferences && '_dataset' in item.ref) { const leaf = item.path[item.path.length - 1] const parent = item.path.length > 1 ? get(doc, item.path.slice(0, -1)) : doc delete parent[leaf] return } // Apply missing _type on references if (typeof item.ref._type === 'undefined') { item.ref._type = 'reference' } // Ensure cross-dataset references point to the same project ID as being imported to if (typeof item.ref._projectId !== 'undefined') { item.ref._projectId = targetProjectId } }) return doc } function findStrongRefs(doc) { return extractWithPath('..[_ref]', doc) .map((match) => match.path.slice(0, -1)) .map((path) => ({path, ref: get(doc, path)})) .filter((item) => item.ref._weak !== true) } 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) { debug('Strengthening batch of %d documents', batch.length) return retryOnFailure( () => batch .reduce(reducePatch, client.transaction()) .commit({visibility: 'async', tag: suffixTag(tag, 'ref.strengthen')}) .then(progress) .then((res) => res.results.length) .catch((err) => { err.step = 'strengthen-references' throw err }), {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`)), ) } exports.getStrongRefs = getStrongRefs exports.weakenStrongRefs = weakenStrongRefs exports.cleanupReferences = cleanupReferences exports.strengthenReferences = strengthenReferences