Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion forward_engineering/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,19 @@ const {
} = require('../shared/enums/dynamicMessages');
const { HTTP_ERROR_CODES } = require('../shared/enums/httpCodes');
const { applyScript, logApplyScriptAttempt } = require('./services/applyToInstanceService');
const { hasDropStatements } = require('./services/alterScriptBuilder');
const { generateContainerScript } = require('./generateContainerScript');
const { generateScript } = require('./generateScript');

/**
* @param {ConnectionInfo} connectionInfo
* @param {AppLogger} _logger
* @param {Callback} callback
*/
const isDropInStatements = (connectionInfo, _logger, callback) => {
callback(null, hasDropStatements({ connectionInfo }));
};

/**
* @param {ConnectionInfo} connectionInfo
* @param {AppLogger} appLogger
Expand Down Expand Up @@ -106,7 +116,7 @@ const applyToInstance = async (connectionInfo, appLogger, callback, app) => {

/**
* @param {ConnectionInfo} connectionInfo
* @param {AppLogger} logger
* @param {AppLogger} appLogger
* @param {Callback} callback
* @param {App} app
*/
Expand All @@ -131,6 +141,7 @@ const testConnection = async (connectionInfo, appLogger, callback, app) => {
module.exports = {
generateContainerScript,
generateScript,
isDropInStatements,
applyToInstance,
testConnection,
};
14 changes: 13 additions & 1 deletion forward_engineering/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,24 @@
"container": true,
"entity": true
},
"compMode": {
"container": true,
"entity": true
},
"additionalOptions": [
{
"id": "INCLUDE_SAMPLES",
"value": true,
"name": "Include sample data",
"align": "right"
"align": "right",
"hideInDeltaModel": true
},
{
"id": "applyDropStatements",
"value": false,
"forUpdate": true,
"name": "Apply Drop Statements",
"isDropInStatements": true
}
],
"numberOfDocumentsOptions": {
Expand Down
16 changes: 12 additions & 4 deletions forward_engineering/generateContainerScript.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
const { get } = require('lodash');
const logHelper = require('../shared/helpers/logHelper');
const ForwardEngineeringScriptBuilder = require('./services/forwardEngineeringScriptBuilder');
const { buildAlterScript } = require('./services/alterScriptBuilder');
const { GENERATING_CONTAINER_SCRIPT } = require('../shared/enums/staticMessages');
const { includeSamples } = require('./utils/includeSamples');

/**
* @param {ConnectionInfo} connectionInfo
* @param {AppLogger} appLogger
* @param {Callback} callback
* @param {App} app
* @param {App} _app
*/
const generateContainerScript = async (connectionInfo, appLogger, callback, app) => {
const generateContainerScript = async (connectionInfo, appLogger, callback, _app) => {
const logger = logHelper.createLogger({
title: GENERATING_CONTAINER_SCRIPT,
hiddenKeys: connectionInfo.hiddenKeys,
logger: appLogger,
});

try {
if (connectionInfo.isUpdateScript) {
return callback(null, buildAlterScript({ connectionInfo }));
}

const scriptBuilder = new ForwardEngineeringScriptBuilder();

const { jsonData, collections, options } = connectionInfo;
Expand All @@ -27,12 +32,15 @@ const generateContainerScript = async (connectionInfo, appLogger, callback, app)
...rawScope,
bucketName: rawScope?.bucket ?? '',
};
const collectionsData = collections.map(schema => ({

const getCollectionData = ({ schema, scope }) => ({
...JSON.parse(schema),
namespace: scope?.namespace,
bucketName: scope?.bucketName,
scopeName: scope?.name,
}));
});

const collectionsData = collections.map(schema => getCollectionData({ schema, scope }));

scriptBuilder.addScopeScript(scope);
collectionsData.forEach(collection => scriptBuilder.addCollectionScripts(collection));
Expand Down
9 changes: 7 additions & 2 deletions forward_engineering/generateScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@ const { get } = require('lodash');
const logHelper = require('../shared/helpers/logHelper');
const { GENERATING_ENTITY_SCRIPT } = require('../shared/enums/staticMessages');
const ForwardEngineeringScriptBuilder = require('./services/forwardEngineeringScriptBuilder');
const { buildAlterScript } = require('./services/alterScriptBuilder');
const { includeSamples } = require('./utils/includeSamples');

/**
* @param {ConnectionInfo} connectionInfo
* @param {AppLogger} appLogger
* @param {Callback} callback
* @param {App} app
* @param {App} _app
*/
const generateScript = async (connectionInfo, appLogger, callback, app) => {
const generateScript = async (connectionInfo, appLogger, callback, _app) => {
const logger = logHelper.createLogger({
title: GENERATING_ENTITY_SCRIPT,
hiddenKeys: connectionInfo.hiddenKeys,
logger: appLogger,
});

try {
if (connectionInfo.isUpdateScript) {
return callback(null, buildAlterScript({ connectionInfo }));
}

const scriptBuilder = new ForwardEngineeringScriptBuilder();

const { jsonData, jsonSchema, containerData, options } = connectionInfo;
Expand Down
44 changes: 44 additions & 0 deletions forward_engineering/services/alterScript/AlterScriptDto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @param {{
* script: string,
* isDropScript?: boolean,
* isActivated?: boolean,
* modelLevel?: 'collection' | 'index' | 'scope',
* scriptPurpose?: 'deletion' | 'add' | 'modify',
* }} params
* @returns {{
* script: string,
* isDropScript: boolean,
* isActivated: boolean,
* modelLevel: 'collection' | 'index' | 'scope',
* scriptPurpose: 'deletion' | 'add' | 'modify',
* } | undefined}
*/
const getAlterScriptDto = ({
script,
isDropScript = false,
isActivated = true,
modelLevel = 'collection',
scriptPurpose = 'add',
} = {}) => {
const cleanScript = script?.trim();
if (!cleanScript) {
return;
}

return {
script: cleanScript,
isDropScript,
isActivated,
modelLevel,
scriptPurpose,
};
};

const AlterScriptDto = {
getInstance: getAlterScriptDto,
};

module.exports = {
AlterScriptDto,
};
156 changes: 156 additions & 0 deletions forward_engineering/services/alterScript/collectionAlterHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
const { getCollectionScript, getDropCollectionScript } = require('../statements/collectionsStatements');
const { AlterScriptDto } = require('./AlterScriptDto');
const { getDeltaItems } = require('./deltaSchemaHelper');

/**
* @param {{ entity: object }} params
* @returns {object}
*/
const getCompMod = ({ entity = {} } = {}) => entity.role?.compMod || entity.compMod || {};

/**
* @param {{ entity: object }} params
* @returns {object}
*/
const getEntityRole = ({ entity = {} } = {}) => entity.role || entity;

/**
* @param {{ entity: object, nameType?: 'old' | 'new' | 'current' }} params
* @returns {string}
*/
const getCollectionName = ({ entity = {}, nameType = 'current' } = {}) => {
const role = getEntityRole({ entity });
const compMod = getCompMod({ entity });

if (nameType === 'old') {
return compMod.code?.old || compMod.collectionName?.old || role.code || role.collectionName || '';
}

if (nameType === 'new') {
return compMod.code?.new || compMod.collectionName?.new || role.code || role.collectionName || '';
}

return role.code || role.collectionName || entity.title || role.name || '';
};

/**
* @param {{ entity: object }} params
* @returns {{ namespace: string, bucketName: string, scopeName: string, ifNotExists: boolean }}
*/
const getCollectionContext = ({ entity = {} } = {}) => {
const role = getEntityRole({ entity });
const compMod = getCompMod({ entity });
const bucketProperties = compMod.bucketProperties || {};

return {
namespace: bucketProperties.namespace,
bucketName: bucketProperties.bucket,
scopeName: compMod.keyspaceName || bucketProperties.code || bucketProperties.name,
ifNotExists: Boolean(role.ifNotExists),
};
};

/**
* @param {{ entity: object, collectionName: string }} params
* @returns {AlterScriptDto | undefined}
*/
const getCreateCollectionDto = ({ entity, collectionName } = {}) => {
const context = getCollectionContext({ entity });
const script = getCollectionScript({
...context,
collectionName,
});

return AlterScriptDto.getInstance({ script, isDropScript: false, modelLevel: 'collection', scriptPurpose: 'add' });
};

/**
* @param {{ entity: object, collectionName: string }} params
* @returns {AlterScriptDto | undefined}
*/
const getDropCollectionDto = ({ entity, collectionName } = {}) => {
const context = getCollectionContext({ entity });
const script = getDropCollectionScript({
...context,
collectionName,
ifExists: true,
});

return AlterScriptDto.getInstance({
script,
isDropScript: true,
modelLevel: 'collection',
scriptPurpose: 'deletion',
});
};

/**
* @param {{ entity: object }} params
* @returns {boolean}
*/
const isCollectionRenamed = ({ entity } = {}) => {
const compMod = getCompMod({ entity });
const oldName = compMod.code?.old || compMod.collectionName?.old;
const newName = compMod.code?.new || compMod.collectionName?.new;

return Boolean(oldName && newName && oldName !== newName);
};

/**
* @param {{ entity: object }} params
* @returns {AlterScriptDto[]}
*/
const getAddedCollectionDtos = ({ entity } = {}) => {
const collectionName = getCollectionName({ entity, nameType: 'new' }) || getCollectionName({ entity });
return [getCreateCollectionDto({ entity, collectionName })].filter(Boolean);
};

/**
* @param {{ entity: object }} params
* @returns {AlterScriptDto[]}
*/
const getDeletedCollectionDtos = ({ entity } = {}) => {
const collectionName = getCollectionName({ entity, nameType: 'old' }) || getCollectionName({ entity });
return [getDropCollectionDto({ entity, collectionName })].filter(Boolean);
};

/**
* @param {{ entity: object }} params
* @returns {AlterScriptDto[]}
*/
const getModifiedCollectionDtos = ({ entity } = {}) => {
if (!isCollectionRenamed({ entity })) {
return [];
}

const oldName = getCollectionName({ entity, nameType: 'old' });
const newName = getCollectionName({ entity, nameType: 'new' });

return [
getDropCollectionDto({ entity, collectionName: oldName }),
getCreateCollectionDto({ entity, collectionName: newName }),
].filter(Boolean);
};

/**
* @param {{ schema: object }} params
* @returns {AlterScriptDto[]}
*/
const getCollectionAlterScriptDtos = ({ schema } = {}) => {
const addedEntities = getDeltaItems({ schema, nameProperty: 'entities', modify: 'added' });
const modifiedEntities = getDeltaItems({ schema, nameProperty: 'entities', modify: 'modified' });
const deletedEntities = getDeltaItems({ schema, nameProperty: 'entities', modify: 'deleted' });

const addedDtos = addedEntities.flatMap(entity => getAddedCollectionDtos({ entity }));
const modifiedDtos = modifiedEntities.flatMap(entity => getModifiedCollectionDtos({ entity }));
const deletedDtos = deletedEntities.flatMap(entity => getDeletedCollectionDtos({ entity }));

return [...deletedDtos, ...modifiedDtos, ...addedDtos].filter(Boolean);
};

module.exports = {
getCollectionAlterScriptDtos,
getCollectionContext,
getCollectionName,
getCompMod,
};
22 changes: 22 additions & 0 deletions forward_engineering/services/alterScript/commentHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { joinStatements } = require('../statements/commonStatements');

/**
* @param {{ statement: string }} params
* @returns {string}
*/
const commentStatement = ({ statement } = {}) => {
if (!statement) {
return '';
}

const joinedStatement = joinStatements({
statements: statement.split('\n').map(line => ` * ${line}`),
separator: '\n',
});

return `/*\n${joinedStatement}\n */`;
};

module.exports = {
commentStatement,
};
Loading