Skip to content
Merged
7 changes: 7 additions & 0 deletions api/fe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { generateContainerScript } = require('../forward_engineering/api/generateContainerScript');
const { isDropInStatements } = require('../forward_engineering/api/isDropInStatements');

module.exports = {
generateContainerScript,
isDropInStatements,
};
10 changes: 10 additions & 0 deletions constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,19 @@ const INLINE_COMMENT = '--';

const PERSENT = '__PERCENT__';

const CONSTRAINT_POSTFIX = {
primaryKey: 'pk',
foreignKey: 'fk',
uniqueKey: 'uk',
notNull: 'nn',
check: 'check',
default: 'default',
};

module.exports = {
ERROR_MESSAGE,
TABLE_TYPE,
INLINE_COMMENT,
PERSENT,
CONSTRAINT_POSTFIX,
};
1 change: 1 addition & 0 deletions esbuild.package.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ esbuild
.build({
entryPoints: [
path.resolve(__dirname, 'forward_engineering', 'api.js'),
path.resolve(__dirname, 'api', 'fe.js'),
path.resolve(__dirname, 'forward_engineering', 'ddlProvider.js'),
path.resolve(__dirname, 'reverse_engineering', 'api.js'),
],
Expand Down
71 changes: 71 additions & 0 deletions forward_engineering/alterScript/alterScriptBuilder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const { commentIfDeactivated } = require('../utils/general');
const { getAlterScriptDtos } = require('./alterScriptFromDeltaHelper');

const joinAlterScriptDtosIntoScript = (dtos, shouldApplyDropStatements) => {
return dtos
.flatMap(dto => {
if (dto.isActivated === false) {
return dto.scripts.map(scriptDto =>
commentIfDeactivated(scriptDto.script, {
isActivated: false,
isPartOfLine: false,
}),
);
}
if (!shouldApplyDropStatements) {
return dto.scripts.map(scriptDto =>
commentIfDeactivated(scriptDto.script, {
isActivated: !scriptDto.isDropScript,
isPartOfLine: false,
}),
);
}
return dto.scripts.map(scriptDto => scriptDto.script);
})
.map(scriptLine => scriptLine?.trim())
.filter(Boolean)
.join('\n\n');
};

const doesEntityLevelAlterScriptContainDropStatements = (data, app) => {
const alterScriptDtos = getAlterScriptDtos(data, app);
return alterScriptDtos.some(
alterScriptDto =>
alterScriptDto.isActivated &&
alterScriptDto.scripts.some(scriptModificationDto => scriptModificationDto.isDropScript),
);
};

const mapCoreDataForContainerLevelScripts = data => {
return {
...data,
jsonSchema: data.collections[0],
internalDefinitions: Object.values(data.internalDefinitions)[0],
};
};

const buildContainerLevelAlterScript = (data, app) => {
const preparedData = mapCoreDataForContainerLevelScripts(data);
const alterScriptDtos = getAlterScriptDtos(preparedData, app);
const shouldApplyDropStatements = preparedData.options?.additionalOptions?.some(
option => option.id === 'applyDropStatements' && option.value,
);

return joinAlterScriptDtosIntoScript(alterScriptDtos, shouldApplyDropStatements);
};

const doesContainerLevelAlterScriptContainDropStatements = (data, app) => {
const preparedData = mapCoreDataForContainerLevelScripts(data);
const alterScriptDtos = getAlterScriptDtos(preparedData, app);
return alterScriptDtos.some(
alterScriptDto =>
alterScriptDto.isActivated &&
alterScriptDto.scripts.some(scriptModificationDto => scriptModificationDto.isDropScript),
);
};

module.exports = {
doesEntityLevelAlterScriptContainDropStatements,
buildContainerLevelAlterScript,
doesContainerLevelAlterScriptContainDropStatements,
};
154 changes: 154 additions & 0 deletions forward_engineering/alterScript/alterScriptFromDeltaHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
const {
getModifyCollectionScriptDtos,
getModifyCollectionKeysScriptDtos,
getModifyColumnScriptDtos,
} = require('./alterScriptHelpers/alterEntityHelper');
const {
getDeleteForeignKeyScriptDtos,
getAddForeignKeyScriptDtos,
getModifyForeignKeyScriptDtos,
} = require('./alterScriptHelpers/alterForeignKeyHelper');
const { getModifyViewScriptDtos } = require('./alterScriptHelpers/alterViewHelper');

const getItems = data => [data?.items].flat().filter(Boolean);

const getAlterCollectionScriptDtos = ({
collection,
app,
modelDefinitions,
internalDefinitions,
externalDefinitions,
}) => {
const modifyScriptsData = getItems(collection.properties?.entities?.properties?.modified).map(
item => Object.values(item.properties)[0],
);

const modifyCollectionScriptDtos = modifyScriptsData.flatMap(getModifyCollectionScriptDtos);
const modifyCollectionKeysScriptDtos = modifyScriptsData.flatMap(getModifyCollectionKeysScriptDtos);
const modifyColumnScriptDtos = modifyScriptsData.flatMap(getModifyColumnScriptDtos);

return [...modifyCollectionScriptDtos, ...modifyColumnScriptDtos, ...modifyCollectionKeysScriptDtos].filter(
Boolean,
);
};

const getAlterViewScriptDtos = collection => {
const modifyViewScriptDtos = getItems(collection.properties?.views?.properties?.modified)
.map(viewWrapper => Object.values(viewWrapper.properties)[0])
.map(view => ({ ...view, ...view.role }))
.flatMap(getModifyViewScriptDtos);

return [...modifyViewScriptDtos].filter(Boolean);
};

const getAlterRelationshipsScriptDtos = ({ collection, app, ignoreRelationshipIDs = [] }) => {
const addedRelationships = getItems(collection.properties?.relationships?.properties?.added)
.filter(Boolean)
.map(item => Object.values(item.properties)[0])
.filter(
relationship =>
relationship?.role?.compMod?.created && !ignoreRelationshipIDs.includes(relationship?.role?.id),
);

const deletedRelationships = getItems(collection.properties?.relationships?.properties?.deleted)
.filter(Boolean)
.map(item => Object.values(item.properties)[0])
.filter(
relationship =>
relationship?.role?.compMod?.deleted && !ignoreRelationshipIDs.includes(relationship?.role?.id),
);

const modifiedRelationships = getItems(collection.properties?.relationships?.properties?.modified)
.filter(Boolean)
.map(item => Object.values(item.properties)[0])
.filter(
relationship =>
relationship?.role?.compMod?.modified && !ignoreRelationshipIDs.includes(relationship?.role?.id),
);

const deleteFkScriptDtos = getDeleteForeignKeyScriptDtos(deletedRelationships);
const addFkScriptDtos = getAddForeignKeyScriptDtos(addedRelationships);
const modifiedFkScriptDtos = getModifyForeignKeyScriptDtos(modifiedRelationships);

return [...deleteFkScriptDtos, ...addFkScriptDtos, ...modifiedFkScriptDtos].filter(Boolean);
};

const getInlineRelationships = ({ collection, options }) => {
if (options?.scriptGenerationOptions?.feActiveOptions?.foreignKeys !== 'inline') {
return [];
}

const addedCollectionIDs = getItems(collection.properties?.entities?.properties?.added)
.filter(item => item && Object.values(item.properties)?.[0]?.compMod?.created)
.map(item => Object.values(item.properties)[0].role.id);

const addedRelationships = getItems(collection.properties?.relationships?.properties?.added)
.map(item => item && Object.values(item.properties)[0])
.filter(r => r?.role?.compMod?.created && addedCollectionIDs.includes(r?.role?.childCollection));

return addedRelationships;
};

const prettifyAlterScriptDto = dto => {
if (!dto) {
return undefined;
}
/**
* @type {Array<ModificationScript>}
* */
const nonEmptyScriptModificationDtos = dto.scripts
.map(scriptDto => ({
...scriptDto,
script: (scriptDto.script || '').trim(),
}))
.filter(scriptDto => Boolean(scriptDto.script));
if (!nonEmptyScriptModificationDtos.length) {
return undefined;
}
return {
...dto,
scripts: nonEmptyScriptModificationDtos,
};
};

const getAlterScriptDtos = (data, app) => {
const collection = JSON.parse(data.jsonSchema);

if (!collection) {
throw new Error(
'"comparisonModelCollection" is not found. Alter script can be generated only from Delta model',
);
}

const modelDefinitions = JSON.parse(data.modelDefinitions);
const internalDefinitions = JSON.parse(data.internalDefinitions);
const externalDefinitions = JSON.parse(data.externalDefinitions);

const inlineDeltaRelationships = getInlineRelationships({ collection, options: data.options });
const ignoreRelationshipIDs = inlineDeltaRelationships.map(relationship => relationship.role.id);

const collectionsScriptDtos = getAlterCollectionScriptDtos({
collection,
app,
modelDefinitions,
internalDefinitions,
externalDefinitions,
});

const viewScriptDtos = getAlterViewScriptDtos(collection);

const relationshipScriptDtos = getAlterRelationshipsScriptDtos({
collection,
app,
ignoreRelationshipIDs,
});

return [...collectionsScriptDtos, ...viewScriptDtos, ...relationshipScriptDtos]
.filter(Boolean)
.map(dto => dto && prettifyAlterScriptDto(dto))
.filter(Boolean);
};

module.exports = {
getAlterScriptDtos,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { getModifiedCommentOnColumnScriptDtos } = require('./columnHelpers/commentsHelper');
const { getModifyNonNullColumnsScriptDtos } = require('./columnHelpers/nonNullConstraintHelper');
const { getModifyCheckConstraintScriptDtos } = require('./entityHelpers/checkConstraintHelper');
const { getModifyEntityCommentsScriptDtos } = require('./entityHelpers/commentsHelper');
const { getModifyPkConstraintsScriptDtos } = require('./entityHelpers/primaryKeyHelper');
const { getModifyUkConstraintsScriptDtos } = require('./entityHelpers/uniqueKeyHelper');
const { getModifiedDefaultColumnValueScriptDtos } = require('./columnHelpers/defaultValueHelper');

const getModifyCollectionScriptDtos = collection => {
const modifyCheckConstraintScriptDtos = getModifyCheckConstraintScriptDtos(collection);
const modifyCommentScriptDtos = getModifyEntityCommentsScriptDtos(collection);
return [...modifyCheckConstraintScriptDtos, ...modifyCommentScriptDtos].filter(Boolean);
};

const getModifyCollectionKeysScriptDtos = collection => {
const modifyPkConstraintDtos = getModifyPkConstraintsScriptDtos(collection);
const modifyUkConstraintDtos = getModifyUkConstraintsScriptDtos(collection);
return [...modifyPkConstraintDtos, ...modifyUkConstraintDtos].filter(Boolean);
};

const getModifyColumnScriptDtos = collection => {
const modifyNotNullScriptDtos = getModifyNonNullColumnsScriptDtos(collection);
const modifyCommentScriptDtos = getModifiedCommentOnColumnScriptDtos(collection);
const modifyDefaultColumnValueScriptDtos = getModifiedDefaultColumnValueScriptDtos({ collection });

return [...modifyNotNullScriptDtos, ...modifyDefaultColumnValueScriptDtos, ...modifyCommentScriptDtos].filter(
Boolean,
);
};

module.exports = {
getModifyCollectionScriptDtos,
getModifyColumnScriptDtos,
getModifyCollectionKeysScriptDtos,
};
Loading