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
5 changes: 5 additions & 0 deletions api/fe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const { generateScript } = require('../forward_engineering/api');

module.exports = {
generateScript,
};
9 changes: 9 additions & 0 deletions esbuild.package.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const fs = require('fs');
const path = require('path');
const esbuild = require('esbuild');
const { clean } = require('esbuild-plugin-clean');
const { copy } = require('esbuild-plugin-copy');
const { copyFolderFiles, addReleaseFlag } = require('@hackolade/hck-esbuild-plugins-pack');
const { EXCLUDED_EXTENSIONS, EXCLUDED_FILES, DEFAULT_RELEASE_FOLDER_PATH } = require('./buildConstants');

Expand All @@ -11,6 +12,7 @@ const RELEASE_FOLDER_PATH = path.join(DEFAULT_RELEASE_FOLDER_PATH, `${packageDat
esbuild
.build({
entryPoints: [
path.resolve(__dirname, 'api', 'fe.js'),
path.resolve(__dirname, 'forward_engineering', 'api.js'),
path.resolve(__dirname, 'reverse_engineering', 'api.js'),
],
Expand All @@ -21,10 +23,17 @@ esbuild
outdir: RELEASE_FOLDER_PATH,
minify: true,
logLevel: 'info',
external: ['lodash'],
plugins: [
clean({
patterns: [DEFAULT_RELEASE_FOLDER_PATH],
}),
copy({
assets: {
from: [path.join('node_modules', 'lodash', '**', '*')],
to: [path.join('node_modules', 'lodash')],
},
}),
copyFolderFiles({
fromPath: __dirname,
targetFolderPath: RELEASE_FOLDER_PATH,
Expand Down
318 changes: 29 additions & 289 deletions forward_engineering/api.js
Original file line number Diff line number Diff line change
@@ -1,303 +1,43 @@
const helper = require('../helper/helper.js');
const schemaHelper = require('../helper/schemaHelper.js');
const { getFieldsSchema } = require('./helpers/getFieldsSchema');
const { getMappingScript } = require('./helpers/getMappingScript');
const { getTypeSchema } = require('./helpers/getTypeSchema');
const { getCurlScript } = require('./helpers/getCurlScript');
const { getKibanaScript } = require('./helpers/getKibanaScript');

module.exports = {
generateScript(data, logger, cb) {
const { jsonSchema, modelData, entityData, isUpdateScript } = data;
const containerData = data.containerData || {};
const {
jsonSchema,
modelData,
entityData,
isUpdateScript,
pluginConfiguration,
internalDefinitions,
modelDefinitions,
externalDefinitions,
containerData = {},
} = data;

let result = '';
let fieldsSchema = this.getFieldsSchema({

const fieldsSchema = getFieldsSchema({
jsonSchema: JSON.parse(jsonSchema),
internalDefinitions: JSON.parse(data.internalDefinitions),
modelDefinitions: JSON.parse(data.modelDefinitions),
externalDefinitions: JSON.parse(data.externalDefinitions),
internalDefinitions: JSON.parse(internalDefinitions),
modelDefinitions: JSON.parse(modelDefinitions),
externalDefinitions: JSON.parse(externalDefinitions),
fieldLevelConfig: pluginConfiguration.fieldLevelConfig,
});
let typeSchema = this.getTypeSchema(entityData, fieldsSchema);
let mappingScript = this.getMappingScript(containerData, typeSchema);

const typeSchema = getTypeSchema(entityData, fieldsSchema);

const mappingScript = getMappingScript(containerData, typeSchema, pluginConfiguration.containerLevelConfig);

if (isUpdateScript) {
result = this.getCurlScript(mappingScript, modelData, containerData);
result = getCurlScript(mappingScript, modelData, containerData);
} else {
result += this.getKibanaScript(mappingScript, containerData);
result += getKibanaScript(mappingScript, containerData);
}

cb(null, result);
},

getCurlScript(mapping, modelData, indexData) {
const host = modelData.host || 'localhost';
const port = modelData.port || 9200;
const indexName = indexData.name || '';
const majorVersion = +(modelData.dbVersion || '').split('.').shift();
const includeTypeName = majorVersion >= 7 ? '&include_type_name=true' : '';

return `curl -XPUT '${host}:${port}/${indexName.toLowerCase()}?pretty${includeTypeName}' -H 'Content-Type: application/json' -d '\n${JSON.stringify(mapping, null, 4)}\n'`;
},

getKibanaScript(mapping, indexData) {
const indexName = indexData.name || '';

return `PUT /${indexName.toLowerCase()}\n${JSON.stringify(mapping, null, 4)}`;
},

getFieldsSchema(data) {
const { jsonSchema } = data;
let schema = {};

if (!(jsonSchema.properties && jsonSchema.properties._source && jsonSchema.properties._source.properties)) {
return schema;
}

schema = this.getSchemaByItem(jsonSchema.properties._source.properties, data);

return schema;
},

getSchemaByItem(properties, data) {
let schema = {};

for (let fieldName in properties) {
let field = properties[fieldName];

schema[fieldName] = this.getField(field, data);
}

return schema;
},

getField(field, data) {
let schema = {};
const fieldProperties = helper.getFieldProperties(field.type, field, {});
let type = this.getFieldType(field);

if (type !== 'object' && type !== 'array') {
schema.type = type;
}

if (type === 'object') {
schema.properties = {};
}

this.setProperties(schema, fieldProperties, data);

if (type === 'alias') {
return { ...schema, ...this.getAliasSchema(field, data) };
} else if (type === 'join') {
return { ...schema, ...this.getJoinSchema(field) };
} else if (
[
'completion',
'sparse_vector',
'dense_vector',
'geo_shape',
'geo_point',
'rank_feature',
'rank_features',
].includes(type)
) {
return schema;
} else if (field.properties) {
schema.properties = this.getSchemaByItem(field.properties, data);
} else if (field.items) {
let arrData = field.items;

if (Array.isArray(field.items)) {
arrData = field.items[0];
}

schema = { ...schema, ...this.getField(arrData, data) };
}

return schema;
},

getFieldType(field) {
switch (field.type) {
case 'geo-shape':
return 'geo_shape';
case 'geo-point':
return 'geo_point';
case 'number':
return field.mode || 'long';
case 'string':
return field.mode || 'text';
case 'range':
return field.mode || 'integer_range';
case 'null':
return 'long';
default:
return field.type;
}
},

setProperties(schema, properties, data) {
for (let propName in properties) {
if (propName === 'stringfields') {
try {
schema['fields'] = JSON.parse(properties[propName]);
} catch (e) {}
} else if (this.isFieldList(properties[propName])) {
const names = schemaHelper.getNamesByIds(
properties[propName].map(item => item.keyId),
[data.jsonSchema, data.internalDefinitions, data.modelDefinitions, data.externalDefinitions],
);
if (names.length) {
schema[propName] = names.length === 1 ? names[0] : names;
}
} else {
schema[propName] = properties[propName];
}
}

return schema;
},

getTypeSchema(typeData, fieldsSchema) {
let script = {};

if (typeData.dynamic) {
script.dynamic = typeData.dynamic;
}

script.properties = fieldsSchema;

return {
[(typeData.collectionName || '').toLowerCase()]: script,
};
},

getMappingScript(indexData, typeSchema) {
let mappingScript = {};
let settings = this.getSettings(indexData);
let aliases = this.getAliases(indexData);

if (settings) {
mappingScript.settings = settings;
}

if (aliases) {
mappingScript.aliases = aliases;
}

mappingScript.mappings = typeSchema;

return mappingScript;
},

getSettings(indexData) {
let settings;
let properties = helper.getContainerLevelProperties();

properties.forEach(propertyName => {
if (indexData[propertyName]) {
if (!settings) {
settings = {};
}

settings[propertyName] = indexData[propertyName];
}
});

return settings;
},

getAliases(indexData) {
let aliases;

if (!indexData.aliases) {
return aliases;
}

indexData.aliases.forEach(alias => {
if (alias.name) {
if (!aliases) {
aliases = {};
}

aliases[alias.name] = {};

if (alias.filter) {
let filterData = '';
try {
filterData = JSON.parse(alias.filter);
} catch (e) {}

aliases[alias.name].filter = {
term: filterData,
};
}

if (alias.routing) {
aliases[alias.name].routing = alias.routing;
}
}
});

return aliases;
},

isFieldList(property) {
if (!Array.isArray(property)) {
return false;
}

if (!property[0]) {
return false;
}

if (property[0].keyId) {
return true;
}

return false;
},

getJoinSchema(field) {
if (!Array.isArray(field.relations)) {
return {};
}

const relations = field.relations.reduce((result, item) => {
if (!item.parent) {
return result;
}

if (!Array.isArray(item.children)) {
return result;
}

if (item.children.length === 1) {
return {
...result,
[item.parent]: item.children?.[0]?.name
};
}

return {
...result,
[item.parent]: item.children.map(item => item.name || '')
};
}, {});

return { relations };
},

getAliasSchema(field, data) {
if (!Array.isArray(field.path)) {
return {};
}

if (field.path.length === 0) {
return {};
}

const pathName = schemaHelper.getPathName(field.path[0].keyId, [
data.jsonSchema,
data.internalDefinitions,
data.modelDefinitions,
data.externalDefinitions,
]);

return { path: pathName };
},
};
13 changes: 13 additions & 0 deletions forward_engineering/helpers/getCurlScript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const getCurlScript = (mapping, modelData, indexData) => {
const host = modelData.host || 'localhost';
const port = modelData.port || 9200;
const indexName = indexData.name || '';
const majorVersion = +(modelData.dbVersion || '').split('.').shift();
const includeTypeName = majorVersion >= 7 ? '&include_type_name=true' : '';

return `curl -XPUT '${host}:${port}/${indexName.toLowerCase()}?pretty${includeTypeName}' -H 'Content-Type: application/json' -d '\n${JSON.stringify(mapping, null, 4)}\n'`;
};

module.exports = {
getCurlScript,
};
Loading