Add extension and storage paths to App container (#1756)

This commit is contained in:
Charis Kyriakou
2022-11-14 15:47:58 +00:00
committed by GitHub
parent 3fd9fd449c
commit fca2faf021
9 changed files with 118 additions and 14 deletions

View File

@@ -2,4 +2,7 @@ import { AppEventEmitter } from './events';
export interface App {
createEventEmitter<T>(): AppEventEmitter<T>;
extensionPath: string;
globalStoragePath: string;
workspaceStoragePath?: string;
}

View File

@@ -1,8 +1,26 @@
import * as vscode from 'vscode';
import { App } from '../app';
import { AppEventEmitter } from '../events';
import { VSCodeAppEventEmitter } from './events';
export class ExtensionApp implements App {
public constructor(
public readonly extensionContext: vscode.ExtensionContext
) {
}
public get extensionPath(): string {
return this.extensionContext.extensionPath;
}
public get globalStoragePath(): string {
return this.extensionContext.globalStorageUri.fsPath;
}
public get workspaceStoragePath(): string | undefined {
return this.extensionContext.storageUri?.fsPath;
}
public createEventEmitter<T>(): AppEventEmitter<T> {
return new VSCodeAppEventEmitter<T>();
}

View File

@@ -5,6 +5,7 @@ import * as chokidar from 'chokidar';
import { DisposableObject } from '../pure/disposable-object';
import { DbConfigValidator } from './db-config-validator';
import { ValueResult } from '../common/value-result';
import { App } from '../common/app';
export class DbConfigStore extends DisposableObject {
private readonly configPath: string;
@@ -14,17 +15,16 @@ export class DbConfigStore extends DisposableObject {
private configErrors: string[];
private configWatcher: chokidar.FSWatcher | undefined;
public constructor(
workspaceStoragePath: string,
extensionPath: string) {
public constructor(app: App) {
super();
this.configPath = path.join(workspaceStoragePath, 'workspace-databases.json');
const storagePath = app.workspaceStoragePath || app.globalStoragePath;
this.configPath = path.join(storagePath, 'workspace-databases.json');
this.config = this.createEmptyConfig();
this.configErrors = [];
this.configWatcher = undefined;
this.configValidator = new DbConfigValidator(extensionPath);
this.configValidator = new DbConfigValidator(app.extensionPath);
}
public async initialize(): Promise<void> {

View File

@@ -1,4 +1,5 @@
import * as vscode from 'vscode';
import { ExtensionApp } from '../common/vscode/vscode-app';
import { isCanary, isNewQueryRunExperienceEnabled } from '../config';
import { logger } from '../logging';
import { DisposableObject } from '../pure/disposable-object';
@@ -21,9 +22,9 @@ export class DbModule extends DisposableObject {
void logger.log('Initializing database module');
const storagePath = extensionContext.storageUri?.fsPath || extensionContext.globalStorageUri.fsPath;
const extensionPath = extensionContext.extensionPath;
const dbConfigStore = new DbConfigStore(storagePath, extensionPath);
const app = new ExtensionApp(extensionContext);
const dbConfigStore = new DbConfigStore(app);
await dbConfigStore.initialize();
const dbManager = new DbManager(dbConfigStore);

View File

@@ -0,0 +1,21 @@
import * as vscode from 'vscode';
/**
* Creates a partially implemented mock of vscode.ExtensionContext.
*/
export function createMockExtensionContext({
extensionPath = '/mock/extension/path',
workspaceStoragePath = '/mock/workspace/storage/path',
globalStoragePath = '/mock/global/storage/path',
}: {
extensionPath?: string,
workspaceStoragePath?: string,
globalStoragePath?: string,
}): vscode.ExtensionContext {
return {
extensionPath: extensionPath,
globalStorageUri: vscode.Uri.file(globalStoragePath),
storageUri: vscode.Uri.file(workspaceStoragePath),
} as any as vscode.ExtensionContext;
}

View File

@@ -10,11 +10,14 @@ import { DbTreeDataProvider } from '../../../databases/ui/db-tree-data-provider'
import { DbPanel } from '../../../databases/ui/db-panel';
import { DbItemKind } from '../../../databases/db-item';
import { DbTreeViewItem } from '../../../databases/ui/db-tree-view-item';
import { ExtensionApp } from '../../../common/vscode/vscode-app';
import { createMockExtensionContext } from '../../factories/extension-context';
const proxyquire = pq.noPreserveCache();
describe('db panel', async () => {
const workspaceStoragePath = path.join(__dirname, 'test-workspace');
const workspaceStoragePath = path.join(__dirname, 'test-workspace-storage');
const globalStoragePath = path.join(__dirname, 'test-global-storage');
const extensionPath = path.join(__dirname, '../../../../');
const dbConfigFilePath = path.join(workspaceStoragePath, 'workspace-databases.json');
let dbTreeDataProvider: DbTreeDataProvider;
@@ -23,7 +26,14 @@ describe('db panel', async () => {
let dbPanel: DbPanel;
before(async () => {
dbConfigStore = new DbConfigStore(workspaceStoragePath, extensionPath);
const extensionContext = createMockExtensionContext({
extensionPath,
globalStoragePath,
workspaceStoragePath
});
const app = new ExtensionApp(extensionContext);
dbConfigStore = new DbConfigStore(app);
dbManager = new DbManager(dbConfigStore);
// Create a modified version of the DbPanel module that allows

View File

@@ -0,0 +1,36 @@
import { App } from '../../src/common/app';
import { AppEvent, AppEventEmitter } from '../../src/common/events';
import { Disposable } from '../../src/pure/disposable-object';
export function createMockApp({
extensionPath = '/mock/extension/path',
workspaceStoragePath = '/mock/workspace/storage/path',
globalStoragePath = '/mock/global/storage/path',
createEventEmitter = <T>() => new MockAppEventEmitter<T>()
}: {
extensionPath?: string,
workspaceStoragePath?: string,
globalStoragePath?: string,
createEventEmitter?: <T>() => AppEventEmitter<T>
}): App {
return {
createEventEmitter,
extensionPath,
workspaceStoragePath,
globalStoragePath
};
}
export class MockAppEventEmitter<T> implements AppEventEmitter<T> {
public event: AppEvent<T>;
constructor() {
this.event = () => {
return {} as Disposable;
};
}
public fire(): void {
// no-op
}
}

View File

@@ -2,6 +2,7 @@ import * as fs from 'fs-extra';
import * as path from 'path';
import { DbConfigStore } from '../../../src/databases/db-config-store';
import { expect } from 'chai';
import { createMockApp } from '../../__mocks__/appMock';
describe('db config store', async () => {
const extensionPath = path.join(__dirname, '../../..');
@@ -17,9 +18,14 @@ describe('db config store', async () => {
});
it('should create a new config if one does not exist', async () => {
const app = createMockApp({
extensionPath,
workspaceStoragePath: tempWorkspaceStoragePath
});
const configPath = path.join(tempWorkspaceStoragePath, 'workspace-databases.json');
const configStore = new DbConfigStore(tempWorkspaceStoragePath, extensionPath);
const configStore = new DbConfigStore(app);
await configStore.initialize();
expect(await fs.pathExists(configPath)).to.be.true;
@@ -32,7 +38,11 @@ describe('db config store', async () => {
});
it('should load an existing config', async () => {
const configStore = new DbConfigStore(testDataStoragePath, extensionPath);
const app = createMockApp({
extensionPath,
workspaceStoragePath: testDataStoragePath
});
const configStore = new DbConfigStore(app);
await configStore.initialize();
const config = configStore.getConfig().value;
@@ -70,7 +80,11 @@ describe('db config store', async () => {
});
it('should not allow modification of the config', async () => {
const configStore = new DbConfigStore(testDataStoragePath, extensionPath);
const app = createMockApp({
extensionPath,
workspaceStoragePath: testDataStoragePath
});
const configStore = new DbConfigStore(app);
await configStore.initialize();
const config = configStore.getConfig().value;

View File

@@ -4,6 +4,7 @@
"exclude": [],
"compilerOptions": {
"noEmit": true,
"resolveJsonModule": true
"resolveJsonModule": true,
"rootDirs": [".", "../src"]
}
}