Skip to content

Commit ca1e09e

Browse files
committed
doc is writable
1 parent 6866548 commit ca1e09e

File tree

6 files changed

+96
-69
lines changed

6 files changed

+96
-69
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
"editor.formatOnSave": true
1414
},
1515
"editor.codeActionsOnSave": {
16-
"source.fixAll": true
16+
"source.fixAll": "explicit"
1717
}
1818
}

src/api/document.repository.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ export default class DocumentRepository {
5050
return await db.get(document._id, {});
5151
}
5252

53+
public async put(document: Document, content: any): Promise<string> {
54+
const couch = await this.connection.instance();
55+
56+
const db = couch.use(document.source);
57+
58+
const response = await db.insert(content);
59+
60+
return response.rev;
61+
}
62+
5363
public async remove(document: Document): Promise<void> {
5464
const couch = await this.connection.instance();
5565

src/core/document.store.ts

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ import DataStore from '../api/data.interface';
44
import DocumentRepository from '../api/document.repository';
55
import { Document, Empty, Load } from '../provider/couch.collection';
66
import CouchItem from '../provider/couch.item';
7-
import { DocumentGetResponse } from 'nano';
87

98
export default class DocumentStore extends DataStore<CouchItem> {
10-
public active?: DocumentGetResponse;
11-
129
private total = 0;
1310

1411
constructor(private readonly documentRepository: DocumentRepository) {
@@ -31,31 +28,41 @@ export default class DocumentStore extends DataStore<CouchItem> {
3128
return data;
3229
}
3330

34-
public async get(document: {
35-
source: string;
36-
_id: string;
37-
}): Promise<Document> {
31+
public async get(uri: vscode.Uri): Promise<Document> {
32+
const document = this.findByURI(uri);
33+
if (!document) {
34+
throw new Error('Document not found');
35+
}
36+
3837
const data = await this.documentRepository.get(document);
38+
document.setContent(data); // update doc with current data
3939

40-
let doc = this.data.find((d) => (d as Document)._id! === document._id);
41-
if (!doc) {
42-
doc = new Document(
43-
{
44-
id: data._id,
45-
value: {
46-
rev: data._rev,
47-
},
48-
},
49-
document.source
50-
);
40+
return document;
41+
}
5142

52-
this.data.push(doc);
43+
public async put(uri: vscode.Uri, data: Uint8Array): Promise<void> {
44+
const document = this.findByURI(uri);
45+
if (!document) {
46+
throw new Error('Document not found');
5347
}
5448

55-
(doc as Document).mtime = Date.now();
56-
(doc as Document).setContent(JSON.stringify(data, null, '\t'));
49+
try {
50+
// inject current _id and _rev into content for update
51+
const content = JSON.parse(data.toString());
52+
content['_id'] = document._id;
53+
54+
if (document._rev) {
55+
content['_rev'] = document._rev;
56+
}
57+
58+
const rev = await this.documentRepository.put(document, content);
5759

58-
return doc as Document;
60+
document.setContent(content);
61+
document.setRev(rev);
62+
63+
} catch (error) {
64+
throw new Error('Cannot update document.');
65+
}
5966
}
6067

6168
public findByURI(uri: vscode.Uri): Document | undefined {
@@ -81,7 +88,7 @@ export default class DocumentStore extends DataStore<CouchItem> {
8188
}
8289

8390
public async refresh(document: Document): Promise<void> {
84-
const index = this.data.findIndex((d) => d.id === document.id);
91+
const index = this.data.findIndex((d) => (d as Document)._id === document._id);
8592

8693
if (index === -1) {
8794
return;

src/provider/couch.collection.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import CouchItem, { ViewType } from './couch.item';
33
import { extensionId, iconPath } from '../extension';
44
import { CouchResponse } from '../api/couch.interface';
55
import { CouchFileSystemProvider } from './filesystem.provider';
6+
import { TextEncoder } from 'util';
67

78
export class Database extends CouchItem {
89
constructor(label: string) {
@@ -31,8 +32,6 @@ export class Document extends CouchItem implements vscode.FileStat {
3132

3233
public _rev: string;
3334

34-
public content: string;
35-
3635
public source: string;
3736

3837
uri: vscode.Uri;
@@ -47,6 +46,8 @@ export class Document extends CouchItem implements vscode.FileStat {
4746

4847
public permissions?: vscode.FilePermission | undefined;
4948

49+
private content: any;
50+
5051
constructor(document: CouchResponse, source: string) {
5152
super(document.id, vscode.TreeItemCollapsibleState.None);
5253

@@ -80,10 +81,24 @@ export class Document extends CouchItem implements vscode.FileStat {
8081
return ViewType.DOCUMENT;
8182
}
8283

83-
public setContent(content: string): void {
84+
public setContent(content: any): void {
85+
delete content._id;
86+
if (content._rev) {
87+
this.setRev(content._rev);
88+
89+
delete content._rev;
90+
}
91+
8492
this.content = content;
8593

86-
this.size = Buffer.from(content).byteLength;
94+
this.size = Buffer.from(JSON.stringify(this.content, null, '\t')).byteLength;
95+
this.mtime = Date.now();
96+
}
97+
98+
public getContent(): Uint8Array {
99+
const content = JSON.stringify(this.content, null, '\t');
100+
101+
return new TextEncoder().encode(content);
87102
}
88103

89104
public setRev(rev: string): void {

src/provider/couch.document.provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as vscode from 'vscode';
2-
import CouchItem, { ViewType } from './couch.item';
2+
import CouchItem from './couch.item';
33
import DocumentStore from '../core/document.store';
44

55
export class CouchDocumentProvider
Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,81 @@
11
import * as vscode from 'vscode';
22
import DocumentStore from '../core/document.store';
3-
import { TextEncoder } from 'util';
4-
import { Document } from './couch.collection';
3+
import { FileSystemError } from 'vscode';
54

65
export class CouchFileSystemProvider implements vscode.FileSystemProvider {
76
public static scheme = 'couchdb';
87

9-
onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
8+
private readonly _emitter = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
9+
10+
readonly onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]> = this._emitter.event;
11+
private readonly watchers = new Map<string, Set<Symbol>>;
1012

1113
constructor(private readonly documentStore: DocumentStore) {
12-
this.onDidChangeFile = new vscode.EventEmitter<
13-
vscode.FileChangeEvent[]
14-
>().event;
14+
this._emitter = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
15+
this.onDidChangeFile = this._emitter.event;
1516
}
1617

17-
public watch(
18-
uri: vscode.Uri,
19-
options: { readonly recursive: boolean; readonly excludes: readonly string[] }
20-
): vscode.Disposable {
21-
console.log('watch', uri, options);
22-
23-
return new vscode.Disposable(() => {});
18+
watch(resource: vscode.Uri): vscode.Disposable {
19+
return new vscode.Disposable(() => undefined);
2420
}
2521

26-
public stat(uri: vscode.Uri): vscode.FileStat {
27-
const doc = this.documentStore.findByURI(uri);
22+
public async stat(uri: vscode.Uri): Promise<vscode.FileStat> {
23+
const document = this.documentStore.findByURI(uri);
24+
if (!document) {
25+
throw FileSystemError.FileNotFound;
26+
}
2827

2928
return {
3029
type: vscode.FileType.File,
31-
ctime: (doc as Document).ctime,
32-
mtime: (doc as Document).mtime,
33-
size: new TextEncoder().encode((doc as Document).content || '').length,
30+
ctime: 0,
31+
mtime: document.mtime,
32+
size: document.size,
3433
};
3534
}
3635

3736
public readDirectory(
3837
uri: vscode.Uri
3938
): [string, vscode.FileType][] | Thenable<[string, vscode.FileType][]> {
40-
console.log('readDirectory', uri);
41-
4239
return Promise.reject();
4340
}
4441

4542
public createDirectory(uri: vscode.Uri): void | Thenable<void> {
46-
console.log('createDirectory', uri);
47-
4843
return Promise.reject();
4944
}
5045

5146
public async readFile(uri: vscode.Uri): Promise<Uint8Array> {
52-
const document = await this.documentStore.get({
53-
source: uri.authority,
54-
_id: uri.path.slice(1),
55-
});
56-
47+
const document = await this.documentStore.get(uri);
5748
if (!document) {
58-
throw new Error('Document not found');
49+
throw FileSystemError.FileNotFound;
5950
}
6051

61-
return new TextEncoder().encode(document.content);
52+
try {
53+
return document.getContent();
54+
} catch (error) {
55+
throw new Error();
56+
}
6257
}
6358

64-
public writeFile(
59+
public async writeFile(
6560
uri: vscode.Uri,
6661
content: Uint8Array,
6762
options: { readonly create: boolean; readonly overwrite: boolean }
68-
): void | Thenable<void> {
69-
console.log('writeFile', uri, content, options);
70-
71-
return Promise.reject();
63+
): Promise<void> {
64+
try {
65+
await this.documentStore.put(uri, content);
66+
67+
this._emitter.fire([{ type: vscode.FileChangeType.Changed, uri }]);
68+
69+
return Promise.resolve();
70+
} catch (error) {
71+
return Promise.reject(error);
72+
}
7273
}
7374

7475
public delete(
7576
uri: vscode.Uri,
7677
options: { readonly recursive: boolean }
7778
): void | Thenable<void> {
78-
console.log('delete', uri, options);
79-
8079
return Promise.reject();
8180
}
8281

@@ -85,8 +84,6 @@ export class CouchFileSystemProvider implements vscode.FileSystemProvider {
8584
newUri: vscode.Uri,
8685
options: { readonly overwrite: boolean }
8786
): void | Thenable<void> {
88-
console.log('rename', oldUri, newUri, options);
89-
9087
return Promise.reject();
9188
}
9289

@@ -95,8 +92,6 @@ export class CouchFileSystemProvider implements vscode.FileSystemProvider {
9592
destination: vscode.Uri,
9693
options: { readonly overwrite: boolean }
9794
): void | Thenable<void> {
98-
console.log('copy', source, destination, options);
99-
10095
return Promise.reject();
10196
}
10297
}

0 commit comments

Comments
 (0)