@strapi/data-transfer
Version:
Data transfer capabilities for Strapi
79 lines (76 loc) • 3.58 kB
JavaScript
import { Writable } from 'stream';
import { ProviderTransferError } from '../../../../../errors/providers.mjs';
import { createLinkQuery } from '../../../../queries/link.mjs';
import { resolveLinkRef } from './resolve-link-ref.mjs';
const isErrorWithCode = (error)=>{
return error && typeof error.code === 'string';
};
const isForeignKeyConstraintError = (e)=>{
const MYSQL_FK_ERROR_CODES = [
'1452',
'1557',
'1216',
'1217',
'1451'
];
const POSTGRES_FK_ERROR_CODE = '23503';
const SQLITE_FK_ERROR_CODE = 'SQLITE_CONSTRAINT_FOREIGNKEY';
if (isErrorWithCode(e) && e.code) {
return [
SQLITE_FK_ERROR_CODE,
POSTGRES_FK_ERROR_CODE,
...MYSQL_FK_ERROR_CODES
].includes(e.code);
}
return e.message.toLowerCase().includes('foreign key constraint');
};
const createLinksWriteStream = (mapID, strapi, transaction, onWarning)=>{
return new Writable({
objectMode: true,
async write (link, _encoding, callback) {
await transaction?.attach(async (trx)=>{
const { left, right } = link;
const query = createLinkQuery(strapi, trx);
const originalLeftRef = left.ref;
const originalRightRef = right.ref;
const mappedLeftRef = resolveLinkRef(strapi, link, 'left', mapID);
const mappedRightRef = resolveLinkRef(strapi, link, 'right', mapID);
// A missing mapping means the referenced row was never transferred
// during the entities stage (e.g. an orphaned component or a dangling
// reference in the source database). Falling back to the original ID
// would either violate a foreign key constraint — which aborts the
// whole transaction on PostgreSQL — or silently attach the link to an
// unrelated row, so the link is skipped instead.
if (mappedLeftRef === undefined || mappedRightRef === undefined) {
const missingRefs = [
...mappedLeftRef === undefined ? [
`${left.type}:${originalLeftRef}`
] : [],
...mappedRightRef === undefined ? [
`${right.type}:${originalRightRef}`
] : []
].join(' and ');
onWarning?.(`Skipping link ${left.type}:${originalLeftRef} -> ${right.type}:${originalRightRef} because ${missingRefs} was not transferred during the entities stage.`);
return callback(null);
}
left.ref = mappedLeftRef;
right.ref = mappedRightRef;
try {
await query().insert(link);
} catch (e) {
if (e instanceof Error) {
if (isForeignKeyConstraintError(e)) {
onWarning?.(`Skipping link ${left.type}:${originalLeftRef} -> ${right.type}:${originalRightRef} due to a foreign key constraint.`);
return callback(null);
}
return callback(e);
}
return callback(new ProviderTransferError(`An error happened while trying to import a ${left.type} link.`));
}
callback(null);
});
}
});
};
export { createLinksWriteStream };
//# sourceMappingURL=links.mjs.map