Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
"editor.formatOnSave": true
},
"editor.codeActionsOnSave": {
"source.fixAll": true
"source.fixAll": "explicit"
}
}
2 changes: 1 addition & 1 deletion src/api/database.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ export default class DatabaseRepository {
public async remove(database: Database): Promise<void> {
const couch = await this.connection.instance();

await couch.db.destroy(database.label);
await couch.db.destroy(database.id!);
}
}
55 changes: 51 additions & 4 deletions src/api/document.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@ import { DocumentGetResponse } from 'nano';
import { Database, Document } from '../provider/couch.collection';
import ConnectionService from '../service/connection.service';
import { CouchResponse } from './couch.interface';
import LoggerService from '../service/logger.service';
import { TextDecoder } from 'util';

export const PAGE_SIZE = 10;

export default class DocumentRepository {
public database?: Database;

public constructor(private readonly connection: ConnectionService) {}
private readonly logger: LoggerService;

public constructor(private readonly connection: ConnectionService) {
this.logger = new LoggerService('DocumentRepository');
}

public async connect(): Promise<void> {
if (this.database) {
return;
}

await this.connection.instance();

this.logger.info('Connected to CouchDB');
}

public setActiveDatabase(database?: Database): void {
this.database = database;
Expand All @@ -24,7 +40,7 @@ export default class DocumentRepository {
const couch = await this.connection.instance();

const response = await couch.request({
db: this.database.label,
db: this.database.id,
path: '_all_docs',
method: 'post',
body: {
Expand All @@ -39,12 +55,33 @@ export default class DocumentRepository {
};
}

public async get(document: Document): Promise<DocumentGetResponse> {
public async get(document: {
source: string;
_id: string;
}): Promise<DocumentGetResponse> {
const couch = await this.connection.instance();

const db = couch.use(document.source);

return await db.get(document._id, {});
}

public async put(document: Document): Promise<{ok: boolean, rev: string}> {
this.logger.info('Writing document to database', document._id, {
rev: document._rev
});

const couch = await this.connection.instance();

const db = couch.use(document.source);

return db.get(document._id, {});
const content = JSON.parse(new TextDecoder().decode(document.getContent(true, true)));

const response = await db.insert(content);

this.logger.info('Response', document._id, response);

return {ok: response.ok, rev: response.rev};
}

public async remove(document: Document): Promise<void> {
Expand All @@ -54,4 +91,14 @@ export default class DocumentRepository {

await db.destroy(document._id, document._rev);
}

public async check(document: Document): Promise<void> {
const couch = await this.connection.instance();

const db = couch.use(document.source);

const response = await db.head(document._id);

return;
}
}
47 changes: 34 additions & 13 deletions src/controller/document.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,13 @@ import CouchItem from '../provider/couch.item';
import DocumentStore from '../core/document.store';
import { CouchDocumentProvider } from '../provider/couch.document.provider';
import { Document } from '../provider/couch.collection';
import EditorService from '../service/editor.service';

export default class DocumentController {
private readonly editorService: EditorService;

constructor(
private readonly documentStore: DocumentStore,
private readonly documentProvider: CouchDocumentProvider,
private readonly documentView: vscode.TreeView<CouchItem>,
private readonly context: vscode.ExtensionContext
) {
this.editorService = new EditorService(context);
}
private readonly documentView: vscode.TreeView<CouchItem>
) {}

public async refreshDocuments(): Promise<void> {
try {
Expand Down Expand Up @@ -59,18 +53,45 @@ export default class DocumentController {

public async openDocument(document: Document): Promise<void> {
try {
const data = await this.documentStore.get(document);

this.documentProvider.refresh(this.documentView);

document.setRev(data._rev);
document.setContent(JSON.stringify(data, null, '\t'));
await this.editorService.openDocument(document);
// open the document in a new editor
const doc = await vscode.workspace.openTextDocument(document.uri);

// set json language mode
await vscode.languages.setTextDocumentLanguage(doc, 'json');

vscode.window.showTextDocument(doc);
} catch (error) {
vscode.window.showErrorMessage('Document was removed.');

await this.documentStore.remove(document);
this.documentProvider.refresh(this.documentView);
}
}

public async writeDocument(uri: vscode.Uri): Promise<void> {
const document = this.documentStore.findByURI(uri);

try {
if (!document) {
throw new Error('Document not found.');
}

const result = await this.documentStore.put(uri, document.getContent(true, true));

if (!result) {
// something went wrong during update

// try fetching document
const checkDoc = await this.documentStore.get(uri);

}

await this.documentStore.refresh(document);
this.documentProvider.refresh(this.documentView);
} catch (error: any) {
vscode.window.showErrorMessage(error.message);
}
}
}
2 changes: 1 addition & 1 deletion src/core/database.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class DatabaseStore extends DataStore<Database> {

this.data.push(database);

this.data = this.data.filter((entry) => entry.type !== ViewType.EMPTY);
this.data = this.data.filter((entry) => entry.viewType !== ViewType.EMPTY);
++this.total;

return database;
Expand Down
106 changes: 96 additions & 10 deletions src/core/document.store.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import * as vscode from 'vscode';
import { TextDecoder } from 'util';
import { CouchResponse } from '../api/couch.interface';
import DataStore from '../api/data.interface';
import DocumentRepository from '../api/document.repository';
import { Document, Empty, Load } from '../provider/couch.collection';
import CouchItem from '../provider/couch.item';
import { DocumentGetResponse } from 'nano';
import LoggerService from '../service/logger.service';

export default class DocumentStore extends DataStore<CouchItem> {
private total = 0;

private logger: LoggerService;

constructor(private readonly documentRepository: DocumentRepository) {
super();

this.logger = new LoggerService('DocumentStore');
}

public list(): CouchItem[] {
Expand All @@ -29,8 +34,76 @@ export default class DocumentStore extends DataStore<CouchItem> {
return data;
}

public async get(document: Document): Promise<DocumentGetResponse> {
return this.documentRepository.get(document);
public async check(uri: vscode.Uri): Promise<void> {
const document = this.findByURI(uri);
if (!document) {
throw new Error('Document not found');
}

const result = await this.documentRepository.check(document);
}

public async get(uri: vscode.Uri): Promise<Document> {
// Check if document is already in store
let document = this.findByURI(uri);

const documentName = uri.path.split('/').pop() as string;

if (!document) {
try {
const data = await this.documentRepository.get({source: uri.authority, _id: documentName});
document = new Document({
id: data._id,
value: {
rev: data._rev,
},
}, uri.authority);

document.setContent(data);

return document;
} catch (error) {
throw new Error('Document not found');
}
}

if (!document) {
throw new Error('Document not found');
}

const data = await this.documentRepository.get(document);
document.setContent(data); // update doc with current data

return document;
}

public async put(uri: vscode.Uri, data: Uint8Array): Promise<boolean> {
const document = this.findByURI(uri);
if (!document) {
throw new Error('Document not found');
}

const content = JSON.parse(new TextDecoder().decode(data));
const { ok, rev } = await this.documentRepository.put(document);

// document might have been updated or deleted
if (!ok) {
return false;
}

document.setRev(rev);

return true;
}

public findByURI(uri: vscode.Uri): Document | undefined {
return this.data.find((d) => {
if (d instanceof Document) {
return d.uri.toString() === uri.toString();
}

return false;
}) as Document;
}

public async remove(document: Document): Promise<void> {
Expand All @@ -40,13 +113,13 @@ export default class DocumentStore extends DataStore<CouchItem> {
// TODO: Handle expected empty document
}

this.data = this.data.filter((d) => (d as Document)._id !== document._id);
this.data = this.data.filter((d) => (d as Document).uri.toString() !== document.uri.toString());

--this.total;
}

public async refresh(document: Document): Promise<void> {
const index = this.data.findIndex((d) => d.id === document.id);
const index = this.data.findIndex((d) => (d as Document).uri.toString() === document.uri.toString());

if (index === -1) {
return;
Expand All @@ -55,6 +128,23 @@ export default class DocumentStore extends DataStore<CouchItem> {
this.data[index] = document;
}

public async sync(): Promise<void> {
// documents to update upstream
const documents = this.data.filter((d) => (d as Document).dirty);

for (const document of documents) {
const doc = document as Document;

const response = await this.documentRepository.put(doc);
doc.dirty = false;
doc.setRev(response.rev);

this.refresh(doc);
}

this.logger.info('Synced documents', undefined, this.data);
}

public clear(): void {
this.data = [];
this.total = 0;
Expand All @@ -78,11 +168,7 @@ export default class DocumentStore extends DataStore<CouchItem> {
)
.map(
(document: CouchResponse) =>
new Document(
document,
this.documentRepository.database!.label,
vscode.TreeItemCollapsibleState.None
)
new Document(document, this.documentRepository.database!.id!)
);

this.data = this.data.concat(data);
Expand Down
Loading