Files
dbgate/packages/web/src/utility/openElectronFile.ts
2022-05-19 14:59:42 +02:00

193 lines
5.7 KiB
TypeScript

import { showModal } from '../modals/modalTools';
import { get } from 'svelte/store';
import newQuery from '../query/newQuery';
import ImportExportModal from '../modals/ImportExportModal.svelte';
import getElectron from './getElectron';
import { currentDatabase, extensions, getCurrentDatabase } from '../stores';
import { getUploadListener } from './uploadFiles';
import getConnectionLabel, { getDatabaseFileLabel } from './getConnectionLabel';
import { apiCall } from './api';
import openNewTab from './openNewTab';
import { SAVED_FILE_HANDLERS } from '../appobj/SavedFileAppObject.svelte';
import _ from 'lodash';
export function canOpenByElectron(file, extensions) {
if (!file) return false;
const nameLower = file.toLowerCase();
if (nameLower.endsWith('.sql')) return true;
if (nameLower.endsWith('.diagram')) return true;
if (nameLower.endsWith('.db') || nameLower.endsWith('.sqlite') || nameLower.endsWith('.sqlite3')) return true;
for (const format of extensions.fileFormats) {
if (nameLower.endsWith(`.${format.extension}`)) return true;
if (format.extensions?.find(ext => nameLower.endsWith(`.${ext}`))) return true;
}
return false;
}
export async function openSqliteFile(filePath) {
const defaultDatabase = getDatabaseFileLabel(filePath);
const resp = await apiCall('connections/save', {
_id: undefined,
databaseFile: filePath,
engine: 'sqlite@dbgate-plugin-sqlite',
singleDatabase: true,
defaultDatabase,
});
currentDatabase.set({
connection: resp,
name: getDatabaseFileLabel(filePath),
});
}
function getFileEncoding(filePath, fs) {
var buf = Buffer.alloc(5);
var fd = fs.openSync(filePath, 'r');
fs.readSync(fd, buf, 0, 5, 0);
fs.closeSync(fd);
// https://en.wikipedia.org/wiki/Byte_order_mark
let e = null;
if (!e && buf[0] === 0xef && buf[1] === 0xbb && buf[2] === 0xbf) e = 'utf8';
if (!e && buf[0] === 0xfe && buf[1] === 0xff) e = 'utf16be';
if (!e && buf[0] === 0xff && buf[1] === 0xfe) e = 'utf16le';
if (!e) e = 'ascii';
return e;
}
function openElectronJsonLinesFile(filePath, parsed) {
openNewTab({
title: parsed.name,
tooltip: filePath,
icon: 'img archive',
tabComponent: 'ArchiveFileTab',
props: {
jslid: `file://${filePath}`,
},
});
}
async function openSavedElectronFile(filePath, parsed, folder) {
const handler = SAVED_FILE_HANDLERS[folder];
const resp = await apiCall('files/load-from', { filePath, format: handler.format });
const connProps: any = {};
let tooltip = undefined;
const db = getCurrentDatabase();
if (handler.currentConnection) {
const connection = db?.connection || {};
const database = db?.name;
connProps.conid = db?.connection?._id;
connProps.database = database;
tooltip = `${getConnectionLabel(connection)}\n${database}`;
}
openNewTab(
{
title: parsed.name,
icon: handler.icon,
tabComponent: handler.tabComponent,
tooltip,
props: {
savedFile: null,
savedFolder: null,
savedFilePath: filePath,
savedFormat: handler.format,
...connProps,
},
},
{ editor: resp }
);
}
export function openElectronFileCore(filePath, extensions) {
const nameLower = filePath.toLowerCase();
const path = window.require('path');
const fs = window.require('fs');
const parsed = path.parse(filePath);
const uploadListener = getUploadListener();
if (nameLower.endsWith('.sql')) {
const encoding = getFileEncoding(filePath, fs);
const data = fs.readFileSync(filePath, { encoding });
newQuery({
title: parsed.name,
initialData: data,
// @ts-ignore
savedFilePath: filePath,
savedFormat: 'text',
});
return;
}
if (nameLower.endsWith('.db') || nameLower.endsWith('.sqlite') || nameLower.endsWith('.sqlite')) {
openSqliteFile(filePath);
return;
}
if (nameLower.endsWith('.jsonl') || nameLower.endsWith('.ndjson')) {
openElectronJsonLinesFile(filePath, parsed);
return;
}
if (nameLower.endsWith('.diagram')) {
openSavedElectronFile(filePath, parsed, 'diagrams');
return;
}
for (const format of extensions.fileFormats) {
if (nameLower.endsWith(`.${format.extension}`)) {
if (uploadListener) {
uploadListener({
filePath,
storageType: format.storageType,
shortName: parsed.name,
});
} else {
showModal(ImportExportModal, {
openedFile: {
filePath,
storageType: format.storageType,
shortName: parsed.name,
},
importToCurrentTarget: true,
initialValues: {
sourceStorageType: format.storageType,
},
});
}
}
}
}
function getFileFormatFilters(extensions) {
return extensions.fileFormats
.filter(x => x.readerFunc)
.map(x => ({ name: x.name, extensions: x.extensions || [x.extension] }));
}
function getFileFormatExtensions(extensions) {
return _.flatten(extensions.fileFormats.filter(x => x.readerFunc).map(x => x.extensions || [x.extension]));
}
export async function openElectronFile() {
const electron = getElectron();
const ext = get(extensions);
const filePaths = await electron.showOpenDialog({
filters: [
{
name: `All supported files`,
extensions: ['sql', 'sqlite', 'db', 'sqlite3', 'diagram', ...getFileFormatExtensions(ext)],
},
{ name: `SQL files`, extensions: ['sql'] },
{ name: `Diagram files`, extensions: ['diagram'] },
{ name: `SQLite database`, extensions: ['sqlite', 'db', 'sqlite3'] },
...getFileFormatFilters(ext),
],
properties: ['showHiddenFiles', 'openFile'],
});
const filePath = filePaths && filePaths[0];
if (canOpenByElectron(filePath, ext)) {
openElectronFileCore(filePath, ext);
}
}