interface ScriptDefinition {
    ... // ?? to be defined
    __meta__: {
        version: number; // this lets the editor know how to handle the def
    }
}
- Runtime field editor returns a field
 
{
    name: string;
    emitType: string;
    getScript() => {
        script: string;
        scriptDefinition: ScriptDefinition;
    };
}- Index pattern management needs to
 
a. Send the field to attach to the ES query
const { getScript, ...rest } = field;
const fieldForQuery = {
    ...rest,
    script: getScript().script, // get the painless script
}b. Save the field to the index pattern saved object
const fieldForIndexPatternSavedObject = {
    ...rest,
    scriptDefinition: getScript().scriptDefinition, // save only the definition. This could be "raw" string and be simply painless
}- Index pattern will need to retrieve the runtime fields from the saved object and return them both in the list of fields and ready for ES query
 
const runtimeFields = savedObject.somePath.runtimeFields.map((field) => {
    // Here we need to return **both** the script for the ES query and the definition for the UI
    return {
        ...field,
        // call a method from the plugin (it could also be exposed statically)
        script: runtimeFieldsPlugin.getScriptFromDefinition(field.scriptDefinition)
    };
});And the above returns runtime field objects like this:
{
    name: string;
    outputType: string;
    script: string; // for the ES Query
    scriptDefinition: ScriptDefinition; // for the UI
}
I am happy with your proposal but I think I miss what problem we are trying to solve here. I will put this on the agenda for tomorrow's UI sync so we can discuss it.