From 35af2e2fc092cc9c9ac8855d97bd4c54fc6344f0 Mon Sep 17 00:00:00 2001 From: CiotkaCierpienia Date: Thu, 13 Feb 2025 16:45:54 +0100 Subject: [PATCH 1/2] prepare importer for relation validation on CTD creation --- commands/importer.js | 138 +++++++++++++++++++++++-------------------- package.json | 2 +- src/flotiq-api.js | 2 +- 3 files changed, 77 insertions(+), 65 deletions(-) diff --git a/commands/importer.js b/commands/importer.js index fb4a02e..8d76873 100644 --- a/commands/importer.js +++ b/commands/importer.js @@ -56,6 +56,44 @@ 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); + } + } +} + async function importer(directory, flotiqApi, skipDefinitions, skipContent, updateDefinitions, disableWebhooks, fixDefinitions, ctd, skipCtd) { if (fixDefinitions) { @@ -110,16 +148,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 { @@ -137,7 +177,7 @@ async function importer(directory, flotiqApi, skipDefinitions, skipContent, upda logger.info( `${remoteCtd ? 'Updating' : 'Persisting'} contentTypeDefinition ${contentTypeDefinition.name}` - ) + ); featuredImages.push( { @@ -146,71 +186,59 @@ 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(); + await restoreDefinitions(remoteContentTypeDefinitions, brokenConstraints, flotiqApi, '2'); + } logger.info('All done') return } - logger.info('Pass 2 – break relationships in content type definitions') - - const breakDefinitions = true; + logger.info('Pass 2 – break relationships in content type definitions'); - 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; - } - - 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(); + } - 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` ) @@ -330,23 +358,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, diff --git a/package.json b/package.json index bb735ff..52d5439 100644 --- a/package.json +++ b/package.json @@ -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, diff --git a/src/flotiq-api.js b/src/flotiq-api.js index 887e4af..4ad3fb9 100644 --- a/src/flotiq-api.js +++ b/src/flotiq-api.js @@ -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); } } From 3e1f9effa392b3a79883518ca6c966ff5b7ce00a Mon Sep 17 00:00:00 2001 From: CiotkaCierpienia Date: Wed, 19 Feb 2025 09:23:34 +0100 Subject: [PATCH 2/2] prepare importer for relation validation on CTD creation --- commands/importer.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/commands/importer.js b/commands/importer.js index 8d76873..c1a4414 100644 --- a/commands/importer.js +++ b/commands/importer.js @@ -94,6 +94,16 @@ async function restoreDefinitions(remoteContentTypeDefinitions, brokenConstraint } } +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) { @@ -207,6 +217,7 @@ async function importer(directory, flotiqApi, skipDefinitions, skipContent, upda if (skipContent) { if(brokenConstraints.length) { remoteContentTypeDefinitions = await flotiqApi.fetchContentTypeDefs(); + remoteContentTypeDefinitions = fixRelationsInCTDs(remoteContentTypeDefinitions, CTDs) await restoreDefinitions(remoteContentTypeDefinitions, brokenConstraints, flotiqApi, '2'); } logger.info('All done') @@ -217,6 +228,7 @@ async function importer(directory, flotiqApi, skipDefinitions, skipContent, upda if(!remoteContentTypeDefinitions) { remoteContentTypeDefinitions = await flotiqApi.fetchContentTypeDefs(); + remoteContentTypeDefinitions = fixRelationsInCTDs(remoteContentTypeDefinitions, CTDs) } /**