Merge pull request #1761 from github/nora/add-selected-state-to-db-config

Add selected to config
This commit is contained in:
Nora
2022-11-15 16:09:06 +01:00
committed by GitHub
10 changed files with 406 additions and 299 deletions

View File

@@ -103,15 +103,17 @@ export class DbConfigStore extends DisposableObject {
private createEmptyConfig(): DbConfig {
return {
remote: {
repositoryLists: [],
owners: [],
repositories: [],
},
local: {
lists: [],
databases: [],
},
databases: {
remote: {
repositoryLists: [],
owners: [],
repositories: [],
},
local: {
lists: [],
databases: [],
},
}
};
}
}

View File

@@ -1,10 +1,25 @@
// Contains models for the data we want to store in the database config
export interface DbConfig {
databases: DbConfigDatabases;
selected?: SelectedDbItem;
}
export interface DbConfigDatabases {
remote: RemoteDbConfig;
local: LocalDbConfig;
}
export interface SelectedDbItem {
kind: SelectedDbItemKind;
value: string;
}
export enum SelectedDbItemKind {
ConfigDefined = 'configDefined',
RemoteSystemDefinedList = 'remoteSystemDefinedList',
}
export interface RemoteDbConfig {
repositoryLists: RemoteRepositoryList[];
owners: string[];
@@ -35,20 +50,26 @@ export interface LocalDatabase {
export function cloneDbConfig(config: DbConfig): DbConfig {
return {
remote: {
repositoryLists: config.remote.repositoryLists.map((list) => ({
name: list.name,
repositories: [...list.repositories],
})),
owners: [...config.remote.owners],
repositories: [...config.remote.repositories],
},
local: {
lists: config.local.lists.map((list) => ({
name: list.name,
databases: list.databases.map((db) => ({ ...db })),
})),
databases: config.local.databases.map((db) => ({ ...db })),
databases: {
remote: {
repositoryLists: config.databases.remote.repositoryLists.map((list) => ({
name: list.name,
repositories: [...list.repositories],
})),
owners: [...config.databases.remote.owners],
repositories: [...config.databases.remote.repositories],
},
local: {
lists: config.databases.local.lists.map((list) => ({
name: list.name,
databases: list.databases.map((db) => ({ ...db })),
})),
databases: config.databases.local.databases.map((db) => ({ ...db })),
},
},
selected: config.selected ? {
kind: config.selected.kind,
value: config.selected.value,
} : undefined
};
}

View File

@@ -16,9 +16,9 @@ export function createRemoteTree(dbConfig: DbConfig): RootRemoteDbItem {
createSystemDefinedList(1000)
];
const userDefinedRepoLists = dbConfig.remote.repositoryLists.map(createUserDefinedList);
const owners = dbConfig.remote.owners.map(createOwnerItem);
const repos = dbConfig.remote.repositories.map(createRepoItem);
const userDefinedRepoLists = dbConfig.databases.remote.repositoryLists.map(createUserDefinedList);
const owners = dbConfig.databases.remote.owners.map(createOwnerItem);
const repos = dbConfig.databases.remote.repositories.map(createRepoItem);
return {
kind: DbItemKind.RootRemote,

View File

@@ -65,14 +65,16 @@ describe('db panel', async () => {
it('should render default local and remote nodes when the config is empty', async () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [],
owners: [],
repositories: []
},
local: {
lists: [],
databases: []
databases: {
remote: {
repositoryLists: [],
owners: [],
repositories: []
},
local: {
lists: [],
databases: []
},
},
};
@@ -111,30 +113,32 @@ describe('db panel', async () => {
it('should render remote repository list nodes', async () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [
{
name: 'my-list-1',
repositories: [
'owner1/repo1',
'owner1/repo2'
]
},
{
name: 'my-list-2',
repositories: [
'owner1/repo1',
'owner2/repo1',
'owner2/repo2'
]
},
],
owners: [],
repositories: []
},
local: {
lists: [],
databases: []
databases: {
remote: {
repositoryLists: [
{
name: 'my-list-1',
repositories: [
'owner1/repo1',
'owner1/repo2'
]
},
{
name: 'my-list-2',
repositories: [
'owner1/repo1',
'owner2/repo1',
'owner2/repo2'
]
},
],
owners: [],
repositories: []
},
local: {
lists: [],
databases: []
},
},
};
@@ -163,14 +167,16 @@ describe('db panel', async () => {
it('should render owner list nodes', async () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [],
owners: ['owner1', 'owner2'],
repositories: []
},
local: {
lists: [],
databases: []
databases: {
remote: {
repositoryLists: [],
owners: ['owner1', 'owner2'],
repositories: []
},
local: {
lists: [],
databases: []
},
},
};
@@ -196,14 +202,16 @@ describe('db panel', async () => {
it('should render repository nodes', async () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [],
owners: [],
repositories: ['owner1/repo1', 'owner1/repo2']
},
local: {
lists: [],
databases: []
databases: {
remote: {
repositoryLists: [],
owners: [],
repositories: ['owner1/repo1', 'owner1/repo2']
},
local: {
lists: [],
databases: []
},
},
};

View File

@@ -0,0 +1,13 @@
{
"databases": {
"remote": {
"repositoryLists": [],
"owners": [],
"repositories": []
},
"local": {
"lists": [],
"databases": []
}
}
}

View File

@@ -1,46 +1,52 @@
{
"remote": {
"repositoryLists": [
{
"name": "repoList1",
"repositories": ["foo/bar", "foo/baz"]
}
],
"owners": [],
"repositories": ["owner/repo1", "owner/repo2", "owner/repo3"]
"databases": {
"remote": {
"repositoryLists": [
{
"name": "repoList1",
"repositories": ["foo/bar", "foo/baz"]
}
],
"owners": [],
"repositories": ["owner/repo1", "owner/repo2", "owner/repo3"]
},
"local": {
"lists": [
{
"name": "localList1",
"databases": [
{
"name": "foo/bar",
"dateAdded": 1668096745193,
"language": "go",
"storagePath": "/path/to/database/"
}
]
},
{
"name": "localList2",
"databases": [
{
"name": "foo/baz",
"dateAdded": 1668096760848,
"language": "javascript",
"storagePath": "/path/to/database/"
}
]
}
],
"databases": [
{
"name": "example-db",
"dateAdded": 1668096927267,
"language": "ruby",
"storagePath": "/path/to/database/"
}
]
}
},
"local": {
"lists": [
{
"name": "localList1",
"databases": [
{
"name": "foo/bar",
"dateAdded": 1668096745193,
"language": "go",
"storagePath": "/path/to/database/"
}
]
},
{
"name": "localList2",
"databases": [
{
"name": "foo/baz",
"dateAdded": 1668096760848,
"language": "javascript",
"storagePath": "/path/to/database/"
}
]
}
],
"databases": [
{
"name": "example-db",
"dateAdded": 1668096927267,
"language": "ruby",
"storagePath": "/path/to/database/"
}
]
"selected": {
"kind": "configDefined",
"value": "path.to.database"
}
}

View File

@@ -29,12 +29,14 @@ describe('db config store', async () => {
await configStore.initialize();
expect(await fs.pathExists(configPath)).to.be.true;
const config = configStore.getConfig().value;
expect(config.remote.repositoryLists).to.be.empty;
expect(config.remote.owners).to.be.empty;
expect(config.remote.repositories).to.be.empty;
expect(config.local.lists).to.be.empty;
expect(config.local.databases).to.be.empty;
expect(config.databases.remote.repositoryLists).to.be.empty;
expect(config.databases.remote.owners).to.be.empty;
expect(config.databases.remote.repositories).to.be.empty;
expect(config.databases.local.lists).to.be.empty;
expect(config.databases.local.databases).to.be.empty;
expect(config.selected).to.be.undefined;
});
it('should load an existing config', async () => {
@@ -46,20 +48,20 @@ describe('db config store', async () => {
await configStore.initialize();
const config = configStore.getConfig().value;
expect(config.remote.repositoryLists).to.have.length(1);
expect(config.remote.repositoryLists[0]).to.deep.equal({
expect(config.databases.remote.repositoryLists).to.have.length(1);
expect(config.databases.remote.repositoryLists[0]).to.deep.equal({
name: 'repoList1',
repositories: ['foo/bar', 'foo/baz']
});
expect(config.remote.owners).to.be.empty;
expect(config.remote.repositories).to.have.length(3);
expect(config.remote.repositories).to.deep.equal([
expect(config.databases.remote.owners).to.be.empty;
expect(config.databases.remote.repositories).to.have.length(3);
expect(config.databases.remote.repositories).to.deep.equal([
'owner/repo1',
'owner/repo2',
'owner/repo3',
]);
expect(config.local.lists).to.have.length(2);
expect(config.local.lists[0]).to.deep.equal({
expect(config.databases.local.lists).to.have.length(2);
expect(config.databases.local.lists[0]).to.deep.equal({
name: 'localList1',
databases: [
{
@@ -70,13 +72,32 @@ describe('db config store', async () => {
},
],
});
expect(config.local.databases).to.have.length(1);
expect(config.local.databases[0]).to.deep.equal({
expect(config.databases.local.databases).to.have.length(1);
expect(config.databases.local.databases[0]).to.deep.equal({
name: 'example-db',
dateAdded: 1668096927267,
language: 'ruby',
storagePath: '/path/to/database/',
});
expect(config.selected).to.deep.equal({
kind: 'configDefined',
value: 'path.to.database',
});
});
it('should load an existing config without selected db', async () => {
const testDataStoragePathWithout = path.join(__dirname, 'data', 'without-selected');
const app = createMockApp({
extensionPath,
workspaceStoragePath: testDataStoragePathWithout
});
const configStore = new DbConfigStore(app);
await configStore.initialize();
const config = configStore.getConfig().value;
expect(config.selected).to.be.undefined;
});
it('should not allow modification of the config', async () => {
@@ -88,9 +109,9 @@ describe('db config store', async () => {
await configStore.initialize();
const config = configStore.getConfig().value;
config.remote.repositoryLists = [];
config.databases.remote.repositoryLists = [];
const reRetrievedConfig = configStore.getConfig().value;
expect(reRetrievedConfig.remote.repositoryLists).to.have.length(1);
expect(reRetrievedConfig.databases.remote.repositoryLists).to.have.length(1);
});
});

View File

@@ -11,15 +11,17 @@ describe('db config validation', async () => {
// We're intentionally bypassing the type check because we'd
// like to make sure validation errors are highlighted.
const dbConfig = {
'remote': {
'repositoryLists': [
{
'name': 'repoList1',
'repositories': ['foo/bar', 'foo/baz']
}
],
'repositories': ['owner/repo1', 'owner/repo2', 'owner/repo3'],
'somethingElse': 'bar'
'databases': {
'remote': {
'repositoryLists': [
{
'name': 'repoList1',
'repositories': ['foo/bar', 'foo/baz']
}
],
'repositories': ['owner/repo1', 'owner/repo2', 'owner/repo3'],
'somethingElse': 'bar'
}
}
} as any as DbConfig;
@@ -27,8 +29,8 @@ describe('db config validation', async () => {
expect(validationOutput).to.have.length(3);
expect(validationOutput[0]).to.deep.equal(' must have required property \'local\'');
expect(validationOutput[1]).to.deep.equal('/remote must have required property \'owners\'');
expect(validationOutput[2]).to.deep.equal('/remote must NOT have additional properties');
expect(validationOutput[0]).to.deep.equal('/databases must have required property \'local\'');
expect(validationOutput[1]).to.deep.equal('/databases/remote must have required property \'owners\'');
expect(validationOutput[2]).to.deep.equal('/databases/remote must NOT have additional properties');
});
});

View File

@@ -8,15 +8,17 @@ describe('db tree creator', () => {
describe('createRemoteTree', () => {
it('should build root node and system defined lists', () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [],
owners: [],
repositories: []
databases: {
remote: {
repositoryLists: [],
owners: [],
repositories: []
},
local: {
lists: [],
databases: []
}
},
local: {
lists: [],
databases: []
}
};
const dbTreeRoot = createRemoteTree(dbConfig);
@@ -46,32 +48,34 @@ describe('db tree creator', () => {
it('should create remote user defined list nodes', () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [
{
name: 'my-list-1',
repositories: [
'owner1/repo1',
'owner1/repo2',
'owner2/repo1'
]
},
{
name: 'my-list-2',
repositories: [
'owner3/repo1',
'owner3/repo2',
'owner4/repo1'
]
}
],
owners: [],
repositories: []
databases: {
remote: {
repositoryLists: [
{
name: 'my-list-1',
repositories: [
'owner1/repo1',
'owner1/repo2',
'owner2/repo1'
]
},
{
name: 'my-list-2',
repositories: [
'owner3/repo1',
'owner3/repo2',
'owner4/repo1'
]
}
],
owners: [],
repositories: []
},
local: {
lists: [],
databases: []
},
},
local: {
lists: [],
databases: []
}
};
const dbTreeRoot = createRemoteTree(dbConfig);
@@ -85,16 +89,16 @@ describe('db tree creator', () => {
expect(repositoryListNodes.length).to.equal(2);
expect(repositoryListNodes[0]).to.deep.equal({
kind: DbItemKind.RemoteUserDefinedList,
listName: dbConfig.remote.repositoryLists[0].name,
repos: dbConfig.remote.repositoryLists[0].repositories.map((repo) => ({
listName: dbConfig.databases.remote.repositoryLists[0].name,
repos: dbConfig.databases.remote.repositoryLists[0].repositories.map((repo) => ({
kind: DbItemKind.RemoteRepo,
repoFullName: repo
}))
});
expect(repositoryListNodes[1]).to.deep.equal({
kind: DbItemKind.RemoteUserDefinedList,
listName: dbConfig.remote.repositoryLists[1].name,
repos: dbConfig.remote.repositoryLists[1].repositories.map((repo) => ({
listName: dbConfig.databases.remote.repositoryLists[1].name,
repos: dbConfig.databases.remote.repositoryLists[1].repositories.map((repo) => ({
kind: DbItemKind.RemoteRepo,
repoFullName: repo
}))
@@ -103,17 +107,19 @@ describe('db tree creator', () => {
it('should create remote owner nodes', () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [],
owners: [
'owner1',
'owner2'
],
repositories: []
},
local: {
lists: [],
databases: []
databases: {
remote: {
repositoryLists: [],
owners: [
'owner1',
'owner2'
],
repositories: []
},
local: {
lists: [],
databases: []
}
}
};
@@ -128,28 +134,30 @@ describe('db tree creator', () => {
expect(ownerNodes.length).to.equal(2);
expect(ownerNodes[0]).to.deep.equal({
kind: DbItemKind.RemoteOwner,
ownerName: dbConfig.remote.owners[0]
ownerName: dbConfig.databases.remote.owners[0]
});
expect(ownerNodes[1]).to.deep.equal({
kind: DbItemKind.RemoteOwner,
ownerName: dbConfig.remote.owners[1]
ownerName: dbConfig.databases.remote.owners[1]
});
});
it('should create remote repo nodes', () => {
const dbConfig: DbConfig = {
remote: {
repositoryLists: [],
owners: [],
repositories: [
'owner1/repo1',
'owner1/repo2',
'owner2/repo1'
]
},
local: {
lists: [],
databases: []
databases: {
remote: {
repositoryLists: [],
owners: [],
repositories: [
'owner1/repo1',
'owner1/repo2',
'owner2/repo1'
]
},
local: {
lists: [],
databases: []
},
}
};
@@ -164,15 +172,15 @@ describe('db tree creator', () => {
expect(repoNodes.length).to.equal(3);
expect(repoNodes[0]).to.deep.equal({
kind: DbItemKind.RemoteRepo,
repoFullName: dbConfig.remote.repositories[0]
repoFullName: dbConfig.databases.remote.repositories[0]
});
expect(repoNodes[1]).to.deep.equal({
kind: DbItemKind.RemoteRepo,
repoFullName: dbConfig.remote.repositories[1]
repoFullName: dbConfig.databases.remote.repositories[1]
});
expect(repoNodes[2]).to.deep.equal({
kind: DbItemKind.RemoteRepo,
repoFullName: dbConfig.remote.repositories[2]
repoFullName: dbConfig.databases.remote.repositories[2]
});
});
});

View File

@@ -4,112 +4,138 @@
"$schema": {
"type": "string"
},
"remote": {
"databases": {
"type": "object",
"properties": {
"repositoryLists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"repositories": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-_\\.]+/[a-zA-Z0-9-_\\.]+$"
}
"remote": {
"type": "object",
"properties": {
"repositoryLists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"repositories": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-_\\.]+/[a-zA-Z0-9-_\\.]+$"
}
}
},
"required": ["name", "repositories"],
"additionalProperties": false
}
},
"required": ["name", "repositories"],
"additionalProperties": false
}
"owners": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-_\\.]+$"
}
},
"repositories": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-_\\.]+/[a-zA-Z0-9-_\\.]+$"
}
}
},
"required": ["repositoryLists", "owners", "repositories"],
"additionalProperties": false
},
"owners": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-_\\.]+$"
}
},
"repositories": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-_\\.]+/[a-zA-Z0-9-_\\.]+$"
}
"local": {
"type": "object",
"properties": {
"lists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"databases": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"dateAdded": {
"type": "number"
},
"language": {
"type": "string"
},
"storagePath": {
"type": "string"
}
},
"required": [
"name",
"dateAdded",
"language",
"storagePath"
],
"additionalProperties": false
}
}
},
"required": ["name", "databases"],
"additionalProperties": false
}
},
"databases": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"dateAdded": {
"type": "number"
},
"language": {
"type": "string"
},
"storagePath": {
"type": "string"
}
},
"required": ["name", "dateAdded", "language", "storagePath"],
"additionalProperties": false
}
}
},
"required": ["lists", "databases"],
"additionalProperties": false
}
},
"required": ["repositoryLists", "owners", "repositories"],
"required": ["remote", "local"],
"additionalProperties": false
},
"local": {
"selected": {
"type": "object",
"properties": {
"lists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"databases": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"dateAdded": {
"type": "number"
},
"language": {
"type": "string"
},
"storagePath": {
"type": "string"
}
},
"required": ["name", "dateAdded", "language", "storagePath"],
"additionalProperties": false
}
}
},
"required": ["name", "databases"],
"additionalProperties": false
}
"kind": {
"type": "string",
"enum": ["configDefined", "remoteSystemDefinedList"]
},
"databases": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"dateAdded": {
"type": "number"
},
"language": {
"type": "string"
},
"storagePath": {
"type": "string"
}
},
"required": ["name", "dateAdded", "language", "storagePath"],
"additionalProperties": false
}
"value": {
"type": "string"
}
},
"required": ["lists", "databases"],
"required": ["kind", "value"],
"additionalProperties": false
}
},
"required": ["remote", "local"],
"required": ["databases"],
"additionalProperties": false
}