mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge pull request #19 from dbeaver/feat-configuration-service
Feat configuration service
This commit is contained in:
@@ -55,14 +55,14 @@ type WebServiceConfig {
|
||||
}
|
||||
|
||||
type ServerConfig {
|
||||
name: String
|
||||
version: String
|
||||
name: String!
|
||||
version: String!
|
||||
supportsPredefinedConnections: Boolean
|
||||
supportsProvidedConnections: Boolean
|
||||
supportsCustomConnections: Boolean
|
||||
supportsConnectionBrowser: Boolean
|
||||
supportsWorkspaces: Boolean
|
||||
supportedLanguages: [ ServerLanguage ]
|
||||
supportedLanguages: [ ServerLanguage ]!
|
||||
services: [ WebServiceConfig ]
|
||||
productConfiguration: Object!
|
||||
}
|
||||
@@ -70,12 +70,12 @@ type ServerConfig {
|
||||
type SessionInfo {
|
||||
id: ID!
|
||||
|
||||
createTime: String
|
||||
lastAccessTime: String
|
||||
locale: String
|
||||
createTime: String!
|
||||
lastAccessTime: String!
|
||||
locale: String!
|
||||
|
||||
serverMessages: [ ServerMessage ]
|
||||
connections: [ ConnectionInfo ]
|
||||
connections: [ ConnectionInfo ]!
|
||||
}
|
||||
|
||||
####################################################
|
||||
|
||||
@@ -12,11 +12,14 @@ const modules = [
|
||||
|
||||
// The order of modules is important.
|
||||
// The module must be built before it is used in another module
|
||||
'/extensions',
|
||||
'/di',
|
||||
'/utils',
|
||||
'/eventsLog',
|
||||
|
||||
'/settings',
|
||||
'/product',
|
||||
'/plugin',
|
||||
'/theming',
|
||||
'/localization',
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ module.exports = (env, argv) => merge(commonConfig(env, argv), {
|
||||
dialogs: "./dialogs/index.ts",
|
||||
eventsLog: "./eventsLog/index.ts",
|
||||
localization: "./localization/index.ts",
|
||||
extensions: "./extensions/index.ts",
|
||||
plugin: "./plugin/index.ts",
|
||||
product: "./product/index.ts",
|
||||
// queries dir - ignore
|
||||
root: "./root/index.ts",
|
||||
sdk: "./sdk/index.ts",
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "@dbeaver/core/plugin",
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"main": "../dist/plugin",
|
||||
"module": "../dist/plugin",
|
||||
"types": "../dist/types/plugin"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "@dbeaver/core/product",
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"main": "../dist/product",
|
||||
"module": "../dist/product",
|
||||
"types": "../dist/types/product"
|
||||
}
|
||||
@@ -14,9 +14,11 @@ import {
|
||||
} from '@dbeaver/core/app';
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { ExceptionsCatcherService } from '@dbeaver/core/eventsLog';
|
||||
import { SessionService } from '@dbeaver/core/root';
|
||||
import { ThemeService } from '@dbeaver/core/theming';
|
||||
|
||||
import { SessionExpireService } from './dialogs';
|
||||
import { LocalizationService } from './localization';
|
||||
|
||||
/**
|
||||
* AppBootstrap.init() will be executed between first and second phase of App initialization,
|
||||
* when application has registered all dependencies but plugins did'nt initialized.
|
||||
@@ -27,11 +29,12 @@ import { ThemeService } from '@dbeaver/core/theming';
|
||||
export class AppBootstrap {
|
||||
|
||||
constructor(private exceptionsCatcherService: ExceptionsCatcherService,
|
||||
private sessionService: SessionService,
|
||||
private localizationService: LocalizationService,
|
||||
private themeService: ThemeService,
|
||||
private connectionDialogService: ConnectionDialogsService,
|
||||
private connectionsManager: ConnectionsManagerService,
|
||||
private logViewerMenuService: LogViewerMenuService,
|
||||
private sessionExpireService: SessionExpireService,
|
||||
private navigationTreeContextMenuService: NavigationTreeContextMenuService,
|
||||
private nodesManagerService: NodesManagerService,
|
||||
private navigationTabsService: NavigationTabsService,
|
||||
@@ -40,8 +43,9 @@ export class AppBootstrap {
|
||||
|
||||
async init() {
|
||||
this.exceptionsCatcherService.subscribe();
|
||||
this.sessionExpireService.subscribe();
|
||||
|
||||
await this.sessionService.init();
|
||||
await this.localizationService.init();
|
||||
await this.themeService.init();
|
||||
|
||||
this.connectionSchemaManagerService.registerCallbacks();
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { PluginManagerService } from '@dbeaver/core/plugin';
|
||||
|
||||
const defaultSettings = {
|
||||
'app.logViewer.refreshInterval': 3000,
|
||||
'app.logViewer.maxLogEntries': 1000,
|
||||
};
|
||||
|
||||
export type CoreSettings = typeof defaultSettings
|
||||
|
||||
@injectable()
|
||||
export class CoreSettingsService {
|
||||
|
||||
readonly settings = this.pluginManagerService.getPluginSettings('core', defaultSettings);
|
||||
|
||||
constructor(private pluginManagerService: PluginManagerService) { }
|
||||
}
|
||||
@@ -12,9 +12,9 @@ import styled, { css } from 'reshadow';
|
||||
import {
|
||||
Pane, ResizerControls, Split, splitHorizontalStyles, splitStyles,
|
||||
} from '@dbeaver/core/blocks';
|
||||
import { useController } from '@dbeaver/core/di';
|
||||
import { composes, useStyles } from '@dbeaver/core/theming';
|
||||
|
||||
import { useController } from '../di';
|
||||
import { NavigationTabsBar } from './shared/NavigationTabs/NavigationTabsBar';
|
||||
import { LogViewTab } from './shared/ToolsPanel/LogViewTab/LogViewTab';
|
||||
import { LogViewTabController } from './shared/ToolsPanel/LogViewTab/LogViewTabController';
|
||||
|
||||
@@ -11,7 +11,7 @@ import styled from 'reshadow';
|
||||
|
||||
import { Icon } from '@dbeaver/core/blocks';
|
||||
import { useService } from '@dbeaver/core/di';
|
||||
import { SessionService } from '@dbeaver/core/root';
|
||||
import { ServerService } from '@dbeaver/core/root';
|
||||
import { useStyles } from '@dbeaver/core/theming';
|
||||
|
||||
import { ConnectionSelector } from './ConnectionSchemaManager/ConnectionSelector/ConnectionSelector';
|
||||
@@ -23,8 +23,8 @@ import { topNavBarStyles } from './topNavBarStyles';
|
||||
declare const version: string; // declared in webpack DefinePlugin // todo move to enviroment?
|
||||
|
||||
export const TopNavBar = observer(function TopNavBar() {
|
||||
const sessionService = useService(SessionService);
|
||||
const title = `Frontend: ${version}\nBackend: ${sessionService.version}`;
|
||||
const serverService = useService(ServerService);
|
||||
const title = `Frontend: ${version}\nBackend: ${serverService.config.data?.version}`;
|
||||
|
||||
return styled(useStyles(topNavBarStyles))(
|
||||
<header>
|
||||
|
||||
+17
-16
@@ -10,13 +10,12 @@ import { computed, observable } from 'mobx';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { ConnectionShortInfo, SessionService } from '@dbeaver/core/root';
|
||||
import { SessionService } from '@dbeaver/core/root';
|
||||
import {
|
||||
ConnectionInfo,
|
||||
DataSourceInfo,
|
||||
DriverInfo,
|
||||
GraphQLService,
|
||||
NavGetStructContainersQuery,
|
||||
CachedResource,
|
||||
DatabaseObjectInfo,
|
||||
} from '@dbeaver/core/sdk';
|
||||
@@ -118,9 +117,16 @@ export class ConnectionsManagerService {
|
||||
}
|
||||
|
||||
async restoreConnections() {
|
||||
for (const connection of this.sessionService.getConnections()) {
|
||||
this.restoreConnection(connection);
|
||||
const config = await this.sessionService.session.load();
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: connections must be string[]
|
||||
for (const connection of config.connections) {
|
||||
await this.restoreConnection(connection);
|
||||
}
|
||||
await this.nodesManagerService.updateRootChildren();
|
||||
}
|
||||
|
||||
private async refreshObjectContainersAsync(
|
||||
@@ -130,7 +136,10 @@ export class ConnectionsManagerService {
|
||||
catalogId?: string,
|
||||
): Promise<Map<string, ObjectContainer[]>> {
|
||||
if (refresh || !data.has(connectionId)) {
|
||||
const { navGetStructContainers } = await this.loadSchemasAndCatalogs(connectionId, catalogId);
|
||||
const { navGetStructContainers } = await this.graphQLService.gql.navGetStructContainers({
|
||||
connectionId,
|
||||
catalogId,
|
||||
});
|
||||
data.set(connectionId, [...navGetStructContainers.schemaList, ...navGetStructContainers.catalogList]);
|
||||
}
|
||||
|
||||
@@ -149,18 +158,10 @@ export class ConnectionsManagerService {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this request returns either schemaList or catalogList. You never got both lists together
|
||||
*/
|
||||
private async loadSchemasAndCatalogs(connectionId: string, catalogId?: string): Promise<NavGetStructContainersQuery> {
|
||||
return this.graphQLService.gql.navGetStructContainers({ connectionId, catalogId });
|
||||
}
|
||||
private async restoreConnection(connection: Connection) {
|
||||
// TODO: Must be loaded based on connection id
|
||||
// const { connection } = await this.graphQLService.gql.connectionState({ id });
|
||||
|
||||
private restoreConnection(connectionInfo: ConnectionShortInfo) {
|
||||
const connection: Connection = {
|
||||
...connectionInfo,
|
||||
connected: true,
|
||||
};
|
||||
this.connectionsMap.set(connection.id, connection);
|
||||
this.onOpenConnection.next(connection);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { createExtension, isExtension, IExtension } from '../../../../extensions';
|
||||
import { createExtension, isExtension, IExtension } from '@dbeaver/core/extensions';
|
||||
|
||||
const connectionProviderSymbol = Symbol('@extension/ConnectionProvider');
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { createExtension, isExtension, IExtension } from '../../../../extensions';
|
||||
import { createExtension, isExtension, IExtension } from '@dbeaver/core/extensions';
|
||||
|
||||
const connectionSetterSymbol = Symbol('@extension/ConnectionSetter');
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
query connectionState($id: ID!) {
|
||||
connection: connectionState(id: $id) {
|
||||
id
|
||||
name
|
||||
driverId
|
||||
connected
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,9 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { IExtension } from '../../../extensions';
|
||||
import { Style } from '../../../theming';
|
||||
import { IExtension } from '@dbeaver/core/extensions';
|
||||
import { Style } from '@dbeaver/core/theming';
|
||||
|
||||
import { ITab } from './ITab';
|
||||
|
||||
export type TabHandlerTabProps<T = any> = {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { createExtension, isExtension, IExtension } from '../../../../extensions';
|
||||
import { createExtension, isExtension, IExtension } from '@dbeaver/core/extensions';
|
||||
|
||||
const objectCatalogProviderSymbol = Symbol('@extension/ObjectCatalogProvider');
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { createExtension, isExtension, IExtension } from '../../../../extensions';
|
||||
import { createExtension, isExtension, IExtension } from '@dbeaver/core/extensions';
|
||||
|
||||
const objectCatalogSetterSymbol = Symbol('@extension/ObjectCatalogSetter');
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { createExtension, isExtension, IExtension } from '../../../../extensions';
|
||||
import { createExtension, isExtension, IExtension } from '@dbeaver/core/extensions';
|
||||
|
||||
const objectSchemaProviderSymbol = Symbol('@extension/ObjectSchemaProvider');
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { createExtension, isExtension, IExtension } from '../../../../extensions';
|
||||
import { createExtension, isExtension, IExtension } from '@dbeaver/core/extensions';
|
||||
|
||||
const objectSchemaSetterSymbol = Symbol('@extension/ObjectSchemaSetter');
|
||||
|
||||
|
||||
@@ -11,16 +11,11 @@ import { action, observable } from 'mobx';
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { NotificationService } from '@dbeaver/core/eventsLog';
|
||||
import { GraphQLService } from '@dbeaver/core/sdk';
|
||||
import { SettingsService } from '@dbeaver/core/settings';
|
||||
import { uuid } from '@dbeaver/core/utils';
|
||||
|
||||
import { CoreSettingsService } from '../../../../CoreSettingsService';
|
||||
import { ILogEntry } from './ILogEntry';
|
||||
|
||||
const REFRESH_INTERVAL = 3000;
|
||||
const REFRESH_INTERVAL_TOKEN = 'core.app.logViewer.refreshInterval';
|
||||
const MAX_LOG_ENTRIES = 1000;
|
||||
const MAX_LOG_ENTRIES_TOKEN = 'core.app.logViewer.maxLogEntries';
|
||||
|
||||
@injectable()
|
||||
export class LogViewerService {
|
||||
|
||||
@@ -28,11 +23,9 @@ export class LogViewerService {
|
||||
|
||||
@observable private log: ILogEntry[] = [];
|
||||
private interval: any = null;
|
||||
private refreshInterval = this.settingsService.getProperty(REFRESH_INTERVAL_TOKEN, REFRESH_INTERVAL);
|
||||
private maxLogEntries = this.settingsService.getProperty(MAX_LOG_ENTRIES_TOKEN, MAX_LOG_ENTRIES);
|
||||
|
||||
constructor(private graphQLService: GraphQLService,
|
||||
private settingsService: SettingsService,
|
||||
private coreSettingsService: CoreSettingsService,
|
||||
private notificationService: NotificationService) {
|
||||
}
|
||||
|
||||
@@ -55,9 +48,10 @@ export class LogViewerService {
|
||||
return;
|
||||
}
|
||||
await this.updateLog();
|
||||
const refreshInterval = this.coreSettingsService.settings.getValue('app.logViewer.refreshInterval');
|
||||
this.interval = setInterval(() => {
|
||||
this.updateLog();
|
||||
}, this.refreshInterval);
|
||||
}, refreshInterval);
|
||||
}
|
||||
|
||||
stopLog() {
|
||||
@@ -84,14 +78,16 @@ export class LogViewerService {
|
||||
@action
|
||||
addNewEntries(entries: ILogEntry[]) {
|
||||
this.log.unshift(...entries.reverse());
|
||||
if (this.log.length > this.maxLogEntries) {
|
||||
this.log.splice(this.maxLogEntries, this.log.length - this.maxLogEntries);
|
||||
const maxLogEntries = this.coreSettingsService.settings.getValue('app.logViewer.maxLogEntries');
|
||||
if (this.log.length > maxLogEntries) {
|
||||
this.log.splice(maxLogEntries, this.log.length - maxLogEntries);
|
||||
}
|
||||
}
|
||||
|
||||
async loadLog(): Promise<ILogEntry[]> {
|
||||
const maxLogEntries = this.coreSettingsService.settings.getValue('app.logViewer.maxLogEntries');
|
||||
const { log } = await this.graphQLService.gql.readSessionLog({
|
||||
maxEntries: this.maxLogEntries,
|
||||
maxEntries: maxLogEntries,
|
||||
clearEntries: true,
|
||||
});
|
||||
const entries: ILogEntry[] = (log || []).map(item => ({
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
import { observer } from 'mobx-react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { useTranslate } from '../localization';
|
||||
import { useStyles, composes } from '../theming';
|
||||
import { useTranslate } from '@dbeaver/core/localization';
|
||||
import { useStyles, composes } from '@dbeaver/core/theming';
|
||||
|
||||
import { Button } from './Button';
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import styled, { css, use } from 'reshadow';
|
||||
|
||||
import { useStyles } from '../theming';
|
||||
import { useStyles } from '@dbeaver/core/theming';
|
||||
|
||||
const styles = css`
|
||||
label {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import { css } from 'reshadow';
|
||||
|
||||
import { composes } from '../../theming/themeUtils';
|
||||
import { composes } from '@dbeaver/core/theming';
|
||||
|
||||
export const loaderStyles = css`
|
||||
loader {
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
import { ButtonHTMLAttributes, PropsWithChildren } from 'react';
|
||||
|
||||
import { TLocalizationToken } from '@dbeaver/core/localization';
|
||||
|
||||
import { Style } from '../../theming/useStyles';
|
||||
import { Style } from '@dbeaver/core/theming';
|
||||
|
||||
export type MenuMod = 'primary' | 'surface' | 'secondary';
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import {
|
||||
GQLError, GraphQLService, EServerErrorCode
|
||||
} from '@dbeaver/core/sdk';
|
||||
|
||||
import { CommonDialogService } from '../CommonDialog/CommonDialogService';
|
||||
import { SessionExpiredDialog } from './SessionExpiredDialog';
|
||||
|
||||
@injectable()
|
||||
export class SessionExpireService {
|
||||
private isNotifiedAboutExpiredSession = false;
|
||||
|
||||
onSessionExpire = new Subject();
|
||||
constructor(
|
||||
private graphQLService: GraphQLService,
|
||||
private commonDialogService: CommonDialogService
|
||||
) {
|
||||
}
|
||||
|
||||
subscribe() {
|
||||
this.graphQLService.registerInterceptor(this.sessionExpiredInterceptor.bind(this));
|
||||
}
|
||||
|
||||
private async sessionExpiredInterceptor(request: Promise<any>): Promise<any> {
|
||||
try {
|
||||
return await request;
|
||||
} catch (exception) {
|
||||
if (exception instanceof GQLError
|
||||
&& exception.errorCode === EServerErrorCode.sessionExpired
|
||||
&& !this.isNotifiedAboutExpiredSession) {
|
||||
this.isNotifiedAboutExpiredSession = true;
|
||||
this.onSessionExpire.next();
|
||||
await this.commonDialogService.open(SessionExpiredDialog, null);
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -11,10 +11,12 @@ import { useCallback } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Button } from '@dbeaver/core/blocks';
|
||||
import { CommonDialogWrapper, DialogComponent } from '@dbeaver/core/dialogs';
|
||||
import { useTranslate } from '@dbeaver/core/localization';
|
||||
import { useStyles } from '@dbeaver/core/theming';
|
||||
|
||||
import { DialogComponent } from '../CommonDialog/CommonDialogService';
|
||||
import { CommonDialogWrapper } from '../CommonDialog/CommonDialogWrapper';
|
||||
|
||||
const styles = css`
|
||||
dialog-content {
|
||||
display: flex;
|
||||
@@ -13,3 +13,5 @@ export * from './Menu/models/ComputedMenuPanelModel';
|
||||
export * from './Menu/ContextMenu/ContextMenuService';
|
||||
export * from './Menu/ContextMenu/IContextMenuItem';
|
||||
export * from './Menu/ContextMenu/IMenuContext';
|
||||
|
||||
export * from './SessionExpire/SessionExpireService';
|
||||
|
||||
@@ -14,6 +14,7 @@ import { NotificationService } from '@dbeaver/core/eventsLog';
|
||||
import { GraphQLService, ServerLanguage } from '@dbeaver/core/sdk';
|
||||
import { SettingsService } from '@dbeaver/core/settings';
|
||||
|
||||
import { SessionService, ServerService } from '../root';
|
||||
import { Locale } from './Locale';
|
||||
import { TLocalizationToken } from './TLocalizationToken';
|
||||
|
||||
@@ -37,6 +38,8 @@ export class LocalizationService {
|
||||
private localeMap: Map<string, Locale> = new Map();
|
||||
|
||||
constructor(private notificationService: NotificationService,
|
||||
private sessionService: SessionService,
|
||||
private serverService: ServerService,
|
||||
private graphQLService: GraphQLService,
|
||||
private settingsService: SettingsService) {
|
||||
|
||||
@@ -78,13 +81,19 @@ export class LocalizationService {
|
||||
return locale && locale[token];
|
||||
}
|
||||
|
||||
async init(sessionLanguage: string | undefined, supportedLanguages: ServerLanguageShort[]) {
|
||||
this.supportedLanguages = supportedLanguages;
|
||||
async init() {
|
||||
const session = await this.sessionService.session.load();
|
||||
const config = await this.serverService.config.load();
|
||||
|
||||
if (!session || !config) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.supportedLanguages = config.supportedLanguages;
|
||||
|
||||
this.settingsService.registerSettings(this.settings, LANG_SETTINGS_KEY); // overwrite default value with settings
|
||||
if (sessionLanguage) {
|
||||
this.setCurrentLocale(sessionLanguage); // session language wins
|
||||
}
|
||||
this.setCurrentLocale(session.locale); // session language wins
|
||||
|
||||
await this.setLocale(this.getCurrentLanguage());
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,20 @@ import {
|
||||
SettingsMenuService, LogViewerService, LogViewerMenuService,
|
||||
} from '@dbeaver/core/app';
|
||||
import { PluginManifest } from '@dbeaver/core/di';
|
||||
import { CommonDialogService, ContextMenuService } from '@dbeaver/core/dialogs';
|
||||
import { CommonDialogService, ContextMenuService, SessionExpireService } from '@dbeaver/core/dialogs';
|
||||
import { NotificationService, ExceptionsCatcherService } from '@dbeaver/core/eventsLog';
|
||||
import { LocalizationService } from '@dbeaver/core/localization';
|
||||
import { SessionService } from '@dbeaver/core/root';
|
||||
import { PluginManagerService } from '@dbeaver/core/plugin';
|
||||
import { ProductManagerService, ProductSettingsService } from '@dbeaver/core/product';
|
||||
import {
|
||||
SessionService, ServerService, SessionSettingsService, ServerSettingsService
|
||||
} from '@dbeaver/core/root';
|
||||
import { EnvironmentService, GraphQLService } from '@dbeaver/core/sdk';
|
||||
import { LocalStorageSaveService, SettingsService } from '@dbeaver/core/settings';
|
||||
import { ThemeService } from '@dbeaver/core/theming';
|
||||
|
||||
import { CoreSettingsService } from './CoreSettingsService';
|
||||
|
||||
export const coreManifest: PluginManifest = {
|
||||
info: {
|
||||
name: 'DBeaver core',
|
||||
@@ -29,7 +35,14 @@ export const coreManifest: PluginManifest = {
|
||||
depends: [],
|
||||
|
||||
providers: [
|
||||
ProductSettingsService,
|
||||
ProductManagerService,
|
||||
PluginManagerService,
|
||||
ServerSettingsService,
|
||||
SessionSettingsService,
|
||||
CoreSettingsService,
|
||||
CommonDialogService,
|
||||
SessionExpireService,
|
||||
ConnectionDialogsService,
|
||||
ConnectionSchemaManagerService,
|
||||
ConnectionsManagerService,
|
||||
@@ -52,6 +65,7 @@ export const coreManifest: PluginManifest = {
|
||||
SettingsMenuService,
|
||||
SettingsService,
|
||||
ThemeService,
|
||||
ServerService,
|
||||
],
|
||||
|
||||
async initialize(services) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { ProductManagerService } from '@dbeaver/core/product';
|
||||
|
||||
import { PluginSettings } from './PluginSettings';
|
||||
|
||||
|
||||
@injectable()
|
||||
export class PluginManagerService {
|
||||
|
||||
constructor(private productManagerService: ProductManagerService) { }
|
||||
|
||||
getPluginSettings<T>(scope: string, defaults: T) {
|
||||
return new PluginSettings(this.productManagerService.settings, scope, defaults);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { ISettingsSource } from '@dbeaver/core/settings';
|
||||
|
||||
export class PluginSettings<T> implements ISettingsSource {
|
||||
constructor(
|
||||
private source: ISettingsSource,
|
||||
private scope: string,
|
||||
private defaults: T
|
||||
) {
|
||||
}
|
||||
|
||||
has<TKey extends keyof T>(key: TKey): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
getValue<TKey extends keyof T>(key: TKey): T[TKey] {
|
||||
if (this.source.has(this.scopedKey(key))) {
|
||||
return this.source.getValue(this.scopedKey(key));
|
||||
}
|
||||
|
||||
return this.defaults[key];
|
||||
}
|
||||
|
||||
setValue<TKey extends keyof T>(key: TKey, value: T[TKey]) {
|
||||
this.source.setValue(this.scopedKey(key), value);
|
||||
}
|
||||
|
||||
private scopedKey(key: string | number | symbol): string {
|
||||
return `${this.scope}.${String(key)}`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './PluginSettings';
|
||||
export * from './PluginManagerService';
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { ServerService } from '@dbeaver/core/root';
|
||||
import { parseJSONFlat } from '@dbeaver/core/utils';
|
||||
|
||||
import { ProductSettingsService } from './ProductSettingsService';
|
||||
|
||||
@injectable()
|
||||
export class ProductManagerService {
|
||||
|
||||
readonly settings = new ProductSettingsService(this.serverService.settings)
|
||||
|
||||
constructor(private serverService: ServerService) { }
|
||||
|
||||
setSettings(object: any) {
|
||||
|
||||
parseJSONFlat(
|
||||
object,
|
||||
this.settings.setSelfValue.bind(this.settings),
|
||||
undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { SettingsSource, ISettingsSource } from '@dbeaver/core/settings';
|
||||
|
||||
@injectable()
|
||||
export class ProductSettingsService extends SettingsSource {
|
||||
|
||||
constructor(fallback: ISettingsSource) {
|
||||
super(fallback);
|
||||
}
|
||||
|
||||
setValue(key: string, value: any) {
|
||||
this.fallback?.setValue(key, value);
|
||||
}
|
||||
|
||||
setSelfValue(key: string, value: string) {
|
||||
super.setValue(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './ProductManagerService';
|
||||
export * from './ProductSettingsService';
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { GraphQLService, ServerConfig, CachedResource } from '@dbeaver/core/sdk';
|
||||
import { parseJSONFlat } from '@dbeaver/core/utils';
|
||||
|
||||
import { ServerSettingsService } from './ServerSettingsService';
|
||||
import { SessionService } from './SessionService';
|
||||
|
||||
@injectable()
|
||||
export class ServerService {
|
||||
readonly config = new CachedResource(undefined, this.refreshConfigAsync.bind(this));
|
||||
readonly settings = new ServerSettingsService(this.sessionService.settings);
|
||||
|
||||
private lastConfig: any = null
|
||||
constructor(
|
||||
private graphQLService: GraphQLService,
|
||||
private sessionService: SessionService,
|
||||
) {
|
||||
}
|
||||
|
||||
private async refreshConfigAsync(data: ServerConfig | undefined): Promise<ServerConfig> {
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
const { serverConfig } = await this.graphQLService.gql.serverConfig();
|
||||
|
||||
if (serverConfig.productConfiguration !== this.lastConfig) {
|
||||
this.lastConfig = serverConfig.productConfiguration;
|
||||
this.settings.clear();
|
||||
parseJSONFlat(
|
||||
serverConfig.productConfiguration,
|
||||
this.settings.setSelfValue.bind(this.settings),
|
||||
undefined
|
||||
);
|
||||
}
|
||||
return serverConfig;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { SettingsSource, ISettingsSource } from '@dbeaver/core/settings';
|
||||
|
||||
@injectable()
|
||||
export class ServerSettingsService extends SettingsSource {
|
||||
|
||||
constructor(fallback: ISettingsSource) {
|
||||
super(fallback);
|
||||
}
|
||||
|
||||
setValue(key: string, value: string) {
|
||||
this.fallback?.setValue(key, value);
|
||||
}
|
||||
|
||||
setSelfValue(key: string, value: string) {
|
||||
super.setValue(key, value);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.store.clear();
|
||||
}
|
||||
}
|
||||
@@ -6,98 +6,31 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { computed } from 'mobx';
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { CommonDialogService } from '@dbeaver/core/dialogs';
|
||||
import { LocalizationService } from '@dbeaver/core/localization';
|
||||
import {
|
||||
ConnectionInfo, GQLError, GraphQLService, ServerLanguage, SessionInfo,
|
||||
ConnectionInfo, GraphQLService, SessionInfo, CachedResource,
|
||||
} from '@dbeaver/core/sdk';
|
||||
|
||||
import { EServerErrorCode } from '../sdk/EServerErrorCode';
|
||||
import { SessionExpiredDialog } from './SessionExpiredDialog';
|
||||
import { SessionSettingsService } from './SessionSettingsService';
|
||||
|
||||
export type ConnectionShortInfo = Pick<ConnectionInfo, 'id' | 'name' | 'driverId'>;
|
||||
export type SessionShortInfo = Pick<SessionInfo, 'locale' | 'connections'>;
|
||||
|
||||
export type Session = {
|
||||
name: string;
|
||||
version: string;
|
||||
language: string;
|
||||
supportedLanguages: Pick<ServerLanguage, 'isoCode' | 'nativeName'>[];
|
||||
connections: ConnectionShortInfo[];
|
||||
}
|
||||
|
||||
export type Server = {
|
||||
name: string;
|
||||
version: string;
|
||||
supportedLanguages: ConnectionShortInfo[];
|
||||
}
|
||||
export type SessionState = Pick<SessionInfo, 'id' | 'createTime' | 'lastAccessTime' | 'locale'> & {
|
||||
connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'connected' | 'driverId'>>;
|
||||
};
|
||||
|
||||
@injectable()
|
||||
export class SessionService {
|
||||
private session: Session = {
|
||||
name: '',
|
||||
version: '',
|
||||
language: 'en',
|
||||
supportedLanguages: [],
|
||||
connections: [],
|
||||
};
|
||||
readonly session = new CachedResource(undefined, this.refreshSessionStateAsync.bind(this));
|
||||
readonly settings = new SessionSettingsService('session_settings');
|
||||
|
||||
@computed get version() {
|
||||
return this.session.version;
|
||||
}
|
||||
constructor(private graphQLService: GraphQLService) {}
|
||||
|
||||
private isNotifiedAboutExpiredSession = false;
|
||||
|
||||
constructor(private graphQLService: GraphQLService,
|
||||
private localizationService: LocalizationService,
|
||||
private commonDialogService: CommonDialogService) {
|
||||
this.graphQLService.registerInterceptor(this.sessionExpiredInterceptor.bind(this));
|
||||
}
|
||||
|
||||
getConnections(): ConnectionShortInfo[] {
|
||||
return this.session.connections;
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
this.session = await this.fetchCurrentSession();
|
||||
|
||||
this.localizationService.init(this.session.language, this.session.supportedLanguages);
|
||||
|
||||
}
|
||||
|
||||
private async sessionExpiredInterceptor(request: Promise<any>): Promise<any> {
|
||||
try {
|
||||
return await request;
|
||||
} catch (exception) {
|
||||
if (exception instanceof GQLError
|
||||
&& exception.errorCode === EServerErrorCode.sessionExpired
|
||||
&& !this.isNotifiedAboutExpiredSession) {
|
||||
this.isNotifiedAboutExpiredSession = true;
|
||||
await this.commonDialogService.open(SessionExpiredDialog, null);
|
||||
}
|
||||
throw exception;
|
||||
private async refreshSessionStateAsync(data: SessionState | undefined): Promise<SessionState> {
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
private async fetchCurrentSession(): Promise<Session> {
|
||||
const { serverConfig } = await this.graphQLService.gql.serverConfig();
|
||||
const sessionInfo = await this.openNewSession();
|
||||
const { session } = await this.graphQLService.gql.openSession();
|
||||
|
||||
const session: Session = {
|
||||
name: serverConfig.name || 'WHERE IS A NAME',
|
||||
version: serverConfig.version || 'WHERE IS A VERSION',
|
||||
language: sessionInfo.locale || 'en',
|
||||
supportedLanguages: serverConfig.supportedLanguages,
|
||||
connections: sessionInfo.connections || [],
|
||||
};
|
||||
return session;
|
||||
}
|
||||
|
||||
private async openNewSession(): Promise<SessionShortInfo> {
|
||||
const response = await this.graphQLService.gql.openSession();
|
||||
return response.session;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@dbeaver/core/di';
|
||||
import { SettingsSource } from '@dbeaver/core/settings';
|
||||
|
||||
@injectable()
|
||||
export class SessionSettingsService extends SettingsSource {
|
||||
|
||||
constructor(private localStorageKey: string) {
|
||||
super();
|
||||
const state = localStorage.getItem(this.localStorageKey);
|
||||
if (state) {
|
||||
this.store = JSON.parse(state);
|
||||
}
|
||||
}
|
||||
|
||||
setValue(key: string, value: string) {
|
||||
super.setValue(key, value);
|
||||
localStorage.setItem(this.localStorageKey, JSON.stringify(this.store));
|
||||
}
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
export * from './SessionService';
|
||||
export * from './ServerService';
|
||||
export * from './ServerSettingsService';
|
||||
export * from './SessionSettingsService';
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
mutation openSession {
|
||||
session: openSession {
|
||||
id
|
||||
createTime
|
||||
lastAccessTime
|
||||
locale
|
||||
connections {
|
||||
id
|
||||
name,
|
||||
name
|
||||
driverId
|
||||
connected
|
||||
}
|
||||
locale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,17 @@ query serverConfig {
|
||||
serverConfig {
|
||||
name
|
||||
version
|
||||
productConfiguration
|
||||
supportsPredefinedConnections
|
||||
supportsProvidedConnections
|
||||
supportsCustomConnections
|
||||
supportsConnectionBrowser
|
||||
supportsWorkspaces
|
||||
supportedLanguages {
|
||||
isoCode
|
||||
displayName
|
||||
nativeName
|
||||
}
|
||||
productConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
query sessionState {
|
||||
sessionState {
|
||||
id
|
||||
createTime
|
||||
lastAccessTime
|
||||
locale
|
||||
connections {
|
||||
id
|
||||
name,
|
||||
name
|
||||
driverId
|
||||
connected
|
||||
}
|
||||
locale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,3 +4,4 @@ export * from './sdk';
|
||||
export * from './GQLError';
|
||||
export * from './ServerInternalError';
|
||||
export * from './CachedResource';
|
||||
export * from './EServerErrorCode';
|
||||
|
||||
@@ -24,6 +24,11 @@ export type AsyncTaskInfo = {
|
||||
status?: Maybe<Scalars["String"]>;
|
||||
error?: Maybe<ServerError>;
|
||||
result?: Maybe<SqlExecuteInfo>;
|
||||
/**
|
||||
* Task result.
|
||||
* Can be some kind of identifier to obtain real result using another API function
|
||||
*/
|
||||
taskResult?: Maybe<Scalars["Object"]>;
|
||||
};
|
||||
|
||||
export type AsyncTaskResult = SqlExecuteInfo;
|
||||
@@ -411,14 +416,14 @@ export type QueryMetadataGetNodeDdlArgs = {
|
||||
};
|
||||
|
||||
export type ServerConfig = {
|
||||
name?: Maybe<Scalars["String"]>;
|
||||
version?: Maybe<Scalars["String"]>;
|
||||
name: Scalars["String"];
|
||||
version: Scalars["String"];
|
||||
supportsPredefinedConnections?: Maybe<Scalars["Boolean"]>;
|
||||
supportsProvidedConnections?: Maybe<Scalars["Boolean"]>;
|
||||
supportsCustomConnections?: Maybe<Scalars["Boolean"]>;
|
||||
supportsConnectionBrowser?: Maybe<Scalars["Boolean"]>;
|
||||
supportsWorkspaces?: Maybe<Scalars["Boolean"]>;
|
||||
supportedLanguages?: Maybe<Array<Maybe<ServerLanguage>>>;
|
||||
supportedLanguages: Array<Maybe<ServerLanguage>>;
|
||||
services?: Maybe<Array<Maybe<WebServiceConfig>>>;
|
||||
productConfiguration: Scalars["Object"];
|
||||
};
|
||||
@@ -443,11 +448,11 @@ export type ServerMessage = {
|
||||
|
||||
export type SessionInfo = {
|
||||
id: Scalars["ID"];
|
||||
createTime?: Maybe<Scalars["String"]>;
|
||||
lastAccessTime?: Maybe<Scalars["String"]>;
|
||||
locale?: Maybe<Scalars["String"]>;
|
||||
createTime: Scalars["String"];
|
||||
lastAccessTime: Scalars["String"];
|
||||
locale: Scalars["String"];
|
||||
serverMessages?: Maybe<Array<Maybe<ServerMessage>>>;
|
||||
connections?: Maybe<Array<Maybe<ConnectionInfo>>>;
|
||||
connections: Array<Maybe<ConnectionInfo>>;
|
||||
};
|
||||
|
||||
export type SqlCompletionProposal = {
|
||||
@@ -562,6 +567,16 @@ export type CloseConnectionMutationVariables = {
|
||||
|
||||
export type CloseConnectionMutation = Pick<Mutation, "closeConnection">;
|
||||
|
||||
export type ConnectionStateQueryVariables = {
|
||||
id: Scalars["ID"];
|
||||
};
|
||||
|
||||
export type ConnectionStateQuery = {
|
||||
connection: Maybe<
|
||||
Pick<ConnectionInfo, "id" | "name" | "driverId" | "connected">
|
||||
>;
|
||||
};
|
||||
|
||||
export type CreateConnectionMutationVariables = {
|
||||
config: ConnectionConfig;
|
||||
};
|
||||
@@ -1094,9 +1109,9 @@ export type OpenSessionMutationVariables = {};
|
||||
|
||||
export type OpenSessionMutation = {
|
||||
session: Maybe<
|
||||
Pick<SessionInfo, "locale"> & {
|
||||
connections: Maybe<
|
||||
Array<Maybe<Pick<ConnectionInfo, "id" | "name" | "driverId">>>
|
||||
Pick<SessionInfo, "id" | "createTime" | "lastAccessTime" | "locale"> & {
|
||||
connections: Array<
|
||||
Maybe<Pick<ConnectionInfo, "id" | "name" | "driverId" | "connected">>
|
||||
>;
|
||||
}
|
||||
>;
|
||||
@@ -1106,9 +1121,19 @@ export type ServerConfigQueryVariables = {};
|
||||
|
||||
export type ServerConfigQuery = {
|
||||
serverConfig: Maybe<
|
||||
Pick<ServerConfig, "name" | "version"> & {
|
||||
supportedLanguages: Maybe<
|
||||
Array<Maybe<Pick<ServerLanguage, "isoCode" | "nativeName">>>
|
||||
Pick<
|
||||
ServerConfig,
|
||||
| "name"
|
||||
| "version"
|
||||
| "productConfiguration"
|
||||
| "supportsPredefinedConnections"
|
||||
| "supportsProvidedConnections"
|
||||
| "supportsCustomConnections"
|
||||
| "supportsConnectionBrowser"
|
||||
| "supportsWorkspaces"
|
||||
> & {
|
||||
supportedLanguages: Array<
|
||||
Maybe<Pick<ServerLanguage, "isoCode" | "displayName" | "nativeName">>
|
||||
>;
|
||||
}
|
||||
>;
|
||||
@@ -1118,9 +1143,9 @@ export type SessionStateQueryVariables = {};
|
||||
|
||||
export type SessionStateQuery = {
|
||||
sessionState: Maybe<
|
||||
Pick<SessionInfo, "locale"> & {
|
||||
connections: Maybe<
|
||||
Array<Maybe<Pick<ConnectionInfo, "id" | "name" | "driverId">>>
|
||||
Pick<SessionInfo, "id" | "createTime" | "lastAccessTime" | "locale"> & {
|
||||
connections: Array<
|
||||
Maybe<Pick<ConnectionInfo, "id" | "name" | "driverId" | "connected">>
|
||||
>;
|
||||
}
|
||||
>;
|
||||
@@ -1153,6 +1178,16 @@ export const CloseConnectionDocument = gql`
|
||||
closeConnection(id: $id)
|
||||
}
|
||||
`;
|
||||
export const ConnectionStateDocument = gql`
|
||||
query connectionState($id: ID!) {
|
||||
connection: connectionState(id: $id) {
|
||||
id
|
||||
name
|
||||
driverId
|
||||
connected
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const CreateConnectionDocument = gql`
|
||||
mutation createConnection($config: ConnectionConfig!) {
|
||||
createConnection(config: $config) {
|
||||
@@ -1618,12 +1653,16 @@ export const UpdateResultsDataDocument = gql`
|
||||
export const OpenSessionDocument = gql`
|
||||
mutation openSession {
|
||||
session: openSession {
|
||||
id
|
||||
createTime
|
||||
lastAccessTime
|
||||
locale
|
||||
connections {
|
||||
id
|
||||
name
|
||||
driverId
|
||||
connected
|
||||
}
|
||||
locale
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -1632,22 +1671,34 @@ export const ServerConfigDocument = gql`
|
||||
serverConfig {
|
||||
name
|
||||
version
|
||||
productConfiguration
|
||||
supportsPredefinedConnections
|
||||
supportsProvidedConnections
|
||||
supportsCustomConnections
|
||||
supportsConnectionBrowser
|
||||
supportsWorkspaces
|
||||
supportedLanguages {
|
||||
isoCode
|
||||
displayName
|
||||
nativeName
|
||||
}
|
||||
productConfiguration
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const SessionStateDocument = gql`
|
||||
query sessionState {
|
||||
sessionState {
|
||||
id
|
||||
createTime
|
||||
lastAccessTime
|
||||
locale
|
||||
connections {
|
||||
id
|
||||
name
|
||||
driverId
|
||||
connected
|
||||
}
|
||||
locale
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -1674,6 +1725,14 @@ export function getSdk(client: GraphQLClient) {
|
||||
variables,
|
||||
);
|
||||
},
|
||||
connectionState(
|
||||
variables: ConnectionStateQueryVariables,
|
||||
): Promise<ConnectionStateQuery> {
|
||||
return client.request<ConnectionStateQuery>(
|
||||
print(ConnectionStateDocument),
|
||||
variables,
|
||||
);
|
||||
},
|
||||
createConnection(
|
||||
variables: CreateConnectionMutationVariables,
|
||||
): Promise<CreateConnectionMutation> {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
export interface ISettingsSource {
|
||||
has(key: any): boolean;
|
||||
getValue(key: any): any | undefined;
|
||||
setValue(key: any, value: any): void;
|
||||
}
|
||||
@@ -10,28 +10,10 @@ import { injectable } from '@dbeaver/core/di';
|
||||
|
||||
import { LocalStorageSaveService } from './LocalStorageSaveService';
|
||||
|
||||
const PLUGIN_SETTINGS_KEY = 'pluginSettings';
|
||||
|
||||
@injectable()
|
||||
export class SettingsService {
|
||||
|
||||
private properties = new Map<string, any>();
|
||||
|
||||
constructor(private localStorageSaveService: LocalStorageSaveService) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param name - expected in format {plugin-id}.{scope-id}.{property-name}, default scope-id = main.
|
||||
* @param defaultValue
|
||||
*/
|
||||
getProperty<T>(name: string, defaultValue: T): T {
|
||||
if (this.properties.has(name)) {
|
||||
return this.properties.get(name) as T;
|
||||
}
|
||||
this.properties.set(name, defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
constructor(private localStorageSaveService: LocalStorageSaveService) { }
|
||||
|
||||
/**
|
||||
* if autosaved value exits the settings object will be populated with this value
|
||||
@@ -39,6 +21,6 @@ export class SettingsService {
|
||||
* @param settings - observable object expected
|
||||
*/
|
||||
registerSettings<T extends object>(settings: T, key: string): void {
|
||||
this.localStorageSaveService.withAutoSave(settings, PLUGIN_SETTINGS_KEY);
|
||||
this.localStorageSaveService.withAutoSave(settings, key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { ISettingsSource } from './ISettingsSource';
|
||||
|
||||
export class SettingsSource implements ISettingsSource {
|
||||
protected store = new Map<string, any>()
|
||||
|
||||
constructor(protected fallback?: ISettingsSource) {}
|
||||
|
||||
has(key: string): boolean {
|
||||
if (this.store.has(key)) {
|
||||
return true;
|
||||
}
|
||||
return !!this.fallback?.has(key);
|
||||
}
|
||||
getValue(key: string): any | undefined {
|
||||
if (this.fallback?.has(key)) {
|
||||
return this.fallback.getValue(key);
|
||||
}
|
||||
return this.store.get(key);
|
||||
}
|
||||
setValue(key: string, value: any) {
|
||||
this.store.set(key, value);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
export * from './SettingsService';
|
||||
export * from './LocalStorageSaveService';
|
||||
export * from './SettingsSource';
|
||||
export * from './ISettingsSource';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './OrderedMap';
|
||||
export * from './uuid';
|
||||
export * from './parseJSONFlat';
|
||||
|
||||
export * from './Promises/CancellablePromise';
|
||||
export * from './Promises/Deferred';
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
export function parseJSONFlat(
|
||||
object: any,
|
||||
setValue: (key: string, value: any) => void,
|
||||
scope?: string
|
||||
) {
|
||||
if (typeof object === 'object') {
|
||||
for (const [key, value] of Object.entries<any>(object)) {
|
||||
parseJSONFlat(value, setValue, `${scope ? `${scope}.` : ''}${key}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (scope) {
|
||||
setValue(scope, object);
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,9 @@ module.exports = (env, argv) => merge(commonConfig(env, argv), {
|
||||
"@dbeaver/core/settings": path.resolve(__dirname, "../../../core/src/settings"),
|
||||
"@dbeaver/core/theming": path.resolve(__dirname, "../../../core/src/theming"),
|
||||
"@dbeaver/core/utils": path.resolve(__dirname, "../../../core/src/utils"),
|
||||
"@dbeaver/core/extensions": path.resolve(__dirname, "../../../core/src/extensions"),
|
||||
"@dbeaver/core/product": path.resolve(__dirname, "../../../core/src/product"),
|
||||
"@dbeaver/core/plugin": path.resolve(__dirname, "../../../core/src/plugin"),
|
||||
|
||||
// rewrite imports for unnecessary work in `web/src/libs/sdk.ts`
|
||||
'graphql-tag': path.join(__dirname, '../../fix-gql.js'),
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
"@dbeaver/core/sdk": ["packages/core/src/sdk"],
|
||||
"@dbeaver/core/settings": ["packages/core/src/settings"],
|
||||
"@dbeaver/core/theming": ["packages/core/src/theming"],
|
||||
"@dbeaver/core/utils": ["packages/core/src/utils"]
|
||||
"@dbeaver/core/utils": ["packages/core/src/utils"],
|
||||
"@dbeaver/core/extensions": ["packages/core/src/extensions"],
|
||||
"@dbeaver/core/plugin": ["packages/core/src/plugin"],
|
||||
"@dbeaver/core/product": ["packages/core/src/product"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user