mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-19 07:16:01 +00:00
193 lines
5.7 KiB
TypeScript
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);
|
|
}
|
|
}
|