Skip to content

Commit

Permalink
Merge pull request #95 from flotiq/feature/25685-prepare-for-relation…
Browse files Browse the repository at this point in the history
…-validation-in-ctd

Release 2.10.0 prepare importer for relation validation on CTD creation
  • Loading branch information
KrzysztofBrylski authored Feb 19, 2025
2 parents 5ad5e9f + 3e1f9ef commit 28a2dd1
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 65 deletions.
150 changes: 87 additions & 63 deletions commands/importer.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,54 @@ exports.builder = {
description: "Shortcut for --update-definitions --skip-content",
}
}

function hasRelationshipConstraints(contentTypeDefinition) {
return traverse(contentTypeDefinition)
.reduce(function (haveConstraints, node) {
if (this.key === 'minItems') {
if (node > 0) {
haveConstraints = true;
this.update(0)
}
}

if (this.key === 'relationContenttype') {
if (node !== '') {
this.update('');
haveConstraints = true;
}
}

return haveConstraints;
}, false);
}

async function restoreDefinitions(remoteContentTypeDefinitions, brokenConstraints, flotiqApi, pass = '5') {
logger.info(`Pass ${pass} – restore relationships in definitions`)

for (const contentTypeDefinition of traverse.clone(remoteContentTypeDefinitions)) {
if (contentTypeDefinition.internal) {
continue;
}

if (brokenConstraints.includes(contentTypeDefinition.name)) {
logger.info(`Updating ${contentTypeDefinition.name}`)

await flotiqApi.updateContentTypeDefinition(contentTypeDefinition.name, contentTypeDefinition);
}
}
}

function fixRelationsInCTDs(remoteContentTypeDefinitions, CTDs) {
return remoteContentTypeDefinitions.map(rCTD => {
const newCTD = CTDs.find(ctd => ctd.name === rCTD.name);
if (newCTD) {
return newCTD;
}
return rCTD;
});
}

async function importer(directory, flotiqApi, skipDefinitions, skipContent, updateDefinitions, disableWebhooks, fixDefinitions, ctd, skipCtd)
{
if (fixDefinitions) {
Expand Down Expand Up @@ -110,16 +158,18 @@ async function importer(directory, flotiqApi, skipDefinitions, skipContent, upda
}
});

CTDs = CTDs.filter(def => !flatCtdsToSkip.includes(def.name))
CTDs = CTDs.filter(def => !flatCtdsToSkip.includes(def.name));
}

if (
!(skipDefinitions || updateDefinitions) &&
!(await flotiqApi.checkIfClear(CTDs))
) {
process.exit(1)
process.exit(1);
}
let featuredImages = [];

const brokenConstraints = [];
if (skipDefinitions) {
logger.info('Pass 1 – import content type definitions [skipped]')
} else {
Expand All @@ -137,7 +187,7 @@ async function importer(directory, flotiqApi, skipDefinitions, skipContent, upda

logger.info(
`${remoteCtd ? 'Updating' : 'Persisting'} contentTypeDefinition ${contentTypeDefinition.name}`
)
);

featuredImages.push(
{
Expand All @@ -146,71 +196,61 @@ async function importer(directory, flotiqApi, skipDefinitions, skipContent, upda
}
);
contentTypeDefinition.featuredImage = [];
let haveRelationshipConstraints = hasRelationshipConstraints(contentTypeDefinition);
if (haveRelationshipConstraints) {
brokenConstraints.push(contentTypeDefinition.name);
}
const response = await flotiqApi.createOrUpdate(remoteCtd, contentTypeDefinition);

if (response.ok) {
logger.info(
`${remoteCtd ? 'Updated' : 'Persisted'} contentTypeDefinition ${contentTypeDefinition.name} ${(await response.json()).id}`
)
);
} else {
let responseJson = await response.json()
throw new Error(util.format(`${response.statusText}:`, responseJson))
let responseJson = await response.json();
throw new Error(util.format(`${response.statusText}:`, responseJson));
}
}
}
let remoteContentTypeDefinitions;

