"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.createSchemaFromFieldMap = void 0; var _fs = _interopRequireDefault(require("fs")); var _path = _interopRequireDefault(require("path")); var _saferLodashSet = require("@kbn/safer-lodash-set"); var _lodash = require("lodash"); var _line_writer = require("./lib/line_writer"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ const PLUGIN_DIR = _path.default.resolve(_path.default.join(__dirname, '..')); const createSchemaFromFieldMap = ({ outputFile, fieldMap, schemaPrefix, useAlert = false, useEcs = false, useLegacyAlerts = false, flattened = false }) => { const lineWriters = { IMPORTS: (0, _line_writer.createLineWriter)(), REQUIRED_FIELDS: (0, _line_writer.createLineWriter)(), OPTIONAL_FIELDS: (0, _line_writer.createLineWriter)(), INCLUDED_SCHEMAS: (0, _line_writer.createLineWriter)('') }; if (useAlert) { lineWriters.IMPORTS.addLine(`import { AlertSchema } from './alert_schema';`); lineWriters.INCLUDED_SCHEMAS.addLine(`, AlertSchema`); } if (useEcs) { lineWriters.IMPORTS.addLine(`import { EcsSchema } from './ecs_schema';`); lineWriters.INCLUDED_SCHEMAS.addLine(`, EcsSchema`); } if (useLegacyAlerts) { lineWriters.IMPORTS.addLine(`import { LegacyAlertSchema } from './legacy_alert_schema';`); lineWriters.INCLUDED_SCHEMAS.addLine(`, LegacyAlertSchema`); } generateSchemaFromFieldMap({ lineWriters, fieldMap, flattened }); const contents = getSchemaFileContents(lineWriters, schemaPrefix); writeGeneratedFile(outputFile, `${contents}\n`); }; exports.createSchemaFromFieldMap = createSchemaFromFieldMap; const generateSchemaFromFieldMap = ({ lineWriters, fieldMap, flattened }) => { const requiredFieldMap = { properties: {} }; const optionalFieldMap = { properties: {} }; const getKeyWithProperties = key => key.split('.').join('.properties.'); // Generate required properties Object.keys(fieldMap).filter(key => fieldMap[key].required === true).map(key => (0, _saferLodashSet.set)(requiredFieldMap.properties, getKeyWithProperties(key), fieldMap[key])); generateSchemaLines({ lineWriter: lineWriters.REQUIRED_FIELDS, propertyKey: null, required: true, flattened, fieldMap: requiredFieldMap }); // Generate optional properties Object.keys(fieldMap).filter(key => fieldMap[key].required !== true).map(key => (0, _saferLodashSet.set)(optionalFieldMap.properties, getKeyWithProperties(key), fieldMap[key])); generateSchemaLines({ lineWriter: lineWriters.OPTIONAL_FIELDS, propertyKey: null, required: false, flattened, fieldMap: optionalFieldMap }); }; const getSchemaDefinition = (schemaPrefix, isArray) => { if (isArray) { schemaPrefix = `${schemaPrefix}Array`; } return schemaPrefix; }; const generateSchemaLines = ({ fieldMap, propertyKey, lineWriter, required, flattened }) => { if (fieldMap == null) return; const type = (0, _lodash.get)(fieldMap, 'type'); const isArray = (0, _lodash.get)(fieldMap, 'array', false); const isEnabled = (0, _lodash.get)(fieldMap, 'enabled', true); let keyToWrite = propertyKey; if (propertyKey !== null && propertyKey !== void 0 && propertyKey.includes('.') || propertyKey !== null && propertyKey !== void 0 && propertyKey.includes('@')) { keyToWrite = `'${propertyKey}'`; } if (null != type) { switch (type) { case 'flattened': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaUnknown', isArray)},`); break; case 'object': case 'nested': if (!isEnabled) { lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaUnknown', isArray)},`); } else if (isArray && null != fieldMap.properties) { lineWriter.addLineAndIndent(`${keyToWrite}: rt.array(`); if (required) { lineWriter.addLineAndIndent(`rt.type({`); } else { lineWriter.addLineAndIndent(`rt.partial({`); } for (const prop of Object.keys(fieldMap.properties).sort()) { generateSchemaLines({ lineWriter, propertyKey: prop, required, fieldMap: fieldMap.properties[prop], flattened }); } lineWriter.dedentAndAddLine(`})`); lineWriter.dedentAndAddLine(`),`); } break; case 'keyword': case 'ip': case 'constant_keyword': case 'match_only_text': case 'text': case 'version': case 'wildcard': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaString', isArray)},`); break; case 'date': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaDate', isArray)},`); break; case 'date_range': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaDateRange', isArray)},`); break; case 'geo_point': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaGeoPoint', isArray)},`); break; case 'long': case 'scaled_float': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaStringOrNumber', isArray)},`); break; case 'float': case 'integer': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaNumber', isArray)},`); break; case 'boolean': lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaBoolean', isArray)},`); break; case 'alias': if (!flattened) { lineWriter.addLine(`${keyToWrite}: ${getSchemaDefinition('schemaUnknown', isArray)},`); } break; default: logError(`unknown type ${type}: ${JSON.stringify(fieldMap)}`); break; } return; } if (null == (0, _lodash.get)(fieldMap, 'properties')) { logError(`unknown properties ${propertyKey}: ${JSON.stringify(fieldMap)}`); } if (null == propertyKey) { if (required) { lineWriter.addLineAndIndent(`rt.type({`); } else { lineWriter.addLineAndIndent(`rt.partial({`); } } else if (!flattened) { if (required) { lineWriter.addLineAndIndent(`${propertyKey}: rt.type({`); } else { lineWriter.addLineAndIndent(`${propertyKey}: rt.partial({`); } } // write the object properties for (const prop of Object.keys(fieldMap.properties).sort()) { const key = propertyKey && flattened ? `${propertyKey}.${prop}` : prop; generateSchemaLines({ lineWriter, propertyKey: key, required, flattened, fieldMap: fieldMap.properties[prop] }); } if (null == propertyKey || !flattened) { lineWriter.dedentAndAddLine(`}),`); } }; const SchemaFileTemplate = ` /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ // ---------------------------------- WARNING ---------------------------------- // this file was generated, and should not be edited by hand // ---------------------------------- WARNING ---------------------------------- import * as rt from 'io-ts'; import { Either } from 'fp-ts/lib/Either'; %%IMPORTS%% const ISO_DATE_PATTERN = /^d{4}-d{2}-d{2}Td{2}:d{2}:d{2}.d{3}Z$/; export const IsoDateString = new rt.Type( 'IsoDateString', rt.string.is, (input, context): Either => { if (typeof input === 'string' && ISO_DATE_PATTERN.test(input)) { return rt.success(input); } else { return rt.failure(input, context); } }, rt.identity ); export type IsoDateStringC = typeof IsoDateString; export const schemaDate = IsoDateString; export const schemaDateArray = rt.array(IsoDateString); export const schemaDateRange = rt.partial({ gte: schemaDate, lte: schemaDate, }); export const schemaDateRangeArray = rt.array(schemaDateRange); export const schemaUnknown = rt.unknown; export const schemaUnknownArray = rt.array(rt.unknown); export const schemaString = rt.string; export const schemaStringArray = rt.array(schemaString); export const schemaNumber = rt.number; export const schemaNumberArray = rt.array(schemaNumber); export const schemaStringOrNumber = rt.union([schemaString, schemaNumber]); export const schemaStringOrNumberArray = rt.array(schemaStringOrNumber); export const schemaBoolean = rt.boolean; export const schemaBooleanArray = rt.array(schemaBoolean); const schemaGeoPointCoords = rt.type({ type: schemaString, coordinates: schemaNumberArray, }); const schemaGeoPointString = schemaString; const schemaGeoPointLatLon = rt.type({ lat: schemaNumber, lon: schemaNumber, }); const schemaGeoPointLocation = rt.type({ location: schemaNumberArray, }); const schemaGeoPointLocationString = rt.type({ location: schemaString, }); export const schemaGeoPoint = rt.union([ schemaGeoPointCoords, schemaGeoPointString, schemaGeoPointLatLon, schemaGeoPointLocation, schemaGeoPointLocationString, ]); export const schemaGeoPointArray = rt.array(schemaGeoPoint); // prettier-ignore const %%schemaPrefix%%Required = %%REQUIRED_FIELDS%%; const %%schemaPrefix%%Optional = %%OPTIONAL_FIELDS%%; // prettier-ignore export const %%schemaPrefix%%Schema = rt.intersection([%%schemaPrefix%%Required, %%schemaPrefix%%Optional%%INCLUDED_SCHEMAS%%]); // prettier-ignore export type %%schemaPrefix%% = rt.TypeOf; `.trim(); const getSchemaFileContents = (lineWriters, schemaPrefix) => { return Object.keys(lineWriters).reduce((currTemplate, key) => { const schemaLines = lineWriters[key].getContent().replace(/,$/, ''); return currTemplate.replaceAll(`%%schemaPrefix%%`, schemaPrefix).replace(`%%${key}%%`, schemaLines); }, SchemaFileTemplate); }; const writeGeneratedFile = (fileName, contents) => { const genFileName = _path.default.join(PLUGIN_DIR, fileName); try { _fs.default.writeFileSync(genFileName, contents); } catch (err) { logError(`error writing file: ${genFileName}: ${err.message}`); } }; const logError = message => { // eslint-disable-next-line no-console console.log(`error: ${message}`); process.exit(1); };