refactor: update connection behavior

CB-176
This commit is contained in:
Wroud
2020-07-08 21:25:12 +03:00
parent dcbafa3fb5
commit a526792e06
29 changed files with 606 additions and 93 deletions
@@ -238,7 +238,7 @@ type ConnectionInfo {
authNeeded: Boolean!
authModel: ID
authProperties: [ObjectPropertyInfo!]
authProperties: [ObjectPropertyInfo!]!
# Supported features (provided etc)
features: [ String! ]!
@@ -25,6 +25,7 @@ export function useNavigationTree(nodeId: string, parentId: string) {
const navNodeManagerService = useService(NavNodeManagerService);
const [isExpanded, switchExpand] = useState(false);
const [isSelected, switchSelect] = useState(false);
const [isExpanding, setExpanding] = useState(false);
const { node, isOutdated } = useNode(nodeId);
const children = useChildren(nodeId);
@@ -52,7 +53,9 @@ export function useNavigationTree(nodeId: string, parentId: string) {
const handleExpand = useCallback(
async () => {
if (!isExpandedFiltered) {
setExpanding(true);
const state = await navigationTreeService.loadNestedNodes(nodeId);
setExpanding(false);
if (!state) {
switchExpand(false);
return;
@@ -82,9 +85,15 @@ export function useNavigationTree(nodeId: string, parentId: string) {
useEffect(() => {
if (isExpandedFiltered && children.isOutdated && !children.isLoading && children.isLoaded && !isOutdated) {
setExpanding(true);
navigationTreeService
.loadNestedNodes(nodeId)
.then(state => !state && switchExpand(false));
.then((state) => {
setExpanding(false);
if (!state) {
switchExpand(false);
}
});
}
}, [isExpandedFiltered, children.isOutdated, children.isLoading, children.children, isOutdated, nodeId]);
@@ -106,7 +115,7 @@ export function useNavigationTree(nodeId: string, parentId: string) {
icon,
isExpanded: isExpandedFiltered,
isLoaded,
isLoading: children.isLoading,
isLoading: children.isLoading || isExpanding,
isExpandable,
isSelected,
hasChildren,
@@ -12,6 +12,7 @@ import { Subject, Observable } from 'rxjs';
import { injectable } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { ConnectionAuthService } from '../shared/ConnectionsManager/ConnectionAuthService';
import { ConnectionsManagerService } from '../shared/ConnectionsManager/ConnectionsManagerService';
import { EObjectFeature } from '../shared/NodesManager/EObjectFeature';
import { ROOT_NODE_PATH } from '../shared/NodesManager/NavNodeInfoResource';
@@ -28,7 +29,8 @@ export class NavigationTreeService {
constructor(
private navNodeManagerService: NavNodeManagerService,
private notificationService: NotificationService,
private connectionsManagerService: ConnectionsManagerService
private connectionsManagerService: ConnectionsManagerService,
private connectionAuthService: ConnectionAuthService
) {
this.nodeSelectSubject = new Subject();
this.onNodeSelect = this.nodeSelectSubject.asObservable();
@@ -36,14 +38,12 @@ export class NavigationTreeService {
async loadNestedNodes(id = ROOT_NODE_PATH) {
try {
await this.navNodeManagerService.loadTree(id);
const node = this.navNodeManagerService.getNode(id);
if (node?.objectFeatures.includes(EObjectFeature.dataSource)) {
await this.connectionsManagerService.refreshConnectionInfoAsync(
NodeManagerUtils.connectionNodeIdToConnectionId(id)
);
await this.connectionAuthService.auth(NodeManagerUtils.connectionNodeIdToConnectionId(id));
}
await this.navNodeManagerService.refreshTree(id);
return true;
} catch (exception) {
this.notificationService.logException(exception);
+2
View File
@@ -8,9 +8,11 @@ export * from './TopNavBar/MainMenu/MainMenuService';
export * from './TopNavBar/SettingsMenu/SettingsMenuService';
export * from './TopNavBar/ConnectionSchemaManager/ConnectionSchemaManagerService';
export * from './TopNavBar/TopNavBarService';
export * from './shared/ConnectionsManager/ConnectionAuthService';
export * from './shared/ConnectionsManager/ConnectionInfoResource';
export * from './shared/ConnectionsManager/ConnectionsManagerService';
export * from './shared/ConnectionsManager/ContainerResource';
export * from './shared/ConnectionsManager/DatabaseAuthModelsResource';
export * from './shared/ConnectionsManager/DBDriverResource';
export * from './shared/ConnectionsManager/ConnectionDialogsService';
export * from './shared/ConnectionsManager/extensions/IConnectionProvider';
@@ -0,0 +1,44 @@
/*
* 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 '@cloudbeaver/core-di';
import { ConnectionInfoResource } from './ConnectionInfoResource';
import { ConnectionsManagerService } from './ConnectionsManagerService';
@injectable()
export class ConnectionAuthService {
constructor(
private connectionManagerService: ConnectionsManagerService,
private connectionInfoResource: ConnectionInfoResource
) {}
async auth(connectionId: string) {
let connection = this.connectionInfoResource.get(connectionId);
if (!connection?.connected) {
connection = await this.connectionInfoResource.refresh(connectionId);
} else {
return;
}
if (connection.connected) {
return;
}
if (connection.authNeeded) {
const properties = await this.connectionInfoResource.loadAuthModel(connectionId);
// TODO: authorize dialog
// init with credentials
// await this.connectionInfoResource.init(connectionId);
} else {
await this.connectionInfoResource.init(connectionId);
}
}
}
@@ -7,17 +7,15 @@
*/
import { injectable } from '@cloudbeaver/core-di';
import {
ContextMenuService,
IContextMenuItem,
IMenuContext,
} from '@cloudbeaver/core-dialogs';
import { ContextMenuService, IMenuContext } from '@cloudbeaver/core-dialogs';
import { NavigationTreeContextMenuService } from '../../NavigationTree/NavigationTreeContextMenuService';
import { EMainMenu, MainMenuService } from '../../TopNavBar/MainMenu/MainMenuService';
import { NavNode } from '../NodesManager/EntityTypes';
import { EObjectFeature } from '../NodesManager/EObjectFeature';
import { NodeManagerUtils } from '../NodesManager/NodeManagerUtils';
import { ConnectionsManagerService } from './ConnectionsManagerService';
import { EConnectionFeature } from './EConnectionFeature';
@injectable()
export class ConnectionDialogsService {
@@ -50,19 +48,44 @@ export class ConnectionDialogsService {
}
);
const closeConnection: IContextMenuItem<NavNode> = {
id: 'closeConnection',
isPresent(context) {
return context.contextType === NavigationTreeContextMenuService.nodeContextType
&& !!context.data.objectFeatures.includes(EObjectFeature.dataSource);
},
title: 'Disconnect',
onClick: (context: IMenuContext<NavNode>) => {
const node = context.data;
this.connectionsManagerService.closeNavNodeConnectionAsync(node.id);
},
};
this.contextMenuService.addMenuItem<NavNode>(
this.contextMenuService.getRootMenuToken(),
{
id: 'closeConnection',
isPresent: (context: IMenuContext<NavNode>) => {
const connectionId = NodeManagerUtils.connectionNodeIdToConnectionId(context.data.id);
const connection = this.connectionsManagerService.getConnectionById(connectionId);
this.contextMenuService.addMenuItem<NavNode>(this.contextMenuService.getRootMenuToken(), closeConnection);
return context.contextType === NavigationTreeContextMenuService.nodeContextType
&& !!context.data.objectFeatures.includes(EObjectFeature.dataSource)
&& !!connection?.connected;
},
title: 'Disconnect',
onClick: (context: IMenuContext<NavNode>) => {
const node = context.data;
this.connectionsManagerService.closeNavNodeConnectionAsync(node.id);
},
}
);
this.contextMenuService.addMenuItem<NavNode>(
this.contextMenuService.getRootMenuToken(),
{
id: 'deleteConnection',
isPresent: (context: IMenuContext<NavNode>) => {
const connectionId = NodeManagerUtils.connectionNodeIdToConnectionId(context.data.id);
const connection = this.connectionsManagerService.getConnectionById(connectionId);
return context.contextType === NavigationTreeContextMenuService.nodeContextType
&& !!context.data.objectFeatures.includes(EObjectFeature.dataSource)
&& !!connection?.features.includes(EConnectionFeature.temporary);
},
title: 'Delete',
onClick: (context: IMenuContext<NavNode>) => {
const node = context.data;
this.connectionsManagerService.deleteNavNodeConnectionAsync(node.id);
},
}
);
}
}
@@ -11,9 +11,10 @@ import {
ConnectionInfo,
GraphQLService,
CachedMapResource,
ObjectPropertyInfo
} from '@cloudbeaver/core-sdk';
export type Connection = Pick<ConnectionInfo, 'id' | 'name' | 'connected' | 'driverId' | 'features'>
export type Connection = Pick<ConnectionInfo, 'id' | 'name' | 'connected' | 'driverId' | 'features' | 'authModel' | 'authNeeded'> & { authProperties?: ObjectPropertyInfo[] }
@injectable()
export class ConnectionInfoResource extends CachedMapResource<string, Connection> {
@@ -21,10 +22,41 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
super(new Map());
}
async init(id: string, credentials?: any): Promise<Connection> {
const connection = await this.setActivePromise(id, this.initConnection(id, credentials));
this.set(id, connection);
return this.get(id)!;
}
async loadAuthModel(connectionId: string): Promise<ObjectPropertyInfo[]> {
const connection = await this.load(connectionId);
if (connection?.authProperties) {
return connection.authProperties;
}
connection.authProperties = await this.setActivePromise(connectionId, this.getAuthProperties(connectionId));
return connection.authProperties!;
}
protected async loader(connectionId: string): Promise<Map<string, Connection>> {
const { connection } = await this.graphQLService.gql.connectionState({ id: connectionId });
this.set(connectionId, connection);
return this.data;
}
private async getAuthProperties(id: string): Promise<ObjectPropertyInfo[]> {
const { connection: { authProperties } } = await this.graphQLService.gql.connectionAuthProperties({ id });
return authProperties;
}
private async initConnection(id: string, credentials?: any): Promise<Connection> {
const { connection } = await this.graphQLService.gql.initConnection({ id, credentials });
return connection;
}
}
@@ -14,6 +14,7 @@ import { NotificationService } from '@cloudbeaver/core-events';
import { SessionResource } from '@cloudbeaver/core-root';
import { DataSourceInfo, GraphQLService } from '@cloudbeaver/core-sdk';
import { ROOT_NODE_PATH } from '../NodesManager/NavNodeInfoResource';
import { NavNodeManagerService } from '../NodesManager/NavNodeManagerService';
import { NodeManagerUtils } from '../NodesManager/NodeManagerUtils';
import { ConnectionInfoResource, Connection } from './ConnectionInfoResource';
@@ -64,11 +65,15 @@ export class ConnectionsManagerService {
async addOpenedConnection(connection: Connection) {
this.connectionInfo.set(connection.id, connection);
this.onOpenConnection.next(connection);
await this.navNodeManagerService.updateRootChildren(); // Update connections list, probably here we must also request node info and add it to nodes manager
const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(connection.id);
await this.navNodeManagerService.loadNode({ nodeId, parentId: ROOT_NODE_PATH });
this.navNodeManagerService.navTree.unshiftToNode(ROOT_NODE_PATH, [nodeId]);
}
getConnectionById(connectionId: string): Connection | undefined {
return this.connectionInfo.data.get(connectionId);
return this.connectionInfo.get(connectionId);
}
getObjectContainerById(
@@ -85,8 +90,28 @@ export class ConnectionsManagerService {
);
}
async deleteConnection(id: string) {
const connection = this.getConnectionById(id);
if (!connection?.features.includes(EConnectionFeature.temporary)) {
return;
}
await this.graphQLService.gql.deleteConnection({ id });
await this.afterConnectionClose(id);
this.connectionInfo.delete(id);
const navNodeId = NodeManagerUtils.connectionIdToConnectionNodeId(id);
const node = this.navNodeManagerService.getNode(navNodeId);
if (!node) {
return;
}
this.navNodeManagerService.navTree.deleteInNode(node.parentId, [navNodeId]);
}
hasAnyConnection(): boolean {
return Boolean(this.connections.length);
return !!this.connections.length;
}
async closeAllConnections(): Promise<void> {
@@ -97,15 +122,20 @@ export class ConnectionsManagerService {
}
async closeConnectionAsync(id: string, skipNodesRefresh?: boolean): Promise<void> {
await this.graphQLService.gql.closeConnection({ id });
const connectionUpdatedInfo = await this.graphQLService.gql.closeConnection({ id });
this.connectionInfo.set(connectionUpdatedInfo.connection.id, connectionUpdatedInfo.connection);
await this.afterConnectionClose(id);
this.connectionInfo.delete(id);
if (!skipNodesRefresh) {
await this.navNodeManagerService.updateRootChildren(); // Update connections list, probably here we must just remove nodes from nodes manager
}
}
async deleteNavNodeConnectionAsync(navNodeId: string): Promise<void> {
await this.deleteConnection(NodeManagerUtils.connectionNodeIdToConnectionId(navNodeId));
}
async closeNavNodeConnectionAsync(navNodeId: string): Promise<void> {
const connectionId = NodeManagerUtils.connectionNodeIdToConnectionId(navNodeId);
const connection = this.getConnectionById(connectionId);
@@ -114,22 +144,13 @@ export class ConnectionsManagerService {
}
try {
await this.graphQLService.gql.closeConnection({ id: connectionId });
await this.afterConnectionClose(connectionId);
if (connection?.features.includes(EConnectionFeature.temporary)) {
this.connectionInfo.delete(connectionId);
}
const connectionUpdatedInfo = await this.graphQLService.gql.closeConnection({ id: connectionId });
this.connectionInfo.set(connectionUpdatedInfo.connection.id, connectionUpdatedInfo.connection);
if (connection.features.includes(EConnectionFeature.temporary)) {
const node = this.navNodeManagerService.getNode(navNodeId);
if (!node) {
return;
}
await this.navNodeManagerService.refreshTree(node.parentId);
} else {
await this.navNodeManagerService.refreshNode(navNodeId);
await this.navNodeManagerService.removeTree(navNodeId);
}
await this.afterConnectionClose(connectionId);
this.navNodeManagerService.removeTree(navNodeId);
await this.navNodeManagerService.refreshNode(navNodeId);
} catch (exception) {
this.notificationService.logException(exception, `Can't close connection: ${navNodeId}`);
}
@@ -141,7 +162,7 @@ export class ConnectionsManagerService {
}
private async afterConnectionClose(id: string) {
this.navNodeManagerService.removeTree(id);
// this.navNodeManagerService.removeTree(id);
this.onCloseConnection.next(id);
}
@@ -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 { injectable } from '@cloudbeaver/core-di';
import {
DatabaseAuthModel,
GraphQLService,
CachedMapResource,
resourceKeyList
} from '@cloudbeaver/core-sdk';
@injectable()
export class DatabaseAuthModelsResource extends CachedMapResource<string, DatabaseAuthModel> {
constructor(private graphQLService: GraphQLService) {
super(new Map());
}
protected async loader(key: string): Promise<Map<string, DatabaseAuthModel>> {
const { models } = await this.graphQLService.gql.getAuthModels();
this.set(resourceKeyList(models.map(model => model.id)), models);
this.markUpdated(key);
return this.data;
}
}
@@ -29,6 +29,79 @@ export class NavTreeResource extends CachedMapResource<string, string[]> {
this.onDataOutdated.subscribe(navNodeInfoResource.markOutdated.bind(navNodeInfoResource));
}
deleteInNode(key: string, value: string[]): void;
deleteInNode(key: ResourceKeyList<string>, value: string[][]): void;
deleteInNode(keyObject: ResourceKey<string>, valueObject: string[] | string[][]) {
if (isResourceKeyList(keyObject)) {
for (let i = 0; i < keyObject.list.length; i++) {
const key = keyObject.list[i];
const values = (valueObject as string[][])[i];
const currentValue = this.data.get(key);
if (currentValue) {
this.data.set(key, currentValue.filter(value => !values.includes(value)));
this.delete(resourceKeyList(values));
}
}
} else {
const currentValue = this.data.get(keyObject);
if (currentValue) {
this.data.set(keyObject, currentValue.filter(value => !(valueObject as string[]).includes(value)));
this.delete(resourceKeyList(valueObject as string[]));
}
}
this.markUpdated(keyObject);
this.itemAddSubject.next(keyObject);
}
unshiftToNode(key: string, value: string[]): void;
unshiftToNode(key: ResourceKeyList<string>, value: string[][]): void;
unshiftToNode(keyObject: ResourceKey<string>, valueObject: string[] | string[][]) {
if (isResourceKeyList(keyObject)) {
for (let i = 0; i < keyObject.list.length; i++) {
const key = keyObject.list[i];
const values = (valueObject as string[][])[i];
const currentValue = this.data.get(key) || [];
currentValue.unshift(...values);
this.data.set(key, currentValue);
}
} else {
const currentValue = this.data.get(keyObject) || [];
currentValue.unshift(...valueObject as string[]);
this.data.set(keyObject, currentValue);
}
this.markUpdated(keyObject);
this.itemAddSubject.next(keyObject);
}
pushToNode(key: string, value: string[]): void;
pushToNode(key: ResourceKeyList<string>, value: string[][]): void;
pushToNode(keyObject: ResourceKey<string>, valueObject: string[] | string[][]) {
if (isResourceKeyList(keyObject)) {
for (let i = 0; i < keyObject.list.length; i++) {
const key = keyObject.list[i];
const values = (valueObject as string[][])[i];
const currentValue = this.data.get(key) || [];
currentValue.push(...values);
this.data.set(key, currentValue);
}
} else {
const currentValue = this.data.get(keyObject) || [];
currentValue.push(...valueObject as string[]);
this.data.set(keyObject, currentValue);
}
this.markUpdated(keyObject);
this.itemAddSubject.next(keyObject);
}
set(key: string, value: string[]): void;
set(key: ResourceKeyList<string>, value: string[][]): void;
set(keyObject: ResourceKey<string>, valueObject: string[] | string[][]): void {
@@ -16,6 +16,10 @@ export class NodeManagerUtils {
return connectionNodeId.replace('database://', '');
}
static connectionIdToConnectionNodeId(connectionId: string): string {
return `database://${connectionId}`;
}
static nodeIdToConnectionId(nodeId: string): string {
const matches = nodeId.match(/database:\/\/(.*?)(|\/.*)$/);
if (!matches) {
@@ -10,7 +10,8 @@ import {
ConnectionDialogsService, ConnectionsManagerService,
MainMenuService, NavigationService, NavigationTreeService,
NavNodeManagerService, DBObjectService, NavNodeExtensionsService, NavNodeInfoResource, NavTreeResource,
ConnectionSchemaManagerService, ConnectionInfoResource, ContainerResource, DBDriverResource, NavigationTabsService,
ConnectionSchemaManagerService, ConnectionInfoResource, ContainerResource,
DBDriverResource, NavigationTabsService, DatabaseAuthModelsResource, ConnectionAuthService,
NavigationTreeContextMenuService,
SettingsMenuService, LogViewerService, LogViewerMenuService, TopNavService,
RouterService, ScreenService, AppScreenService, CoreSettingsService
@@ -76,6 +77,8 @@ export const coreManifest: PluginManifest = {
TopNavService,
NavigationService,
NavigationTabsService,
DatabaseAuthModelsResource,
ConnectionAuthService,
NavigationTreeContextMenuService,
NavigationTreeService,
NavNodeManagerService,
@@ -15,7 +15,7 @@ import {
} from '@cloudbeaver/core-sdk';
export type SessionState = Pick<SessionInfo, 'createTime' | 'cacheExpired' | 'lastAccessTime' | 'locale'> & {
connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'connected' | 'driverId' | 'features'>>;
connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'connected' | 'driverId' | 'features' | 'authNeeded' | 'authModel'>>;
};
@injectable()
@@ -78,11 +78,11 @@ export abstract class CachedResource<
this.dataSubject.next(this.data);
}
protected async setActivePromise(param: TParam, promise: Promise<any>) {
protected async setActivePromise<T>(param: TParam, promise: Promise<T>): Promise<T> {
this.activePromise = promise;
this.activePromiseParam = param;
try {
await this.activePromise;
return await this.activePromise;
} finally {
this.activePromise = null;
this.activePromiseParam = null;
@@ -1,3 +1,12 @@
mutation closeConnection($id: ID!) {
closeConnection(id: $id)
connection: closeConnection(id: $id) {
id
name
driverId
connected
features
authNeeded
authModel
}
}
@@ -0,0 +1,15 @@
query connectionAuthProperties($id: ID!) {
connection: connectionState(id: $id) {
authProperties {
id
displayName
description
category
dataType
value
validValues
defaultValue
features
}
}
}
@@ -5,5 +5,8 @@ query connectionState($id: ID!) {
driverId
connected
features
authNeeded
authModel
}
}
@@ -5,5 +5,8 @@ mutation createConnection($config: ConnectionConfig!) {
driverId
connected
features
authNeeded
authModel
}
}
@@ -0,0 +1,3 @@
mutation deleteConnection($id: ID!) {
deleteConnection(id: $id)
}
@@ -9,5 +9,8 @@ query driverList {
embedded
anonymousAccess
promotedScore
defaultAuthModel
# applicableAuthModel
}
}
@@ -0,0 +1,20 @@
query getAuthModels {
models: authModels {
id
displayName
description
icon
properties {
id
displayName
description
category
dataType
value
validValues
defaultValue
features
}
}
}
@@ -0,0 +1,12 @@
mutation initConnection($id: ID!, $credentials: Object) {
connection: initConnection(id: $id, credentials: $credentials) {
id
name
driverId
connected
features
authNeeded
authModel
}
}
@@ -5,5 +5,8 @@ mutation openConnection($config: ConnectionConfig!) {
driverId
connected
features
authNeeded
authModel
}
}
@@ -10,6 +10,9 @@ mutation openSession {
driverId
connected
features
authNeeded
authModel
}
}
}
@@ -16,5 +16,14 @@ query serverConfig {
nativeName
}
productConfiguration
defaultNavigatorSettings {
showSystemObjects
showUtilityObjects
showOnlyEntities
mergeEntities
hideFolders
hideSchemas
hideVirtualModel
}
}
}
@@ -10,6 +10,9 @@ query sessionState {
driverId
connected
features
authNeeded
authModel
}
}
}
+220 -35
View File
@@ -18,10 +18,14 @@ export type Scalars = {
export type Query = {
authLogin: UserAuthInfo;
authLogout?: Maybe<Scalars['Boolean']>;
authModels: Array<DatabaseAuthModel>;
authProviders: Array<AuthProviderInfo>;
connectionInfo: ConnectionInfo;
/** @deprecated Field no longer supported */
connectionState: ConnectionInfo;
createRole: AdminRoleInfo;
createUser: AdminUserInfo;
/** @deprecated Field no longer supported */
dataSourceList: Array<DataSourceInfo>;
dataTransferAvailableStreamProcessors: Array<DataTransferProcessorInfo>;
dataTransferExportDataFromContainer: AsyncTaskInfo;
@@ -50,6 +54,7 @@ export type Query = {
sqlCompletionProposals?: Maybe<Array<Maybe<SqlCompletionProposal>>>;
sqlDialectInfo?: Maybe<SqlDialectInfo>;
sqlListContexts?: Maybe<Array<Maybe<SqlContextInfo>>>;
templateDataSources: Array<DataSourceInfo>;
};
export type QueryAuthLoginArgs = {
@@ -57,6 +62,10 @@ export type QueryAuthLoginArgs = {
credentials: Scalars['Object'];
};
export type QueryConnectionInfoArgs = {
id: Scalars['ID'];
};
export type QueryConnectionStateArgs = {
id: Scalars['ID'];
};
@@ -178,12 +187,17 @@ export type Mutation = {
asyncTaskCancel?: Maybe<Scalars['Boolean']>;
asyncTaskStatus: AsyncTaskInfo;
changeSessionLanguage?: Maybe<Scalars['Boolean']>;
closeConnection: Scalars['Boolean'];
closeConnection: ConnectionInfo;
closeSession?: Maybe<Scalars['Boolean']>;
createConnection: ConnectionInfo;
deleteConnection: Scalars['Boolean'];
initConnection: ConnectionInfo;
/** @deprecated Field no longer supported */
openConnection: ConnectionInfo;
openSession: SessionInfo;
readDataFromContainer?: Maybe<SqlExecuteInfo>;
setConnectionNavigatorSettings: Scalars['Boolean'];
setDefaultNavigatorSettings: Scalars['Boolean'];
sqlContextCreate: SqlContextInfo;
sqlContextDestroy: Scalars['Boolean'];
sqlContextSetDefaults: Scalars['Boolean'];
@@ -222,6 +236,15 @@ export type MutationCreateConnectionArgs = {
config: ConnectionConfig;
};
export type MutationDeleteConnectionArgs = {
id: Scalars['ID'];
};
export type MutationInitConnectionArgs = {
id: Scalars['ID'];
credentials?: Maybe<Scalars['Object']>;
};
export type MutationOpenConnectionArgs = {
config: ConnectionConfig;
};
@@ -233,6 +256,15 @@ export type MutationReadDataFromContainerArgs = {
filter?: Maybe<SqlDataFilter>;
};
export type MutationSetConnectionNavigatorSettingsArgs = {
id: Scalars['ID'];
settings: NavigatorSettingsInput;
};
export type MutationSetDefaultNavigatorSettingsArgs = {
settings: NavigatorSettingsInput;
};
export type MutationSqlContextCreateArgs = {
connectionId: Scalars['ID'];
defaultCatalog?: Maybe<Scalars['String']>;
@@ -285,6 +317,18 @@ export type MutationUpdateResultsDataBatchArgs = {
addedRows?: Maybe<Array<SqlResultRow>>;
};
export type ObjectPropertyInfo = {
id?: Maybe<Scalars['String']>;
displayName?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
category?: Maybe<Scalars['String']>;
dataType?: Maybe<Scalars['String']>;
value?: Maybe<Scalars['Object']>;
validValues?: Maybe<Array<Maybe<Scalars['Object']>>>;
defaultValue?: Maybe<Scalars['Object']>;
features: Array<Scalars['String']>;
};
export type AsyncTaskInfo = {
id: Scalars['String'];
name?: Maybe<Scalars['String']>;
@@ -325,7 +369,9 @@ export type ServerConfig = {
version: Scalars['String'];
anonymousAccessEnabled?: Maybe<Scalars['Boolean']>;
authenticationEnabled?: Maybe<Scalars['Boolean']>;
/** @deprecated Field no longer supported */
supportsPredefinedConnections?: Maybe<Scalars['Boolean']>;
/** @deprecated Field no longer supported */
supportsProvidedConnections?: Maybe<Scalars['Boolean']>;
supportsCustomConnections?: Maybe<Scalars['Boolean']>;
supportsConnectionBrowser?: Maybe<Scalars['Boolean']>;
@@ -333,6 +379,7 @@ export type ServerConfig = {
supportedLanguages: Array<ServerLanguage>;
services?: Maybe<Array<Maybe<WebServiceConfig>>>;
productConfiguration: Scalars['Object'];
defaultNavigatorSettings: NavigatorSettings;
};
export type SessionInfo = {
@@ -344,6 +391,14 @@ export type SessionInfo = {
connections: Array<ConnectionInfo>;
};
export type DatabaseAuthModel = {
id: Scalars['ID'];
displayName: Scalars['String'];
description?: Maybe<Scalars['String']>;
icon?: Maybe<Scalars['String']>;
properties: Array<ObjectPropertyInfo>;
};
export type DriverInfo = {
id: Scalars['ID'];
name?: Maybe<Scalars['String']>;
@@ -357,7 +412,9 @@ export type DriverInfo = {
driverInfoURL?: Maybe<Scalars['String']>;
driverPropertiesURL?: Maybe<Scalars['String']>;
embedded?: Maybe<Scalars['Boolean']>;
/** @deprecated Field no longer supported */
anonymousAccess?: Maybe<Scalars['Boolean']>;
/** @deprecated Field no longer supported */
allowsEmptyPassword?: Maybe<Scalars['Boolean']>;
licenseRequired?: Maybe<Scalars['Boolean']>;
license?: Maybe<Scalars['String']>;
@@ -365,18 +422,10 @@ export type DriverInfo = {
promotedScore?: Maybe<Scalars['Int']>;
connectionProperties?: Maybe<Scalars['Object']>;
defaultConnectionProperties?: Maybe<Scalars['Object']>;
driverProperties?: Maybe<Array<Maybe<DriverPropertyInfo>>>;
driverProperties?: Maybe<Array<ObjectPropertyInfo>>;
driverParameters?: Maybe<Scalars['Object']>;
};
export type DriverPropertyInfo = {
id: Scalars['ID'];
displayName?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
category?: Maybe<Scalars['String']>;
dataType?: Maybe<Scalars['String']>;
defaultValue?: Maybe<Scalars['Object']>;
validValues?: Maybe<Array<Maybe<Scalars['Object']>>>;
defaultAuthModel?: Maybe<Scalars['ID']>;
applicableAuthModel: Array<Scalars['ID']>;
};
export type DataSourceInfo = {
@@ -392,10 +441,10 @@ export type DataSourceInfo = {
};
export type ConnectionConfig = {
driverId?: Maybe<Scalars['ID']>;
name?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
dataSourceId?: Maybe<Scalars['ID']>;
driverId?: Maybe<Scalars['ID']>;
host?: Maybe<Scalars['String']>;
port?: Maybe<Scalars['String']>;
databaseName?: Maybe<Scalars['String']>;
@@ -403,6 +452,28 @@ export type ConnectionConfig = {
properties?: Maybe<Scalars['Object']>;
userName?: Maybe<Scalars['String']>;
userPassword?: Maybe<Scalars['String']>;
authModelId?: Maybe<Scalars['ID']>;
credentials?: Maybe<Scalars['Object']>;
};
export type NavigatorSettings = {
showSystemObjects: Scalars['Boolean'];
showUtilityObjects: Scalars['Boolean'];
showOnlyEntities: Scalars['Boolean'];
mergeEntities: Scalars['Boolean'];
hideFolders: Scalars['Boolean'];
hideSchemas: Scalars['Boolean'];
hideVirtualModel: Scalars['Boolean'];
};
export type NavigatorSettingsInput = {
showSystemObjects: Scalars['Boolean'];
showUtilityObjects: Scalars['Boolean'];
showOnlyEntities: Scalars['Boolean'];
mergeEntities: Scalars['Boolean'];
hideFolders: Scalars['Boolean'];
hideSchemas: Scalars['Boolean'];
hideVirtualModel: Scalars['Boolean'];
};
export type ConnectionInfo = {
@@ -417,7 +488,11 @@ export type ConnectionInfo = {
connectionError?: Maybe<ServerError>;
serverVersion?: Maybe<Scalars['String']>;
clientVersion?: Maybe<Scalars['String']>;
authNeeded: Scalars['Boolean'];
authModel?: Maybe<Scalars['ID']>;
authProperties: Array<ObjectPropertyInfo>;
features: Array<Scalars['String']>;
navigatorSettings: NavigatorSettings;
};
export type LogEntry = {
@@ -436,18 +511,6 @@ export type ObjectDescriptor = {
value?: Maybe<Scalars['String']>;
};
export type ObjectPropertyInfo = {
id?: Maybe<Scalars['String']>;
displayName?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
category?: Maybe<Scalars['String']>;
dataType?: Maybe<Scalars['String']>;
value?: Maybe<Scalars['Object']>;
validValues?: Maybe<Array<Maybe<Scalars['Object']>>>;
defaultValue?: Maybe<Scalars['Object']>;
features: Array<Scalars['String']>;
};
export type ObjectPropertyFilter = {
ids?: Maybe<Array<Maybe<Scalars['String']>>>;
features?: Maybe<Array<Maybe<Scalars['String']>>>;
@@ -731,27 +794,39 @@ export type CloseConnectionMutationVariables = Exact<{
id: Scalars['ID'];
}>;
export type CloseConnectionMutation = Pick<Mutation, 'closeConnection'>;
export type CloseConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
export type ConnectionAuthPropertiesQueryVariables = Exact<{
id: Scalars['ID'];
}>;
export type ConnectionAuthPropertiesQuery = { connection: { authProperties: Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'value' | 'validValues' | 'defaultValue' | 'features'>> } };
export type ConnectionStateQueryVariables = Exact<{
id: Scalars['ID'];
}>;
export type ConnectionStateQuery = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features'> };
export type ConnectionStateQuery = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
export type CreateConnectionMutationVariables = Exact<{
config: ConnectionConfig;
}>;
export type CreateConnectionMutation = { createConnection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features'> };
export type CreateConnectionMutation = { createConnection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
export type DataSourceListQueryVariables = Exact<{ [key: string]: never }>;
export type DataSourceListQuery = { dataSourceList: Array<Pick<DataSourceInfo, 'id' | 'name' | 'driverId' | 'description'>> };
export type DeleteConnectionMutationVariables = Exact<{
id: Scalars['ID'];
}>;
export type DeleteConnectionMutation = Pick<Mutation, 'deleteConnection'>;
export type DriverListQueryVariables = Exact<{ [key: string]: never }>;
export type DriverListQuery = { driverList: Array<Pick<DriverInfo, 'id' | 'name' | 'icon' | 'description' | 'defaultPort' | 'sampleURL' | 'embedded' | 'anonymousAccess' | 'promotedScore'>> };
export type DriverListQuery = { driverList: Array<Pick<DriverInfo, 'id' | 'name' | 'icon' | 'description' | 'defaultPort' | 'sampleURL' | 'embedded' | 'anonymousAccess' | 'promotedScore' | 'defaultAuthModel'>> };
export type DriverPropertiesQueryVariables = Exact<{
driverId: Scalars['ID'];
@@ -759,7 +834,14 @@ export type DriverPropertiesQueryVariables = Exact<{
export type DriverPropertiesQuery = { driver: Array<(
Pick<DriverInfo, 'driverParameters'>
& { driverProperties?: Maybe<Array<Maybe<Pick<DriverPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'defaultValue' | 'validValues'>>>> }
& { driverProperties?: Maybe<Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'defaultValue' | 'validValues'>>> }
)>; };
export type GetAuthModelsQueryVariables = Exact<{ [key: string]: never }>;
export type GetAuthModelsQuery = { models: Array<(
Pick<DatabaseAuthModel, 'id' | 'displayName' | 'description' | 'icon'>
& { properties: Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'value' | 'validValues' | 'defaultValue' | 'features'>> }
)>; };
export type GetDriverByIdQueryVariables = Exact<{
@@ -768,11 +850,18 @@ export type GetDriverByIdQueryVariables = Exact<{
export type GetDriverByIdQuery = { driverList: Array<Pick<DriverInfo, 'id' | 'name' | 'icon'>> };
export type InitConnectionMutationVariables = Exact<{
id: Scalars['ID'];
credentials?: Maybe<Scalars['Object']>;
}>;
export type InitConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
export type OpenConnectionMutationVariables = Exact<{
config: ConnectionConfig;
}>;
export type OpenConnectionMutation = { openConnection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features'> };
export type OpenConnectionMutation = { openConnection: Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
export type TestConnectionMutationVariables = Exact<{
config: ConnectionConfig;
@@ -1022,7 +1111,7 @@ export type OpenSessionMutationVariables = Exact<{ [key: string]: never }>;
export type OpenSessionMutation = { session: (
Pick<SessionInfo, 'createTime' | 'lastAccessTime' | 'cacheExpired' | 'locale'>
& { connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features'>> }
& { connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'>> }
); };
export type ReadSessionLogQueryVariables = Exact<{
@@ -1036,7 +1125,7 @@ export type ServerConfigQueryVariables = Exact<{ [key: string]: never }>;
export type ServerConfigQuery = { serverConfig: (
Pick<ServerConfig, 'name' | 'version' | 'productConfiguration' | 'supportsPredefinedConnections' | 'supportsProvidedConnections' | 'supportsCustomConnections' | 'supportsConnectionBrowser' | 'supportsWorkspaces' | 'anonymousAccessEnabled' | 'authenticationEnabled'>
& { supportedLanguages: Array<Pick<ServerLanguage, 'isoCode' | 'displayName' | 'nativeName'>> }
& { supportedLanguages: Array<Pick<ServerLanguage, 'isoCode' | 'displayName' | 'nativeName'>>; defaultNavigatorSettings: Pick<NavigatorSettings, 'showSystemObjects' | 'showUtilityObjects' | 'showOnlyEntities' | 'mergeEntities' | 'hideFolders' | 'hideSchemas' | 'hideVirtualModel'> }
); };
export type SessionPermissionsQueryVariables = Exact<{ [key: string]: never }>;
@@ -1047,7 +1136,7 @@ export type SessionStateQueryVariables = Exact<{ [key: string]: never }>;
export type SessionStateQuery = { sessionState: (
Pick<SessionInfo, 'createTime' | 'lastAccessTime' | 'locale' | 'cacheExpired'>
& { connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features'>> }
& { connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'>> }
); };
export type TouchSessionMutationVariables = Exact<{ [key: string]: never }>;
@@ -1190,7 +1279,32 @@ export const SetUserCredentialsDocument = `
`;
export const CloseConnectionDocument = `
mutation closeConnection($id: ID!) {
closeConnection(id: $id)
connection: closeConnection(id: $id) {
id
name
driverId
connected
features
authNeeded
authModel
}
}
`;
export const ConnectionAuthPropertiesDocument = `
query connectionAuthProperties($id: ID!) {
connection: connectionState(id: $id) {
authProperties {
id
displayName
description
category
dataType
value
validValues
defaultValue
features
}
}
}
`;
export const ConnectionStateDocument = `
@@ -1201,6 +1315,8 @@ export const ConnectionStateDocument = `
driverId
connected
features
authNeeded
authModel
}
}
`;
@@ -1212,6 +1328,8 @@ export const CreateConnectionDocument = `
driverId
connected
features
authNeeded
authModel
}
}
`;
@@ -1225,6 +1343,11 @@ export const DataSourceListDocument = `
}
}
`;
export const DeleteConnectionDocument = `
mutation deleteConnection($id: ID!) {
deleteConnection(id: $id)
}
`;
export const DriverListDocument = `
query driverList {
driverList {
@@ -1237,6 +1360,7 @@ export const DriverListDocument = `
embedded
anonymousAccess
promotedScore
defaultAuthModel
}
}
`;
@@ -1256,6 +1380,27 @@ export const DriverPropertiesDocument = `
}
}
`;
export const GetAuthModelsDocument = `
query getAuthModels {
models: authModels {
id
displayName
description
icon
properties {
id
displayName
description
category
dataType
value
validValues
defaultValue
features
}
}
}
`;
export const GetDriverByIdDocument = `
query getDriverById($driverId: ID!) {
driverList(id: $driverId) {
@@ -1265,6 +1410,19 @@ export const GetDriverByIdDocument = `
}
}
`;
export const InitConnectionDocument = `
mutation initConnection($id: ID!, $credentials: Object) {
connection: initConnection(id: $id, credentials: $credentials) {
id
name
driverId
connected
features
authNeeded
authModel
}
}
`;
export const OpenConnectionDocument = `
mutation openConnection($config: ConnectionConfig!) {
openConnection(config: $config) {
@@ -1273,6 +1431,8 @@ export const OpenConnectionDocument = `
driverId
connected
features
authNeeded
authModel
}
}
`;
@@ -1688,6 +1848,8 @@ export const OpenSessionDocument = `
driverId
connected
features
authNeeded
authModel
}
}
}
@@ -1721,6 +1883,15 @@ export const ServerConfigDocument = `
nativeName
}
productConfiguration
defaultNavigatorSettings {
showSystemObjects
showUtilityObjects
showOnlyEntities
mergeEntities
hideFolders
hideSchemas
hideVirtualModel
}
}
}
`;
@@ -1742,6 +1913,8 @@ export const SessionStateDocument = `
driverId
connected
features
authNeeded
authModel
}
}
}
@@ -1820,6 +1993,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
closeConnection(variables: CloseConnectionMutationVariables): Promise<CloseConnectionMutation> {
return withWrapper(() => client.request<CloseConnectionMutation>(CloseConnectionDocument, variables));
},
connectionAuthProperties(variables: ConnectionAuthPropertiesQueryVariables): Promise<ConnectionAuthPropertiesQuery> {
return withWrapper(() => client.request<ConnectionAuthPropertiesQuery>(ConnectionAuthPropertiesDocument, variables));
},
connectionState(variables: ConnectionStateQueryVariables): Promise<ConnectionStateQuery> {
return withWrapper(() => client.request<ConnectionStateQuery>(ConnectionStateDocument, variables));
},
@@ -1829,15 +2005,24 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
dataSourceList(variables?: DataSourceListQueryVariables): Promise<DataSourceListQuery> {
return withWrapper(() => client.request<DataSourceListQuery>(DataSourceListDocument, variables));
},
deleteConnection(variables: DeleteConnectionMutationVariables): Promise<DeleteConnectionMutation> {
return withWrapper(() => client.request<DeleteConnectionMutation>(DeleteConnectionDocument, variables));
},
driverList(variables?: DriverListQueryVariables): Promise<DriverListQuery> {
return withWrapper(() => client.request<DriverListQuery>(DriverListDocument, variables));
},
driverProperties(variables: DriverPropertiesQueryVariables): Promise<DriverPropertiesQuery> {
return withWrapper(() => client.request<DriverPropertiesQuery>(DriverPropertiesDocument, variables));
},
getAuthModels(variables?: GetAuthModelsQueryVariables): Promise<GetAuthModelsQuery> {
return withWrapper(() => client.request<GetAuthModelsQuery>(GetAuthModelsDocument, variables));
},
getDriverById(variables: GetDriverByIdQueryVariables): Promise<GetDriverByIdQuery> {
return withWrapper(() => client.request<GetDriverByIdQuery>(GetDriverByIdDocument, variables));
},
initConnection(variables: InitConnectionMutationVariables): Promise<InitConnectionMutation> {
return withWrapper(() => client.request<InitConnectionMutation>(InitConnectionDocument, variables));
},
openConnection(variables: OpenConnectionMutationVariables): Promise<OpenConnectionMutation> {
return withWrapper(() => client.request<OpenConnectionMutation>(OpenConnectionDocument, variables));
},
@@ -12,7 +12,7 @@ import { DBDriver } from '@cloudbeaver/core-app';
import { IProperty } from '@cloudbeaver/core-blocks';
import { injectable, IInitializableController } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { DriverPropertyInfo } from '@cloudbeaver/core-sdk';
import { ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
import { uuid } from '@cloudbeaver/core-utils';
import { CustomConnectionService } from '../../../CustomConnectionService';
@@ -25,7 +25,7 @@ type StaticId = {
staticId: string;
}
export type DriverPropertyInfoWithStaticId = DriverPropertyInfo & StaticId
export type DriverPropertyInfoWithStaticId = ObjectPropertyInfo & StaticId
@injectable()
export class DriverPropertiesController implements IInitializableController {
@@ -8,7 +8,7 @@
import { ConnectionsManagerService, Connection } from '@cloudbeaver/core-app';
import { injectable } from '@cloudbeaver/core-di';
import { ConnectionConfig, GraphQLService, DriverPropertyInfo } from '@cloudbeaver/core-sdk';
import { ConnectionConfig, GraphQLService, ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
@injectable()
export class CustomConnectionService {
@@ -17,7 +17,7 @@ export class CustomConnectionService {
private connectionsManagerService: ConnectionsManagerService) {
}
async loadDriverProperties(driverId: string): Promise<DriverPropertyInfo[]> {
async loadDriverProperties(driverId: string): Promise<ObjectPropertyInfo[]> {
const response = await this.graphQLService.gql.driverProperties({
driverId,
});
@@ -26,7 +26,7 @@ export class CustomConnectionService {
throw new Error('Driver properties loading failed');
}
return response.driver[0].driverProperties!;
return response.driver[0].driverProperties! as ObjectPropertyInfo[];
}
async createConnectionAsync(config: ConnectionConfig): Promise<Connection> {