load extensions

This commit is contained in:
Jan Prochazka
2021-02-22 18:50:54 +01:00
parent 1e540b3fe9
commit 48e3cf1be5
7 changed files with 223 additions and 4 deletions

View File

@@ -0,0 +1,87 @@
// import React from 'react';
// import styled from 'styled-components';
// import useTheme from '../theme/useTheme';
// import { useSetOpenedTabs } from '../utility/globalState';
// import { extractPluginIcon, extractPluginAuthor } from '../plugins/manifestExtractors';
// import useOpenNewTab from '../utility/useOpenNewTab';
// const Wrapper = styled.div`
// margin: 1px 3px 10px 5px;
// display: flex;
// align-items: center;
// &:hover {
// background-color: ${props => props.theme.left_background_blue[1]};
// }
// `;
// const Texts = styled.div`
// margin-left: 10px;
// `;
// const Name = styled.div`
// font-weight: bold;
// `;
// const Line = styled.div`
// display: flex;
// `;
// const Icon = styled.img`
// width: 50px;
// height: 50px;
// `;
// const Description = styled.div`
// font-style: italic;
// `;
// const Author = styled.div`
// font-weight: bold;
// `;
// const Version = styled.div`
// margin-left: 5px;
// `;
// function openPlugin(openNewTab, packageManifest) {
// openNewTab({
// title: packageManifest.name,
// icon: 'icon plugin',
// tabComponent: 'PluginTab',
// props: {
// packageName: packageManifest.name,
// },
// });
// }
// function PluginsListItem({ packageManifest }) {
// const openNewTab = useOpenNewTab();
// const theme = useTheme();
// return (
// <Wrapper onClick={() => openPlugin(openNewTab, packageManifest)} theme={theme}>
// <Icon src={extractPluginIcon(packageManifest)} />
// <Texts>
// <Line>
// <Name>{packageManifest.name}</Name>
// <Version>{packageManifest.version}</Version>
// </Line>
// <Line>
// <Description>{packageManifest.description}</Description>
// </Line>
// <Line>
// <Author>{extractPluginAuthor(packageManifest)}</Author>
// </Line>
// </Texts>
// </Wrapper>
// );
// }
// export default function PluginsList({ plugins }) {
// return (
// <>
// {plugins.map(packageManifest => (
// <PluginsListItem packageManifest={packageManifest} key={packageManifest.name} />
// ))}
// </>
// );
// }

View File

@@ -0,0 +1,74 @@
<script lang="ts" context="module">
const dbgateEnv = {
axios,
};
async function loadPlugins(pluginsDict, installedPlugins) {
const newPlugins = {};
for (const installed of installedPlugins || []) {
if (!_.keys(pluginsDict).includes(installed.name)) {
console.log('Loading module', installed.name);
const resp = await axios.request({
method: 'get',
url: 'plugins/script',
params: {
packageName: installed.name,
},
});
const module = eval(`${resp.data}; plugin`);
console.log('Loaded plugin', module);
const moduleContent = module.__esModule ? module.default : module;
if (moduleContent.initialize) moduleContent.initialize(dbgateEnv);
newPlugins[installed.name] = moduleContent;
}
}
return newPlugins;
}
function buildDrivers(plugins) {
const res = [];
for (const { content } of plugins) {
if (content.driver) res.push(content.driver);
if (content.drivers) res.push(...content.drivers);
}
return res;
}
export function buildExtensions(plugins) {
const extensions = {
plugins,
fileFormats: buildFileFormats(plugins),
drivers: buildDrivers(plugins),
};
return extensions;
}
</script>
<script lang="ts">
import _ from 'lodash';
import { extensions } from '../stores';
import axios from '../utility/axios';
import { useInstalledPlugins } from '../utility/metadataLoaders';
import { buildFileFormats } from './fileformats';
let pluginsDict = {};
const installedPlugins = useInstalledPlugins();
$: loadPlugins(pluginsDict, $installedPlugins).then(newPlugins => {
if (_.isEmpty(newPlugins)) return;
pluginsDict = _.pick(
{ ...pluginsDict, ...newPlugins },
$installedPlugins.map(y => y.name)
);
});
$: plugins = ($installedPlugins || [])
.map(manifest => ({
packageName: manifest.name,
manifest,
content: pluginsDict[manifest.name],
}))
.filter(x => x.content);
$: $extensions = buildExtensions(plugins);
</script>

View File

@@ -0,0 +1,34 @@
import { FileFormatDefinition } from 'dbgate-types';
const jsonlFormat = {
storageType: 'jsonl',
extension: 'jsonl',
name: 'JSON lines',
readerFunc: 'jsonLinesReader',
writerFunc: 'jsonLinesWriter',
};
export function buildFileFormats(plugins): FileFormatDefinition[] {
const res = [jsonlFormat];
for (const { content } of plugins) {
const { fileFormats } = content;
if (fileFormats) res.push(...fileFormats);
}
return res;
}
export function findFileFormat(extensions, storageType) {
return extensions.fileFormats.find(x => x.storageType == storageType);
}
export function getFileFormatDirections(format) {
if (!format) return [];
const res = [];
if (format.readerFunc) res.push('source');
if (format.writerFunc) res.push('target');
return res;
}
export function getDefaultFileFormat(extensions) {
return extensions.fileFormats.find(x => x.storageType == 'csv') || jsonlFormat;
}

View File

@@ -0,0 +1,21 @@
import _ from 'lodash';
export function extractPluginIcon(packageManifest) {
const { links } = packageManifest || {};
const { repository } = links || {};
const homepage = (links && links.homepage) || packageManifest.homepage;
const tested = repository || homepage || packageManifest.homepage;
if (tested) {
const match = tested.match(/https:\/\/github.com\/([^/]*)\/([^/]*)/);
if (match) {
return `https://raw.githubusercontent.com/${match[1]}/${match[2]}/master/icon.svg`;
}
}
// eslint-disable-next-line no-undef
return `${process.env.PUBLIC_URL}/unknown.svg`;
}
export function extractPluginAuthor(packageManifest) {
return _.isPlainObject(packageManifest.author) ? packageManifest.author.name : packageManifest.author;
}