diff --git a/packages/api/src/shell/copyStream.js b/packages/api/src/shell/copyStream.js index 60e49deb7..637eb0bb9 100644 --- a/packages/api/src/shell/copyStream.js +++ b/packages/api/src/shell/copyStream.js @@ -1,18 +1,47 @@ const EnsureStreamHeaderStream = require('../utility/EnsureStreamHeaderStream'); +const Stream = require('stream'); +const ColumnMapTransformStream = require('../utility/ColumnMapTransformStream'); + +function copyStream(input, output, options) { + const { columns } = options || {}; + + const transforms = []; + if (columns) { + transforms.push(new ColumnMapTransformStream(columns)); + } + if (output.requireFixedStructure) { + transforms.push(new EnsureStreamHeaderStream()); + } + + // return new Promise((resolve, reject) => { + // Stream.pipeline(input, ...transforms, output, err => { + // if (err) { + // reject(err); + // } else { + // resolve(); + // } + // }); + // }); -function copyStream(input, output) { return new Promise((resolve, reject) => { const finisher = output['finisher'] || output; finisher.on('finish', resolve); finisher.on('error', reject); - if (output.requireFixedStructure) { - const ensureHeader = new EnsureStreamHeaderStream(); - input.pipe(ensureHeader); - ensureHeader.pipe(output); - } else { - input.pipe(output); + let lastStream = input; + for (const tran of transforms) { + lastStream.pipe(tran); + lastStream = tran; } + lastStream.pipe(output); + + // if (output.requireFixedStructure) { + // const ensureHeader = new EnsureStreamHeaderStream(); + // input.pipe(ensureHeader); + // ensureHeader.pipe(output); + // } else { + // input.pipe(output); + // } }); } diff --git a/packages/api/src/utility/ColumnMapTransformStream.js b/packages/api/src/utility/ColumnMapTransformStream.js new file mode 100644 index 000000000..1bbd913df --- /dev/null +++ b/packages/api/src/utility/ColumnMapTransformStream.js @@ -0,0 +1,21 @@ +const stream = require('stream'); +const { transformRowUsingColumnMap } = require('dbgate-tools'); + +class ColumnMapTransformStream extends stream.Transform { + constructor(columns) { + super({ objectMode: true }); + this.columns = columns; + } + _transform(chunk, encoding, done) { + if (chunk.__isStreamHeader) { + // skip stream header + done(); + return; + } + + this.push(transformRowUsingColumnMap(chunk, this.columns)); + done(); + } +} + +module.exports = ColumnMapTransformStream; diff --git a/packages/tools/src/tableTransforms.ts b/packages/tools/src/tableTransforms.ts index 403426cff..54f46ed03 100644 --- a/packages/tools/src/tableTransforms.ts +++ b/packages/tools/src/tableTransforms.ts @@ -1,5 +1,7 @@ import { TableInfo } from 'dbgate-types'; import _cloneDeep from 'lodash/cloneDeep'; +import _fromPairs from 'lodash/fromPairs'; +import _get from 'lodash/get'; export function prepareTableForImport(table: TableInfo): TableInfo { const res = _cloneDeep(table); @@ -10,3 +12,12 @@ export function prepareTableForImport(table: TableInfo): TableInfo { if (res.primaryKey) res.primaryKey.constraintName = null; return res; } + +interface TransformColumnDefinition { + src: string; + dst: string; +} + +export function transformRowUsingColumnMap(row, columns: TransformColumnDefinition[]) { + return _fromPairs(columns.map(col => [col.dst, _get(row, col.src)])); +} diff --git a/packages/web/src/elements/TableControl.svelte b/packages/web/src/elements/TableControl.svelte index e68377345..d22a01524 100644 --- a/packages/web/src/elements/TableControl.svelte +++ b/packages/web/src/elements/TableControl.svelte @@ -24,6 +24,7 @@ export let selectedIndex = 0; export let clickable = false; export let disableFocusOutline = false; + export let emptyMessage = null; export let domTable = undefined; @@ -99,6 +100,11 @@ {/each} {/each} + {#if emptyMessage && rows.length == 0} +