Allow using lodash functions in transform query

This commit is contained in:
Jos de Jong 2020-09-02 12:14:48 +02:00
parent 023c57f492
commit 45f8881e96
3 changed files with 23 additions and 6 deletions

View File

@ -10,6 +10,8 @@
import { sortArray, sortObjectKeys } from '../../logic/sort.js' import { sortArray, sortObjectKeys } from '../../logic/sort.js'
import { sortModalState } from './sortModalState.js' import { sortModalState } from './sortModalState.js'
import { compileJSONPointer } from '../../utils/jsonPointer.js' import { compileJSONPointer } from '../../utils/jsonPointer.js'
import { get } from 'lodash-es'
import { getIn } from '../../utils/immutabilityHelpers.js'
export let id export let id
export let json export let json
@ -22,7 +24,7 @@
$: json $: json
$: jsonIsArray = Array.isArray(json) $: jsonIsArray = Array.isArray(json)
$: paths = jsonIsArray ? getNestedPaths(json) : undefined $: paths = jsonIsArray ? getNestedPaths(json) : undefined
$: properties = paths?.map(pathToOption) $: properties = paths ? paths.map(pathToOption) : undefined
const asc = { const asc = {
value: 1, value: 1,
@ -34,8 +36,8 @@
} }
const directions = [asc, desc] const directions = [asc, desc]
let selectedProperty = sortModalState[stateId]?.selectedProperty || undefined let selectedProperty = (sortModalState[stateId] && sortModalState[stateId].selectedProperty) || undefined
let selectedDirection = sortModalState[stateId]?.selectedDirection || asc let selectedDirection = (sortModalState[stateId] && sortModalState[stateId].selectedDirection) || asc
$: { $: {
// if there is only one option, select it and do not render the select box // if there is only one option, select it and do not render the select box

View File

@ -5,6 +5,12 @@
.description { .description {
padding-bottom: $padding; padding-bottom: $padding;
code {
background: $background-gray;
font-family: $font-family-mono;
font-size: $font-size-mono;
}
} }
label { label {

View File

@ -8,6 +8,8 @@
import { transformModalState } from './transformModalState.js' import { transformModalState } from './transformModalState.js'
import { DEBOUNCE_DELAY, MAX_PREVIEW_CHARACTERS } from '../../constants.js' import { DEBOUNCE_DELAY, MAX_PREVIEW_CHARACTERS } from '../../constants.js'
import { truncate } from '../../utils/stringUtils.js' import { truncate } from '../../utils/stringUtils.js'
import * as _ from 'lodash-es'
import { getIn } from '../../utils/immutabilityHelpers.js'
export let id export let id
export let json export let json
@ -20,14 +22,15 @@
let stateId = `${id}:${compileJSONPointer(rootPath)}` let stateId = `${id}:${compileJSONPointer(rootPath)}`
let query = transformModalState[stateId]?.query || DEFAULT_QUERY let query = (transformModalState[stateId] && transformModalState[stateId].query) || DEFAULT_QUERY
let previewHasError = false let previewHasError = false
let preview = '' let preview = ''
function evalTransform(json, query) { function evalTransform(json, query) {
// FIXME: replace unsafe eval with a JS based query language // FIXME: replace unsafe new Function with a JS based query language
// As long as we don't persist or fetch queries, there is no security risk. // As long as we don't persist or fetch queries, there is no security risk.
const queryFn = eval(`(${query})`) // TODO: only import the most relevant subset of lodash instead of the full library?
const queryFn = new Function('_', `'use strict'; return (${query})`)(_)
return queryFn(json) return queryFn(json)
} }
@ -86,6 +89,12 @@
<div class='description'> <div class='description'>
Enter a JavaScript function to filter, sort, or transform the data. Enter a JavaScript function to filter, sort, or transform the data.
</div> </div>
<div class='description'>
You can use <a href='https://lodash.com' target='_blank' rel='noopener noreferrer'>Lodash</a>
functions like <code>_.map</code>, <code>_.filter</code>,
<code>_.orderBy</code>, <code>_.sortBy</code>, <code>_.groupBy</code>,
<code>_.pick</code>, <code>_.uniq</code>, <code>_.get</code>, etcetera.
</div>
<label>Query</label> <label>Query</label>
<textarea class="query" bind:value={query} /> <textarea class="query" bind:value={query} />