@sanity/import
Version:
Import documents to a Sanity dataset
138 lines (137 loc) • 4.66 kB
JavaScript
import pMap from 'p-map';
import { progressStepper } from './util/progressStepper.js';
import { retryOnFailure } from './util/retryOnFailure.js';
import { suffixTag } from './util/suffixTag.js';
const DOCUMENT_IMPORT_CONCURRENCY = 6;
const RELEASE_IMPORT_CONCURRENCY = 3;
export async function importBatches(batches, options) {
const progress = progressStepper(options.onProgress, {
step: 'Importing documents',
total: batches.length
});
const mapOptions = {
concurrency: DOCUMENT_IMPORT_CONCURRENCY
};
const batchResults = await pMap(batches, importBatch.bind(null, options, progress), mapOptions);
const result = {
count: 0,
importedIds: []
};
for (const batchResult of batchResults){
result.count += batchResult.count;
result.importedIds = [
...result.importedIds,
...batchResult.importedIds
];
}
return result;
}
function importBatch(options, progress, batch) {
const { client, operation, releasesOperation, tag } = options;
const maxRetries = operation === 'create' ? 1 : 3;
return retryOnFailure(async ()=>{
const releaseDocs = [];
const docs = [];
for (const doc of batch){
if (doc._id.startsWith('_.releases.')) {
releaseDocs.push(doc);
} else {
docs.push(doc);
}
}
const docsTransaction = docs.length > 0 ? (()=>{
let trx = client.transaction();
for (const doc of docs){
switch(operation){
case 'create':
{
trx = trx.create(doc);
break;
}
case 'createIfNotExists':
{
trx = trx.createIfNotExists(doc);
break;
}
case 'createOrReplace':
{
trx = trx.createOrReplace(doc);
break;
}
default:
{
throw new Error(`Unknown operation: ${operation}`);
}
}
}
return trx;
})().commit({
tag: suffixTag(tag, 'doc.create'),
visibility: 'async'
}).then((res)=>{
progress();
const importedIds = res.results.filter((r)=>r.operation !== 'none').map((r)=>r.id);
return {
count: res.results.length,
importedIds
};
}) : Promise.resolve({
count: 0,
importedIds: []
});
const releaseResults = releaseDocs.length > 0 ? await pMap(releaseDocs, (doc)=>{
const actionParams = {
actionType: 'sanity.action.release.import',
attributes: doc,
ifExists: releasesOperation,
releaseId: doc.name
};
return client.action(actionParams).then(()=>({
count: 1,
importedIds: [
doc._id
]
})).catch((err)=>{
err.message = `Release import failed for ${doc._id}: ${err.message}`;
throw err;
});
}, {
concurrency: RELEASE_IMPORT_CONCURRENCY,
stopOnError: false
}).catch((err)=>{
if (err instanceof AggregateError) {
const permissionError = err.errors.find((e)=>e.response?.statusCode === 403 || e.statusCode === 403);
throw permissionError || err.errors[0];
}
throw err;
}) : [];
const docsResult = await docsTransaction;
const combined = {
count: 0,
importedIds: []
};
for (const r of [
docsResult,
...releaseResults
]){
combined.count += r.count;
combined.importedIds = [
...combined.importedIds,
...r.importedIds
];
}
return combined;
}, {
isRetriable,
maxTries: maxRetries
});
}
function isRetriable(err) {
const statusCode = err.response?.statusCode ?? err.statusCode;
// 409 Conflict and 403 Forbidden are not retriable
if (statusCode === 409 || statusCode === 403) {
return false;
}
return true;
}
//# sourceMappingURL=importBatches.js.map