Skip to content

Commit

Permalink
[Expressions] Refactor expression functions to use observables undern…
Browse files Browse the repository at this point in the history
…eath (#100409)
  • Loading branch information
dokmic authored Jun 11, 2021
1 parent 9c37a67 commit 9bcae4d
Show file tree
Hide file tree
Showing 19 changed files with 605 additions and 454 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface ExpressionFunctionDefinition<Name extends string, Input, Argume
| [help](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.help.md) | <code>string</code> | Help text displayed in the Expression editor. This text should be internationalized. |
| [inputTypes](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.inputtypes.md) | <code>Array&lt;TypeToString&lt;Input&gt;&gt;</code> | List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. |
| [name](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.name.md) | <code>Name</code> | The name of the function, as will be used in expression. |
| [type](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md) | <code>TypeToString&lt;UnwrapPromiseOrReturn&lt;Output&gt;&gt;</code> | Name of type of value this function outputs. |
| [type](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md) | <code>TypeString&lt;Output&gt; &#124; UnmappedTypeStrings</code> | Name of type of value this function outputs. |
## Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Name of type of value this function outputs.
<b>Signature:</b>

```typescript
type?: TypeToString<UnwrapPromiseOrReturn<Output>>;
type?: TypeString<Output> | UnmappedTypeStrings;
```
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface ExpressionFunctionDefinition<Name extends string, Input, Argume
| [help](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.help.md) | <code>string</code> | Help text displayed in the Expression editor. This text should be internationalized. |
| [inputTypes](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.inputtypes.md) | <code>Array&lt;TypeToString&lt;Input&gt;&gt;</code> | List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. |
| [name](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.name.md) | <code>Name</code> | The name of the function, as will be used in expression. |
| [type](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md) | <code>TypeToString&lt;UnwrapPromiseOrReturn&lt;Output&gt;&gt;</code> | Name of type of value this function outputs. |
| [type](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md) | <code>TypeString&lt;Output&gt; &#124; UnmappedTypeStrings</code> | Name of type of value this function outputs. |
## Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Name of type of value this function outputs.
<b>Signature:</b>

```typescript
type?: TypeToString<UnwrapPromiseOrReturn<Output>>;
type?: TypeString<Output> | UnmappedTypeStrings;
```
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@
* Side Public License, v 1.
*/

import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { Observable, defer, of, zip } from 'rxjs';
import { map } from 'rxjs/operators';
import { i18n } from '@kbn/i18n';
import { ExpressionFunctionDefinition } from '../types';
import { Datatable, DatatableColumn, getType } from '../../expression_types';

export interface MapColumnArguments {
id?: string | null;
name: string;
expression?(datatable: Datatable): Observable<boolean | number | string | null>;
expression(datatable: Datatable): Observable<boolean | number | string | null>;
copyMetaFrom?: string | null;
}

export const mapColumn: ExpressionFunctionDefinition<
'mapColumn',
Datatable,
MapColumnArguments,
Promise<Datatable>
Observable<Datatable>
> = {
name: 'mapColumn',
aliases: ['mc'], // midnight commander. So many times I've launched midnight commander instead of moving a file.
Expand Down Expand Up @@ -80,57 +80,56 @@ export const mapColumn: ExpressionFunctionDefinition<
default: null,
},
},
fn: (input, args) => {
const expression = (...params: Parameters<Required<MapColumnArguments>['expression']>) =>
args
.expression?.(...params)
.pipe(take(1))
.toPromise() ?? Promise.resolve(null);
fn(input, args) {
const existingColumnIndex = input.columns.findIndex(({ id, name }) =>
args.id ? id === args.id : name === args.name
);
const id = input.columns[existingColumnIndex]?.id ?? args.id ?? args.name;

const columns = [...input.columns];
const existingColumnIndex = columns.findIndex(({ id, name }) => {
if (args.id) {
return id === args.id;
}
return name === args.name;
});
const columnId =
existingColumnIndex === -1 ? args.id ?? args.name : columns[existingColumnIndex].id;

const rowPromises = input.rows.map((row) => {
return expression({
type: 'datatable',
columns,
rows: [row],
}).then((val) => ({
...row,
[columnId]: val,
}));
});
return defer(() => {
const rows$ = input.rows.length
? zip(
...input.rows.map((row) =>
args
.expression({
type: 'datatable',
columns: [...input.columns],
rows: [row],
})
.pipe(map((value) => ({ ...row, [id]: value })))
)
)
: of([]);

return Promise.all(rowPromises).then((rows) => {
const type = rows.length ? getType(rows[0][columnId]) : 'null';
const newColumn: DatatableColumn = {
id: columnId,
name: args.name,
meta: { type, params: { id: type } },
};
if (args.copyMetaFrom) {
const metaSourceFrom = columns.find(({ id }) => id === args.copyMetaFrom);
newColumn.meta = { ...newColumn.meta, ...(metaSourceFrom?.meta || {}) };
}
return rows$.pipe<Datatable>(
map((rows) => {
const type = getType(rows[0]?.[id]);
const newColumn: DatatableColumn = {
id,
name: args.name,
meta: { type, params: { id: type } },
};
if (args.copyMetaFrom) {
const metaSourceFrom = input.columns.find(
({ id: columnId }) => columnId === args.copyMetaFrom
);
newColumn.meta = { ...newColumn.meta, ...(metaSourceFrom?.meta ?? {}) };
}

if (existingColumnIndex === -1) {
columns.push(newColumn);
} else {
columns[existingColumnIndex] = newColumn;
}
const columns = [...input.columns];
if (existingColumnIndex === -1) {
columns.push(newColumn);
} else {
columns[existingColumnIndex] = newColumn;
}

return {
type: 'datatable',
columns,
rows,
} as Datatable;
return {
columns,
rows,
type: 'datatable',
};
})
);
});
},
};
Loading

0 comments on commit 9bcae4d

Please sign in to comment.