if (skipContent) {
if(brokenConstraints.length) {
remoteContentTypeDefinitions = await flotiqApi.fetchContentTypeDefs();
remoteContentTypeDefinitions = fixRelationsInCTDs(remoteContentTypeDefinitions, CTDs)
await restoreDefinitions(remoteContentTypeDefinitions, brokenConstraints, flotiqApi, '2');
}
logger.info('All done')
return
}

logger.info('Pass 2 – break relationships in content type definitions')

const breakDefinitions = true;

const remoteContentTypeDefinitions = await flotiqApi.fetchContentTypeDefs();

const brokenConstraints = [];

if (breakDefinitions) {
/**
* We need to clone this right nowe because we will be restoring them at the end.
*/
for (const contentTypeDefinition of traverse.clone(remoteContentTypeDefinitions)) {
if (contentTypeDefinition.internal) {
// logger.info(`Not breaking up internal CTD ${contentTypeDefinition.name}`)
continue;
}
logger.info('Pass 2 – break relationships in content type definitions');

let haveRelationshipConstraints = traverse(contentTypeDefinition)
.reduce(function (haveConstraints, node) {
if (this.key === 'minItems') {
if (node > 0) {
haveConstraints = true;
this.update(0)
}
}
if(!remoteContentTypeDefinitions) {
remoteContentTypeDefinitions = await flotiqApi.fetchContentTypeDefs();
remoteContentTypeDefinitions = fixRelationsInCTDs(remoteContentTypeDefinitions, CTDs)
}

if (this.key === 'relationContenttype') {
if (node !== '') {
this.update('');
haveConstraints = true;
}
}
/**
* We need to clone this right now because we will be restoring them at the end.
*/
for (const contentTypeDefinition of traverse.clone(remoteContentTypeDefinitions)) {
if (contentTypeDefinition.internal) {
continue;
}

return haveConstraints;
}, false)
let haveRelationshipConstraints = hasRelationshipConstraints(contentTypeDefinition);

if (haveRelationshipConstraints) {
logger.info(`Breaking constraints for contentType ${contentTypeDefinition.name}`);
await flotiqApi.updateContentTypeDefinition(contentTypeDefinition.name, contentTypeDefinition);
brokenConstraints.push(contentTypeDefinition.name)
} else {
logger.info(`No constraints to break for contentType ${contentTypeDefinition.name}`);
}
if (haveRelationshipConstraints) {
logger.info(`Breaking constraints for contentType ${contentTypeDefinition.name}`);
await flotiqApi.updateContentTypeDefinition(contentTypeDefinition.name, contentTypeDefinition);
brokenConstraints.push(contentTypeDefinition.name);
} else {
logger.info(`No constraints to break for contentType ${contentTypeDefinition.name}`);
}
}


const ContentObjectFiles = await glob(
`${directory}/**/contentObject*.json`
)
Expand Down Expand Up @@ -330,23 +370,7 @@ async function importer(directory, flotiqApi, skipDefinitions, skipContent, upda
}
}

const restoreDefinitions = true;

if (restoreDefinitions) {
logger.info('Pass 5 – restore relationships in definitions')

for (const contentTypeDefinition of traverse.clone(remoteContentTypeDefinitions)) {
if (contentTypeDefinition.internal) {
continue;
}

if (brokenConstraints.includes(contentTypeDefinition.name)) {
logger.info(`Updating ${contentTypeDefinition.name}`)

await flotiqApi.updateContentTypeDefinition(contentTypeDefinition.name, contentTypeDefinition);
}
}
}
await restoreDefinitions(remoteContentTypeDefinitions, brokenConstraints, flotiqApi);

if (disableWebhooks && existingWebhooks.length > 0) {
// We should restore our webhooks even if we're importing webhooks,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flotiq-cli",
"version": "2.9.1",
"version": "2.10.0",
"description": "Flotiq CLI",
"main": "src/command/command.js",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion src/flotiq-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ module.exports = class FlotiqApi {
await new Promise(resolve => setTimeout(resolve, 1000)); // Retry after 1 second
return this._sendRequest(uri, batch, method); // Retry request
} else {
console.dir(e.response.data.errors, { depth: undefined });
console.dir(e.response?.data?.errors, { depth: undefined });
throw new Error(e.message);
}
}
Expand Down

0 comments on commit 28a2dd1

Please sign in to comment.