import {GeneratorOptions} from './index.js'; import {JSONSchema7} from 'json-schema'; import {ElasticsearchOptionsDSL} from '../dsl/schema.js'; import { IndicesPutTemplateRequest, MappingProperty, MappingTypeMapping, SearchRequest, } from '@elastic/elasticsearch/lib/api/types.js'; import {Context} from './context.js'; import deepmerge from 'deepmerge'; import {renderTemplate} from '../template.js'; /** * Sanitize a type name */ export function sanitizeTypeName(typeName: string): string { return typeName.replaceAll(' ', '_'); } export class MappingGenerator { readonly presets: Map; readonly cache: Map>}>; readonly searchMods: {mods: Partial} = {mods: {}}; readonly template: Partial; constructor(readonly project: JSONSchema7, options: GeneratorOptions) { this.template = options.template ?? {}; this.presets = new Map(Object.entries(options.presets)); this.cache = new Map( Object.entries(options.overrides).map(([name, mapping]) => [ name, { mapping, dependencies: new Map(), }, ]), ); } buildTemplate(name: string): IndicesPutTemplateRequest { const thingType = ((this.project.definitions![name] as JSONSchema7).properties!.type as JSONSchema7) .const; if (typeof thingType !== 'string') { throw new TypeError(`${name} needs a valid thing type`); } const mappingContext = new Context(this, thingType, [name], [], new Map()); const mappings = mappingContext.resolveReference(name); const request: IndicesPutTemplateRequest = deepmerge( {mappings: mappings as MappingTypeMapping}, renderTemplate(this.template, [ ['{name}', name], ['{type}', thingType], ['{_type}', sanitizeTypeName(thingType)], ]), ); if (mappingContext.dependencies.size > 0) { request.mappings!.dynamic_templates = []; for (const [name, paths] of mappingContext.dependencies) { request.mappings!.dynamic_templates.push({ [name]: { path_match: paths.size > 1 ? [...paths] : paths.values().next().value, mapping: mappingContext.resolveReference(name), }, }); } } return request; } }