@codingame/monaco-vscode-2f06fe84-148e-5e6b-a7ca-c7989c5f128a-common 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/empty.js +1 -0
- package/package.json +36 -0
- package/vscode/src/vs/base/browser/indexedDB.d.ts +19 -0
- package/vscode/src/vs/base/browser/indexedDB.js +149 -0
- package/vscode/src/vs/platform/files/common/inMemoryFilesystemProvider.d.ts +60 -0
- package/vscode/src/vs/platform/files/common/inMemoryFilesystemProvider.js +223 -0
- package/vscode/src/vs/workbench/services/storage/browser/storageService.d.ts +74 -0
- package/vscode/src/vs/workbench/services/storage/browser/storageService.js +293 -0
package/empty.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export {}
|
package/package.json
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"name": "@codingame/monaco-vscode-2f06fe84-148e-5e6b-a7ca-c7989c5f128a-common",
|
3
|
+
"version": "12.0.0",
|
4
|
+
"private": false,
|
5
|
+
"description": "VSCode public API plugged on the monaco editor - common package (files, storage, user-data-profile)",
|
6
|
+
"keywords": [],
|
7
|
+
"author": {
|
8
|
+
"name": "CodinGame",
|
9
|
+
"url": "http://www.codingame.com"
|
10
|
+
},
|
11
|
+
"license": "MIT",
|
12
|
+
"repository": {
|
13
|
+
"type": "git",
|
14
|
+
"url": "git+ssh://git@github.com/CodinGame/monaco-vscode-api.git"
|
15
|
+
},
|
16
|
+
"type": "module",
|
17
|
+
"dependencies": {
|
18
|
+
"@codingame/monaco-vscode-e571cbbb-526b-5d8b-92c5-a0437d2dabb3-common": "12.0.0",
|
19
|
+
"vscode": "npm:@codingame/monaco-vscode-api@12.0.0"
|
20
|
+
},
|
21
|
+
"peerDependencies": {},
|
22
|
+
"peerDependenciesMeta": {},
|
23
|
+
"exports": {
|
24
|
+
".": {
|
25
|
+
"default": "./empty.js"
|
26
|
+
},
|
27
|
+
"./vscode/*": {
|
28
|
+
"default": "./vscode/src/*.js",
|
29
|
+
"types": "./vscode/src/*.d.ts"
|
30
|
+
},
|
31
|
+
"./*": {
|
32
|
+
"default": "./*.js",
|
33
|
+
"types": "./*.d.ts"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
export declare class DBClosedError extends Error {
|
2
|
+
readonly code = "DBClosed";
|
3
|
+
constructor(dbName: string);
|
4
|
+
}
|
5
|
+
export declare class IndexedDB {
|
6
|
+
private readonly name;
|
7
|
+
static create(name: string, version: number | undefined, stores: string[]): Promise<IndexedDB>;
|
8
|
+
private static openDatabase;
|
9
|
+
private static doOpenDatabase;
|
10
|
+
private static deleteDatabase;
|
11
|
+
private database;
|
12
|
+
private readonly pendingTransactions;
|
13
|
+
constructor(database: IDBDatabase, name: string);
|
14
|
+
hasPendingTransactions(): boolean;
|
15
|
+
close(): void;
|
16
|
+
runInTransaction<T>(store: string, transactionMode: IDBTransactionMode, dbRequestFn: (store: IDBObjectStore) => IDBRequest<T>[]): Promise<T[]>;
|
17
|
+
runInTransaction<T>(store: string, transactionMode: IDBTransactionMode, dbRequestFn: (store: IDBObjectStore) => IDBRequest<T>): Promise<T>;
|
18
|
+
getKeyValues<V>(store: string, isValid: (value: unknown) => value is V): Promise<Map<string, V>>;
|
19
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
|
2
|
+
import { toErrorMessage } from 'vscode/vscode/vs/base/common/errorMessage';
|
3
|
+
import { getErrorMessage, ErrorNoTelemetry } from 'vscode/vscode/vs/base/common/errors';
|
4
|
+
import { mark } from 'vscode/vscode/vs/base/common/performance';
|
5
|
+
|
6
|
+
class MissingStoresError extends Error {
|
7
|
+
constructor(db) {
|
8
|
+
super('Missing stores');
|
9
|
+
this.db = db;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
class DBClosedError extends Error {
|
13
|
+
constructor(dbName) {
|
14
|
+
super(`IndexedDB database '${dbName}' is closed.`);
|
15
|
+
this.code = 'DBClosed';
|
16
|
+
}
|
17
|
+
}
|
18
|
+
class IndexedDB {
|
19
|
+
static async create(name, version, stores) {
|
20
|
+
const database = await IndexedDB.openDatabase(name, version, stores);
|
21
|
+
return ( new IndexedDB(database, name));
|
22
|
+
}
|
23
|
+
static async openDatabase(name, version, stores) {
|
24
|
+
mark(`code/willOpenDatabase/${name}`);
|
25
|
+
try {
|
26
|
+
return await IndexedDB.doOpenDatabase(name, version, stores);
|
27
|
+
}
|
28
|
+
catch (err) {
|
29
|
+
if (err instanceof MissingStoresError) {
|
30
|
+
console.info(`Attempting to recreate the IndexedDB once.`, name);
|
31
|
+
try {
|
32
|
+
await IndexedDB.deleteDatabase(err.db);
|
33
|
+
}
|
34
|
+
catch (error) {
|
35
|
+
console.error(`Error while deleting the IndexedDB`, getErrorMessage(error));
|
36
|
+
throw error;
|
37
|
+
}
|
38
|
+
return await IndexedDB.doOpenDatabase(name, version, stores);
|
39
|
+
}
|
40
|
+
throw err;
|
41
|
+
}
|
42
|
+
finally {
|
43
|
+
mark(`code/didOpenDatabase/${name}`);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
static doOpenDatabase(name, version, stores) {
|
47
|
+
return ( new Promise((c, e) => {
|
48
|
+
const request = indexedDB.open(name, version);
|
49
|
+
request.onerror = () => e(request.error);
|
50
|
+
request.onsuccess = () => {
|
51
|
+
const db = request.result;
|
52
|
+
for (const store of stores) {
|
53
|
+
if (!db.objectStoreNames.contains(store)) {
|
54
|
+
console.error(`Error while opening IndexedDB. Could not find '${store}'' object store`);
|
55
|
+
e(( new MissingStoresError(db)));
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
c(db);
|
60
|
+
};
|
61
|
+
request.onupgradeneeded = () => {
|
62
|
+
const db = request.result;
|
63
|
+
for (const store of stores) {
|
64
|
+
if (!db.objectStoreNames.contains(store)) {
|
65
|
+
db.createObjectStore(store);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
};
|
69
|
+
}));
|
70
|
+
}
|
71
|
+
static deleteDatabase(database) {
|
72
|
+
return ( new Promise((c, e) => {
|
73
|
+
database.close();
|
74
|
+
const deleteRequest = indexedDB.deleteDatabase(database.name);
|
75
|
+
deleteRequest.onerror = (err) => e(deleteRequest.error);
|
76
|
+
deleteRequest.onsuccess = () => c();
|
77
|
+
}));
|
78
|
+
}
|
79
|
+
constructor(database, name) {
|
80
|
+
this.name = name;
|
81
|
+
this.database = null;
|
82
|
+
this.pendingTransactions = [];
|
83
|
+
this.database = database;
|
84
|
+
}
|
85
|
+
hasPendingTransactions() {
|
86
|
+
return this.pendingTransactions.length > 0;
|
87
|
+
}
|
88
|
+
close() {
|
89
|
+
if (this.pendingTransactions.length) {
|
90
|
+
this.pendingTransactions.splice(0, this.pendingTransactions.length).forEach(transaction => transaction.abort());
|
91
|
+
}
|
92
|
+
this.database?.close();
|
93
|
+
this.database = null;
|
94
|
+
}
|
95
|
+
async runInTransaction(store, transactionMode, dbRequestFn) {
|
96
|
+
if (!this.database) {
|
97
|
+
throw ( new DBClosedError(this.name));
|
98
|
+
}
|
99
|
+
const transaction = this.database.transaction(store, transactionMode);
|
100
|
+
this.pendingTransactions.push(transaction);
|
101
|
+
return ( new Promise((c, e) => {
|
102
|
+
transaction.oncomplete = () => {
|
103
|
+
if (Array.isArray(request)) {
|
104
|
+
c(( request.map(r => r.result)));
|
105
|
+
}
|
106
|
+
else {
|
107
|
+
c(request.result);
|
108
|
+
}
|
109
|
+
};
|
110
|
+
transaction.onerror = () => e(transaction.error ? ErrorNoTelemetry.fromError(transaction.error) : ( new ErrorNoTelemetry('unknown error')));
|
111
|
+
transaction.onabort = () => e(transaction.error ? ErrorNoTelemetry.fromError(transaction.error) : ( new ErrorNoTelemetry('unknown error')));
|
112
|
+
const request = dbRequestFn(transaction.objectStore(store));
|
113
|
+
})).finally(() => this.pendingTransactions.splice(this.pendingTransactions.indexOf(transaction), 1));
|
114
|
+
}
|
115
|
+
async getKeyValues(store, isValid) {
|
116
|
+
if (!this.database) {
|
117
|
+
throw ( new DBClosedError(this.name));
|
118
|
+
}
|
119
|
+
const transaction = this.database.transaction(store, 'readonly');
|
120
|
+
this.pendingTransactions.push(transaction);
|
121
|
+
return ( new Promise(resolve => {
|
122
|
+
const items = ( new Map());
|
123
|
+
const objectStore = transaction.objectStore(store);
|
124
|
+
const cursor = objectStore.openCursor();
|
125
|
+
if (!cursor) {
|
126
|
+
return resolve(items);
|
127
|
+
}
|
128
|
+
cursor.onsuccess = () => {
|
129
|
+
if (cursor.result) {
|
130
|
+
if (isValid(cursor.result.value)) {
|
131
|
+
items.set(( cursor.result.key.toString()), cursor.result.value);
|
132
|
+
}
|
133
|
+
cursor.result.continue();
|
134
|
+
}
|
135
|
+
else {
|
136
|
+
resolve(items);
|
137
|
+
}
|
138
|
+
};
|
139
|
+
const onError = (error) => {
|
140
|
+
console.error(`IndexedDB getKeyValues(): ${toErrorMessage(error, true)}`);
|
141
|
+
resolve(items);
|
142
|
+
};
|
143
|
+
cursor.onerror = () => onError(cursor.error);
|
144
|
+
transaction.onerror = () => onError(transaction.error);
|
145
|
+
})).finally(() => this.pendingTransactions.splice(this.pendingTransactions.indexOf(transaction), 1));
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
export { DBClosedError, IndexedDB };
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { Event } from "vscode/vscode/vs/base/common/event";
|
2
|
+
import { Disposable, IDisposable } from "vscode/vscode/vs/base/common/lifecycle";
|
3
|
+
import { ReadableStreamEvents } from "vscode/vscode/vs/base/common/stream";
|
4
|
+
import { URI } from "vscode/vscode/vs/base/common/uri";
|
5
|
+
import { IFileDeleteOptions, IFileOverwriteOptions, FileSystemProviderCapabilities, FileType, IFileWriteOptions, IFileChange, IFileSystemProviderWithFileReadWriteCapability, IStat, IWatchOptions, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileOpenOptions, IFileSystemProviderWithFileAtomicDeleteCapability, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileAtomicWriteCapability, IFileSystemProviderWithFileReadStreamCapability } from "vscode/vscode/vs/platform/files/common/files";
|
6
|
+
declare class File implements IStat {
|
7
|
+
readonly type: FileType.File;
|
8
|
+
readonly ctime: number;
|
9
|
+
mtime: number;
|
10
|
+
size: number;
|
11
|
+
name: string;
|
12
|
+
data?: Uint8Array;
|
13
|
+
constructor(name: string);
|
14
|
+
}
|
15
|
+
declare class Directory implements IStat {
|
16
|
+
readonly type: FileType.Directory;
|
17
|
+
readonly ctime: number;
|
18
|
+
mtime: number;
|
19
|
+
size: number;
|
20
|
+
name: string;
|
21
|
+
readonly entries: Map<string, File | Directory>;
|
22
|
+
constructor(name: string);
|
23
|
+
}
|
24
|
+
export declare class InMemoryFileSystemProvider extends Disposable implements IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadStreamCapability, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileAtomicWriteCapability, IFileSystemProviderWithFileAtomicDeleteCapability {
|
25
|
+
private memoryFdCounter;
|
26
|
+
private readonly fdMemory;
|
27
|
+
private _onDidChangeCapabilities;
|
28
|
+
readonly onDidChangeCapabilities: Event<void>;
|
29
|
+
private _capabilities;
|
30
|
+
get capabilities(): FileSystemProviderCapabilities;
|
31
|
+
setReadOnly(readonly: boolean): void;
|
32
|
+
root: Directory;
|
33
|
+
stat(resource: URI): Promise<IStat>;
|
34
|
+
readdir(resource: URI): Promise<[
|
35
|
+
string,
|
36
|
+
FileType
|
37
|
+
][]>;
|
38
|
+
readFile(resource: URI): Promise<Uint8Array>;
|
39
|
+
readFileStream(resource: URI): ReadableStreamEvents<Uint8Array>;
|
40
|
+
writeFile(resource: URI, content: Uint8Array, opts: IFileWriteOptions): Promise<void>;
|
41
|
+
open(resource: URI, opts: IFileOpenOptions): Promise<number>;
|
42
|
+
close(fd: number): Promise<void>;
|
43
|
+
read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number>;
|
44
|
+
write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number>;
|
45
|
+
rename(from: URI, to: URI, opts: IFileOverwriteOptions): Promise<void>;
|
46
|
+
delete(resource: URI, opts: IFileDeleteOptions): Promise<void>;
|
47
|
+
mkdir(resource: URI): Promise<void>;
|
48
|
+
private _lookup;
|
49
|
+
private _lookupAsDirectory;
|
50
|
+
private _lookupAsFile;
|
51
|
+
private _lookupParentDirectory;
|
52
|
+
private readonly _onDidChangeFile;
|
53
|
+
readonly onDidChangeFile: Event<readonly IFileChange[]>;
|
54
|
+
private _bufferedChanges;
|
55
|
+
private _fireSoonHandle?;
|
56
|
+
watch(resource: URI, opts: IWatchOptions): IDisposable;
|
57
|
+
private _fireSoon;
|
58
|
+
dispose(): void;
|
59
|
+
}
|
60
|
+
export {};
|
@@ -0,0 +1,223 @@
|
|
1
|
+
|
2
|
+
import { VSBuffer } from 'vscode/vscode/vs/base/common/buffer';
|
3
|
+
import { Emitter } from 'vscode/vscode/vs/base/common/event';
|
4
|
+
import { Disposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
5
|
+
import { basename, dirname } from 'vscode/vscode/vs/base/common/resources';
|
6
|
+
import { newWriteableStream } from 'vscode/vscode/vs/base/common/stream';
|
7
|
+
import { FileType, FileSystemProviderCapabilities, createFileSystemProviderError, FileSystemProviderErrorCode, FileChangeType } from 'vscode/vscode/vs/platform/files/common/files';
|
8
|
+
|
9
|
+
class File {
|
10
|
+
constructor(name) {
|
11
|
+
this.type = FileType.File;
|
12
|
+
this.ctime = Date.now();
|
13
|
+
this.mtime = Date.now();
|
14
|
+
this.size = 0;
|
15
|
+
this.name = name;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
class Directory {
|
19
|
+
constructor(name) {
|
20
|
+
this.type = FileType.Directory;
|
21
|
+
this.ctime = Date.now();
|
22
|
+
this.mtime = Date.now();
|
23
|
+
this.size = 0;
|
24
|
+
this.name = name;
|
25
|
+
this.entries = ( new Map());
|
26
|
+
}
|
27
|
+
}
|
28
|
+
class InMemoryFileSystemProvider extends Disposable {
|
29
|
+
constructor() {
|
30
|
+
super(...arguments);
|
31
|
+
this.memoryFdCounter = 0;
|
32
|
+
this.fdMemory = ( new Map());
|
33
|
+
this._onDidChangeCapabilities = this._register(( new Emitter()));
|
34
|
+
this.onDidChangeCapabilities = this._onDidChangeCapabilities.event;
|
35
|
+
this._capabilities = FileSystemProviderCapabilities.FileReadWrite | FileSystemProviderCapabilities.PathCaseSensitive;
|
36
|
+
this.root = ( new Directory(''));
|
37
|
+
this._onDidChangeFile = this._register(( new Emitter()));
|
38
|
+
this.onDidChangeFile = this._onDidChangeFile.event;
|
39
|
+
this._bufferedChanges = [];
|
40
|
+
}
|
41
|
+
get capabilities() { return this._capabilities; }
|
42
|
+
setReadOnly(readonly) {
|
43
|
+
const isReadonly = !!(this._capabilities & FileSystemProviderCapabilities.Readonly);
|
44
|
+
if (readonly !== isReadonly) {
|
45
|
+
this._capabilities = readonly ? FileSystemProviderCapabilities.Readonly | FileSystemProviderCapabilities.PathCaseSensitive | FileSystemProviderCapabilities.FileReadWrite
|
46
|
+
: FileSystemProviderCapabilities.FileReadWrite | FileSystemProviderCapabilities.PathCaseSensitive;
|
47
|
+
this._onDidChangeCapabilities.fire();
|
48
|
+
}
|
49
|
+
}
|
50
|
+
async stat(resource) {
|
51
|
+
return this._lookup(resource, false);
|
52
|
+
}
|
53
|
+
async readdir(resource) {
|
54
|
+
const entry = this._lookupAsDirectory(resource, false);
|
55
|
+
const result = [];
|
56
|
+
entry.entries.forEach((child, name) => result.push([name, child.type]));
|
57
|
+
return result;
|
58
|
+
}
|
59
|
+
async readFile(resource) {
|
60
|
+
const data = this._lookupAsFile(resource, false).data;
|
61
|
+
if (data) {
|
62
|
+
return data;
|
63
|
+
}
|
64
|
+
throw createFileSystemProviderError('file not found', FileSystemProviderErrorCode.FileNotFound);
|
65
|
+
}
|
66
|
+
readFileStream(resource) {
|
67
|
+
const data = this._lookupAsFile(resource, false).data;
|
68
|
+
const stream = newWriteableStream(data => VSBuffer.concat(( data.map(data => VSBuffer.wrap(data)))).buffer);
|
69
|
+
stream.end(data);
|
70
|
+
return stream;
|
71
|
+
}
|
72
|
+
async writeFile(resource, content, opts) {
|
73
|
+
const basename$1 = basename(resource);
|
74
|
+
const parent = this._lookupParentDirectory(resource);
|
75
|
+
let entry = parent.entries.get(basename$1);
|
76
|
+
if (entry instanceof Directory) {
|
77
|
+
throw createFileSystemProviderError('file is directory', FileSystemProviderErrorCode.FileIsADirectory);
|
78
|
+
}
|
79
|
+
if (!entry && !opts.create) {
|
80
|
+
throw createFileSystemProviderError('file not found', FileSystemProviderErrorCode.FileNotFound);
|
81
|
+
}
|
82
|
+
if (entry && opts.create && !opts.overwrite) {
|
83
|
+
throw createFileSystemProviderError('file exists already', FileSystemProviderErrorCode.FileExists);
|
84
|
+
}
|
85
|
+
if (!entry) {
|
86
|
+
entry = ( new File(basename$1));
|
87
|
+
parent.entries.set(basename$1, entry);
|
88
|
+
this._fireSoon({ type: FileChangeType.ADDED, resource });
|
89
|
+
}
|
90
|
+
entry.mtime = Date.now();
|
91
|
+
entry.size = content.byteLength;
|
92
|
+
entry.data = content;
|
93
|
+
this._fireSoon({ type: FileChangeType.UPDATED, resource });
|
94
|
+
}
|
95
|
+
open(resource, opts) {
|
96
|
+
const data = this._lookupAsFile(resource, false).data;
|
97
|
+
if (data) {
|
98
|
+
const fd = this.memoryFdCounter++;
|
99
|
+
this.fdMemory.set(fd, data);
|
100
|
+
return Promise.resolve(fd);
|
101
|
+
}
|
102
|
+
throw createFileSystemProviderError('file not found', FileSystemProviderErrorCode.FileNotFound);
|
103
|
+
}
|
104
|
+
close(fd) {
|
105
|
+
this.fdMemory.delete(fd);
|
106
|
+
return Promise.resolve();
|
107
|
+
}
|
108
|
+
read(fd, pos, data, offset, length) {
|
109
|
+
const memory = this.fdMemory.get(fd);
|
110
|
+
if (!memory) {
|
111
|
+
throw createFileSystemProviderError(`No file with that descriptor open`, FileSystemProviderErrorCode.Unavailable);
|
112
|
+
}
|
113
|
+
const toWrite = VSBuffer.wrap(memory).slice(pos, pos + length);
|
114
|
+
data.set(toWrite.buffer, offset);
|
115
|
+
return Promise.resolve(toWrite.byteLength);
|
116
|
+
}
|
117
|
+
write(fd, pos, data, offset, length) {
|
118
|
+
const memory = this.fdMemory.get(fd);
|
119
|
+
if (!memory) {
|
120
|
+
throw createFileSystemProviderError(`No file with that descriptor open`, FileSystemProviderErrorCode.Unavailable);
|
121
|
+
}
|
122
|
+
const toWrite = VSBuffer.wrap(data).slice(offset, offset + length);
|
123
|
+
memory.set(toWrite.buffer, pos);
|
124
|
+
return Promise.resolve(toWrite.byteLength);
|
125
|
+
}
|
126
|
+
async rename(from, to, opts) {
|
127
|
+
if (!opts.overwrite && this._lookup(to, true)) {
|
128
|
+
throw createFileSystemProviderError('file exists already', FileSystemProviderErrorCode.FileExists);
|
129
|
+
}
|
130
|
+
const entry = this._lookup(from, false);
|
131
|
+
const oldParent = this._lookupParentDirectory(from);
|
132
|
+
const newParent = this._lookupParentDirectory(to);
|
133
|
+
const newName = basename(to);
|
134
|
+
oldParent.entries.delete(entry.name);
|
135
|
+
entry.name = newName;
|
136
|
+
newParent.entries.set(newName, entry);
|
137
|
+
this._fireSoon({ type: FileChangeType.DELETED, resource: from }, { type: FileChangeType.ADDED, resource: to });
|
138
|
+
}
|
139
|
+
async delete(resource, opts) {
|
140
|
+
const dirname$1 = dirname(resource);
|
141
|
+
const basename$1 = basename(resource);
|
142
|
+
const parent = this._lookupAsDirectory(dirname$1, false);
|
143
|
+
if (( parent.entries.has(basename$1))) {
|
144
|
+
parent.entries.delete(basename$1);
|
145
|
+
parent.mtime = Date.now();
|
146
|
+
parent.size -= 1;
|
147
|
+
this._fireSoon({ type: FileChangeType.UPDATED, resource: dirname$1 }, { resource, type: FileChangeType.DELETED });
|
148
|
+
}
|
149
|
+
}
|
150
|
+
async mkdir(resource) {
|
151
|
+
if (this._lookup(resource, true)) {
|
152
|
+
throw createFileSystemProviderError('file exists already', FileSystemProviderErrorCode.FileExists);
|
153
|
+
}
|
154
|
+
const basename$1 = basename(resource);
|
155
|
+
const dirname$1 = dirname(resource);
|
156
|
+
const parent = this._lookupAsDirectory(dirname$1, false);
|
157
|
+
const entry = ( new Directory(basename$1));
|
158
|
+
parent.entries.set(entry.name, entry);
|
159
|
+
parent.mtime = Date.now();
|
160
|
+
parent.size += 1;
|
161
|
+
this._fireSoon({ type: FileChangeType.UPDATED, resource: dirname$1 }, { type: FileChangeType.ADDED, resource });
|
162
|
+
}
|
163
|
+
_lookup(uri, silent) {
|
164
|
+
const parts = uri.path.split('/');
|
165
|
+
let entry = this.root;
|
166
|
+
for (const part of parts) {
|
167
|
+
if (!part) {
|
168
|
+
continue;
|
169
|
+
}
|
170
|
+
let child;
|
171
|
+
if (entry instanceof Directory) {
|
172
|
+
child = entry.entries.get(part);
|
173
|
+
}
|
174
|
+
if (!child) {
|
175
|
+
if (!silent) {
|
176
|
+
throw createFileSystemProviderError('file not found', FileSystemProviderErrorCode.FileNotFound);
|
177
|
+
}
|
178
|
+
else {
|
179
|
+
return undefined;
|
180
|
+
}
|
181
|
+
}
|
182
|
+
entry = child;
|
183
|
+
}
|
184
|
+
return entry;
|
185
|
+
}
|
186
|
+
_lookupAsDirectory(uri, silent) {
|
187
|
+
const entry = this._lookup(uri, silent);
|
188
|
+
if (entry instanceof Directory) {
|
189
|
+
return entry;
|
190
|
+
}
|
191
|
+
throw createFileSystemProviderError('file not a directory', FileSystemProviderErrorCode.FileNotADirectory);
|
192
|
+
}
|
193
|
+
_lookupAsFile(uri, silent) {
|
194
|
+
const entry = this._lookup(uri, silent);
|
195
|
+
if (entry instanceof File) {
|
196
|
+
return entry;
|
197
|
+
}
|
198
|
+
throw createFileSystemProviderError('file is a directory', FileSystemProviderErrorCode.FileIsADirectory);
|
199
|
+
}
|
200
|
+
_lookupParentDirectory(uri) {
|
201
|
+
const dirname$1 = dirname(uri);
|
202
|
+
return this._lookupAsDirectory(dirname$1, false);
|
203
|
+
}
|
204
|
+
watch(resource, opts) {
|
205
|
+
return Disposable.None;
|
206
|
+
}
|
207
|
+
_fireSoon(...changes) {
|
208
|
+
this._bufferedChanges.push(...changes);
|
209
|
+
if (this._fireSoonHandle) {
|
210
|
+
clearTimeout(this._fireSoonHandle);
|
211
|
+
}
|
212
|
+
this._fireSoonHandle = setTimeout(() => {
|
213
|
+
this._onDidChangeFile.fire(this._bufferedChanges);
|
214
|
+
this._bufferedChanges.length = 0;
|
215
|
+
}, 5);
|
216
|
+
}
|
217
|
+
dispose() {
|
218
|
+
super.dispose();
|
219
|
+
this.fdMemory.clear();
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
export { InMemoryFileSystemProvider };
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import { Disposable, IDisposable } from "vscode/vscode/vs/base/common/lifecycle";
|
2
|
+
import { IStorage, IStorageDatabase, IStorageItemsChangeEvent, IUpdateRequest } from "vscode/vscode/vs/base/parts/storage/common/storage";
|
3
|
+
import { ILogService } from "vscode/vscode/vs/platform/log/common/log.service";
|
4
|
+
import { AbstractStorageService, StorageScope } from "vscode/vscode/vs/platform/storage/common/storage";
|
5
|
+
import { IUserDataProfile } from "vscode/vscode/vs/platform/userDataProfile/common/userDataProfile";
|
6
|
+
import { IAnyWorkspaceIdentifier } from "vscode/vscode/vs/platform/workspace/common/workspace";
|
7
|
+
import { IUserDataProfileService } from "vscode/vscode/vs/workbench/services/userDataProfile/common/userDataProfile.service";
|
8
|
+
export declare class BrowserStorageService extends AbstractStorageService {
|
9
|
+
private workspace;
|
10
|
+
private readonly userDataProfileService;
|
11
|
+
private readonly logService;
|
12
|
+
private static BROWSER_DEFAULT_FLUSH_INTERVAL;
|
13
|
+
private applicationStorage;
|
14
|
+
private applicationStorageDatabase;
|
15
|
+
private readonly applicationStoragePromise;
|
16
|
+
private profileStorage;
|
17
|
+
private profileStorageDatabase;
|
18
|
+
private profileStorageProfile;
|
19
|
+
private readonly profileStorageDisposables;
|
20
|
+
private workspaceStorage;
|
21
|
+
private workspaceStorageDatabase;
|
22
|
+
private readonly workspaceStorageDisposables;
|
23
|
+
get hasPendingUpdate(): boolean;
|
24
|
+
constructor(workspace: IAnyWorkspaceIdentifier, userDataProfileService: IUserDataProfileService, logService: ILogService);
|
25
|
+
private registerListeners;
|
26
|
+
protected doInitialize(): Promise<void>;
|
27
|
+
private createApplicationStorage;
|
28
|
+
private createProfileStorage;
|
29
|
+
private createWorkspaceStorage;
|
30
|
+
private updateIsNew;
|
31
|
+
protected getStorage(scope: StorageScope): IStorage | undefined;
|
32
|
+
protected getLogDetails(scope: StorageScope): string | undefined;
|
33
|
+
protected switchToProfile(toProfile: IUserDataProfile): Promise<void>;
|
34
|
+
protected switchToWorkspace(toWorkspace: IAnyWorkspaceIdentifier, preserveData: boolean): Promise<void>;
|
35
|
+
protected shouldFlushWhenIdle(): boolean;
|
36
|
+
close(): void;
|
37
|
+
clear(): Promise<void>;
|
38
|
+
hasScope(scope: IAnyWorkspaceIdentifier | IUserDataProfile): boolean;
|
39
|
+
}
|
40
|
+
interface IIndexedDBStorageDatabase extends IStorageDatabase, IDisposable {
|
41
|
+
readonly name: string;
|
42
|
+
readonly hasPendingUpdate: boolean;
|
43
|
+
clear(): Promise<void>;
|
44
|
+
}
|
45
|
+
interface IndexedDBStorageDatabaseOptions {
|
46
|
+
id: string;
|
47
|
+
broadcastChanges?: boolean;
|
48
|
+
}
|
49
|
+
export declare class IndexedDBStorageDatabase extends Disposable implements IIndexedDBStorageDatabase {
|
50
|
+
private readonly logService;
|
51
|
+
static createApplicationStorage(logService: ILogService): Promise<IIndexedDBStorageDatabase>;
|
52
|
+
static createProfileStorage(profile: IUserDataProfile, logService: ILogService): Promise<IIndexedDBStorageDatabase>;
|
53
|
+
static createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase>;
|
54
|
+
static create(options: IndexedDBStorageDatabaseOptions, logService: ILogService): Promise<IIndexedDBStorageDatabase>;
|
55
|
+
private static readonly STORAGE_DATABASE_PREFIX;
|
56
|
+
private static readonly STORAGE_OBJECT_STORE;
|
57
|
+
private readonly _onDidChangeItemsExternal;
|
58
|
+
readonly onDidChangeItemsExternal: import("vscode/vscode/vs/base/common/event").Event<IStorageItemsChangeEvent>;
|
59
|
+
private broadcastChannel;
|
60
|
+
private pendingUpdate;
|
61
|
+
get hasPendingUpdate(): boolean;
|
62
|
+
readonly name: string;
|
63
|
+
private readonly whenConnected;
|
64
|
+
private constructor();
|
65
|
+
private registerListeners;
|
66
|
+
private connect;
|
67
|
+
getItems(): Promise<Map<string, string>>;
|
68
|
+
updateItems(request: IUpdateRequest): Promise<void>;
|
69
|
+
private doUpdateItems;
|
70
|
+
optimize(): Promise<void>;
|
71
|
+
close(): Promise<void>;
|
72
|
+
clear(): Promise<void>;
|
73
|
+
}
|
74
|
+
export {};
|
@@ -0,0 +1,293 @@
|
|
1
|
+
|
2
|
+
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6';
|
3
|
+
import { BroadcastDataChannel } from '@codingame/monaco-vscode-e571cbbb-526b-5d8b-92c5-a0437d2dabb3-common/vscode/vs/base/browser/broadcast';
|
4
|
+
import { isSafari } from 'vscode/vscode/vs/base/browser/browser';
|
5
|
+
import { getActiveWindow } from 'vscode/vscode/vs/base/browser/dom';
|
6
|
+
import { IndexedDB } from '../../../../base/browser/indexedDB.js';
|
7
|
+
import { DeferredPromise, Promises } from 'vscode/vscode/vs/base/common/async';
|
8
|
+
import { toErrorMessage } from 'vscode/vscode/vs/base/common/errorMessage';
|
9
|
+
import { Emitter } from 'vscode/vscode/vs/base/common/event';
|
10
|
+
import { DisposableStore, Disposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
11
|
+
import { assertIsDefined } from 'vscode/vscode/vs/base/common/types';
|
12
|
+
import { Storage, InMemoryStorageDatabase, isStorageItemsChangeEvent } from 'vscode/vscode/vs/base/parts/storage/common/storage';
|
13
|
+
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service';
|
14
|
+
import { AbstractStorageService, StorageScope, isProfileUsingDefaultStorage, IS_NEW_KEY, StorageTarget } from 'vscode/vscode/vs/platform/storage/common/storage';
|
15
|
+
import { isUserDataProfile } from 'vscode/vscode/vs/platform/userDataProfile/common/userDataProfile';
|
16
|
+
|
17
|
+
var BrowserStorageService_1;
|
18
|
+
let BrowserStorageService = class BrowserStorageService extends AbstractStorageService {
|
19
|
+
static { BrowserStorageService_1 = this; }
|
20
|
+
static { this.BROWSER_DEFAULT_FLUSH_INTERVAL = 5 * 1000; }
|
21
|
+
get hasPendingUpdate() {
|
22
|
+
return Boolean(this.applicationStorageDatabase?.hasPendingUpdate ||
|
23
|
+
this.profileStorageDatabase?.hasPendingUpdate ||
|
24
|
+
this.workspaceStorageDatabase?.hasPendingUpdate);
|
25
|
+
}
|
26
|
+
constructor(workspace, userDataProfileService, logService) {
|
27
|
+
super({ flushInterval: BrowserStorageService_1.BROWSER_DEFAULT_FLUSH_INTERVAL });
|
28
|
+
this.workspace = workspace;
|
29
|
+
this.userDataProfileService = userDataProfileService;
|
30
|
+
this.logService = logService;
|
31
|
+
this.applicationStoragePromise = ( new DeferredPromise());
|
32
|
+
this.profileStorageProfile = this.userDataProfileService.currentProfile;
|
33
|
+
this.profileStorageDisposables = this._register(( new DisposableStore()));
|
34
|
+
this.workspaceStorageDisposables = this._register(( new DisposableStore()));
|
35
|
+
this.registerListeners();
|
36
|
+
}
|
37
|
+
registerListeners() {
|
38
|
+
this._register(this.userDataProfileService.onDidChangeCurrentProfile(e => e.join(this.switchToProfile(e.profile))));
|
39
|
+
}
|
40
|
+
async doInitialize() {
|
41
|
+
await Promises.settled([
|
42
|
+
this.createApplicationStorage(),
|
43
|
+
this.createProfileStorage(this.profileStorageProfile),
|
44
|
+
this.createWorkspaceStorage()
|
45
|
+
]);
|
46
|
+
}
|
47
|
+
async createApplicationStorage() {
|
48
|
+
const applicationStorageIndexedDB = await IndexedDBStorageDatabase.createApplicationStorage(this.logService);
|
49
|
+
this.applicationStorageDatabase = this._register(applicationStorageIndexedDB);
|
50
|
+
this.applicationStorage = this._register(( new Storage(this.applicationStorageDatabase)));
|
51
|
+
this._register(this.applicationStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.APPLICATION, e)));
|
52
|
+
await this.applicationStorage.init();
|
53
|
+
this.updateIsNew(this.applicationStorage);
|
54
|
+
this.applicationStoragePromise.complete({ indexedDb: applicationStorageIndexedDB, storage: this.applicationStorage });
|
55
|
+
}
|
56
|
+
async createProfileStorage(profile) {
|
57
|
+
this.profileStorageDisposables.clear();
|
58
|
+
this.profileStorageProfile = profile;
|
59
|
+
if (isProfileUsingDefaultStorage(this.profileStorageProfile)) {
|
60
|
+
const { indexedDb: applicationStorageIndexedDB, storage: applicationStorage } = await this.applicationStoragePromise.p;
|
61
|
+
this.profileStorageDatabase = applicationStorageIndexedDB;
|
62
|
+
this.profileStorage = applicationStorage;
|
63
|
+
this.profileStorageDisposables.add(this.profileStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.PROFILE, e)));
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
const profileStorageIndexedDB = await IndexedDBStorageDatabase.createProfileStorage(this.profileStorageProfile, this.logService);
|
67
|
+
this.profileStorageDatabase = this.profileStorageDisposables.add(profileStorageIndexedDB);
|
68
|
+
this.profileStorage = this.profileStorageDisposables.add(( new Storage(this.profileStorageDatabase)));
|
69
|
+
this.profileStorageDisposables.add(this.profileStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.PROFILE, e)));
|
70
|
+
await this.profileStorage.init();
|
71
|
+
this.updateIsNew(this.profileStorage);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
async createWorkspaceStorage() {
|
75
|
+
this.workspaceStorageDisposables.clear();
|
76
|
+
const workspaceStorageIndexedDB = await IndexedDBStorageDatabase.createWorkspaceStorage(this.workspace.id, this.logService);
|
77
|
+
this.workspaceStorageDatabase = this.workspaceStorageDisposables.add(workspaceStorageIndexedDB);
|
78
|
+
this.workspaceStorage = this.workspaceStorageDisposables.add(( new Storage(this.workspaceStorageDatabase)));
|
79
|
+
this.workspaceStorageDisposables.add(this.workspaceStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.WORKSPACE, e)));
|
80
|
+
await this.workspaceStorage.init();
|
81
|
+
this.updateIsNew(this.workspaceStorage);
|
82
|
+
}
|
83
|
+
updateIsNew(storage) {
|
84
|
+
const firstOpen = storage.getBoolean(IS_NEW_KEY);
|
85
|
+
if (firstOpen === undefined) {
|
86
|
+
storage.set(IS_NEW_KEY, true);
|
87
|
+
}
|
88
|
+
else if (firstOpen) {
|
89
|
+
storage.set(IS_NEW_KEY, false);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
getStorage(scope) {
|
93
|
+
switch (scope) {
|
94
|
+
case StorageScope.APPLICATION:
|
95
|
+
return this.applicationStorage;
|
96
|
+
case StorageScope.PROFILE:
|
97
|
+
return this.profileStorage;
|
98
|
+
default:
|
99
|
+
return this.workspaceStorage;
|
100
|
+
}
|
101
|
+
}
|
102
|
+
getLogDetails(scope) {
|
103
|
+
switch (scope) {
|
104
|
+
case StorageScope.APPLICATION:
|
105
|
+
return this.applicationStorageDatabase?.name;
|
106
|
+
case StorageScope.PROFILE:
|
107
|
+
return this.profileStorageDatabase?.name;
|
108
|
+
default:
|
109
|
+
return this.workspaceStorageDatabase?.name;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
async switchToProfile(toProfile) {
|
113
|
+
if (!this.canSwitchProfile(this.profileStorageProfile, toProfile)) {
|
114
|
+
return;
|
115
|
+
}
|
116
|
+
const oldProfileStorage = assertIsDefined(this.profileStorage);
|
117
|
+
const oldItems = oldProfileStorage.items;
|
118
|
+
if (oldProfileStorage !== this.applicationStorage) {
|
119
|
+
await oldProfileStorage.close();
|
120
|
+
}
|
121
|
+
await this.createProfileStorage(toProfile);
|
122
|
+
this.switchData(oldItems, assertIsDefined(this.profileStorage), StorageScope.PROFILE);
|
123
|
+
}
|
124
|
+
async switchToWorkspace(toWorkspace, preserveData) {
|
125
|
+
const oldWorkspaceStorage = assertIsDefined(this.workspaceStorage);
|
126
|
+
const oldItems = preserveData ? oldWorkspaceStorage.items : ( new Map());
|
127
|
+
await oldWorkspaceStorage.close();
|
128
|
+
this.workspace = toWorkspace;
|
129
|
+
await this.createWorkspaceStorage();
|
130
|
+
this.switchData(oldItems, assertIsDefined(this.workspaceStorage), StorageScope.WORKSPACE);
|
131
|
+
}
|
132
|
+
shouldFlushWhenIdle() {
|
133
|
+
return getActiveWindow().document.hasFocus() && !this.hasPendingUpdate;
|
134
|
+
}
|
135
|
+
close() {
|
136
|
+
if (isSafari) {
|
137
|
+
this.applicationStorage?.close();
|
138
|
+
this.profileStorageDatabase?.close();
|
139
|
+
this.workspaceStorageDatabase?.close();
|
140
|
+
}
|
141
|
+
this.dispose();
|
142
|
+
}
|
143
|
+
async clear() {
|
144
|
+
for (const scope of [StorageScope.APPLICATION, StorageScope.PROFILE, StorageScope.WORKSPACE]) {
|
145
|
+
for (const target of [StorageTarget.USER, StorageTarget.MACHINE]) {
|
146
|
+
for (const key of ( this.keys(scope, target))) {
|
147
|
+
this.remove(key, scope);
|
148
|
+
}
|
149
|
+
}
|
150
|
+
await this.getStorage(scope)?.whenFlushed();
|
151
|
+
}
|
152
|
+
await Promises.settled([
|
153
|
+
this.applicationStorageDatabase?.clear() ?? Promise.resolve(),
|
154
|
+
this.profileStorageDatabase?.clear() ?? Promise.resolve(),
|
155
|
+
this.workspaceStorageDatabase?.clear() ?? Promise.resolve()
|
156
|
+
]);
|
157
|
+
}
|
158
|
+
hasScope(scope) {
|
159
|
+
if (isUserDataProfile(scope)) {
|
160
|
+
return this.profileStorageProfile.id === scope.id;
|
161
|
+
}
|
162
|
+
return this.workspace.id === scope.id;
|
163
|
+
}
|
164
|
+
};
|
165
|
+
BrowserStorageService = BrowserStorageService_1 = ( __decorate([
|
166
|
+
( __param(2, ILogService))
|
167
|
+
], BrowserStorageService));
|
168
|
+
class InMemoryIndexedDBStorageDatabase extends InMemoryStorageDatabase {
|
169
|
+
constructor() {
|
170
|
+
super(...arguments);
|
171
|
+
this.hasPendingUpdate = false;
|
172
|
+
this.name = 'in-memory-indexedb-storage';
|
173
|
+
}
|
174
|
+
async clear() {
|
175
|
+
(await this.getItems()).clear();
|
176
|
+
}
|
177
|
+
dispose() {
|
178
|
+
}
|
179
|
+
}
|
180
|
+
class IndexedDBStorageDatabase extends Disposable {
|
181
|
+
static async createApplicationStorage(logService) {
|
182
|
+
return IndexedDBStorageDatabase.create({ id: 'global', broadcastChanges: true }, logService);
|
183
|
+
}
|
184
|
+
static async createProfileStorage(profile, logService) {
|
185
|
+
return IndexedDBStorageDatabase.create({ id: `global-${profile.id}`, broadcastChanges: true }, logService);
|
186
|
+
}
|
187
|
+
static async createWorkspaceStorage(workspaceId, logService) {
|
188
|
+
return IndexedDBStorageDatabase.create({ id: workspaceId }, logService);
|
189
|
+
}
|
190
|
+
static async create(options, logService) {
|
191
|
+
try {
|
192
|
+
const database = ( new IndexedDBStorageDatabase(options, logService));
|
193
|
+
await database.whenConnected;
|
194
|
+
return database;
|
195
|
+
}
|
196
|
+
catch (error) {
|
197
|
+
logService.error(`[IndexedDB Storage ${options.id}] create(): ${toErrorMessage(error, true)}`);
|
198
|
+
return ( new InMemoryIndexedDBStorageDatabase());
|
199
|
+
}
|
200
|
+
}
|
201
|
+
static { this.STORAGE_DATABASE_PREFIX = 'vscode-web-state-db-'; }
|
202
|
+
static { this.STORAGE_OBJECT_STORE = 'ItemTable'; }
|
203
|
+
get hasPendingUpdate() { return !!this.pendingUpdate; }
|
204
|
+
constructor(options, logService) {
|
205
|
+
super();
|
206
|
+
this.logService = logService;
|
207
|
+
this._onDidChangeItemsExternal = this._register(( new Emitter()));
|
208
|
+
this.onDidChangeItemsExternal = this._onDidChangeItemsExternal.event;
|
209
|
+
this.pendingUpdate = undefined;
|
210
|
+
this.name = `${IndexedDBStorageDatabase.STORAGE_DATABASE_PREFIX}${options.id}`;
|
211
|
+
this.broadcastChannel = options.broadcastChanges ? this._register(( new BroadcastDataChannel(this.name))) : undefined;
|
212
|
+
this.whenConnected = this.connect();
|
213
|
+
this.registerListeners();
|
214
|
+
}
|
215
|
+
registerListeners() {
|
216
|
+
if (this.broadcastChannel) {
|
217
|
+
this._register(this.broadcastChannel.onDidReceiveData(data => {
|
218
|
+
if (isStorageItemsChangeEvent(data)) {
|
219
|
+
this._onDidChangeItemsExternal.fire(data);
|
220
|
+
}
|
221
|
+
}));
|
222
|
+
}
|
223
|
+
}
|
224
|
+
async connect() {
|
225
|
+
try {
|
226
|
+
return await IndexedDB.create(this.name, undefined, [IndexedDBStorageDatabase.STORAGE_OBJECT_STORE]);
|
227
|
+
}
|
228
|
+
catch (error) {
|
229
|
+
this.logService.error(`[IndexedDB Storage ${this.name}] connect() error: ${toErrorMessage(error)}`);
|
230
|
+
throw error;
|
231
|
+
}
|
232
|
+
}
|
233
|
+
async getItems() {
|
234
|
+
const db = await this.whenConnected;
|
235
|
+
function isValid(value) {
|
236
|
+
return typeof value === 'string';
|
237
|
+
}
|
238
|
+
return db.getKeyValues(IndexedDBStorageDatabase.STORAGE_OBJECT_STORE, isValid);
|
239
|
+
}
|
240
|
+
async updateItems(request) {
|
241
|
+
let didUpdate = false;
|
242
|
+
this.pendingUpdate = this.doUpdateItems(request);
|
243
|
+
try {
|
244
|
+
didUpdate = await this.pendingUpdate;
|
245
|
+
}
|
246
|
+
finally {
|
247
|
+
this.pendingUpdate = undefined;
|
248
|
+
}
|
249
|
+
if (this.broadcastChannel && didUpdate) {
|
250
|
+
const event = {
|
251
|
+
changed: request.insert,
|
252
|
+
deleted: request.delete
|
253
|
+
};
|
254
|
+
this.broadcastChannel.postData(event);
|
255
|
+
}
|
256
|
+
}
|
257
|
+
async doUpdateItems(request) {
|
258
|
+
const toInsert = request.insert;
|
259
|
+
const toDelete = request.delete;
|
260
|
+
if ((!toInsert && !toDelete) || (toInsert?.size === 0 && toDelete?.size === 0)) {
|
261
|
+
return false;
|
262
|
+
}
|
263
|
+
const db = await this.whenConnected;
|
264
|
+
await db.runInTransaction(IndexedDBStorageDatabase.STORAGE_OBJECT_STORE, 'readwrite', objectStore => {
|
265
|
+
const requests = [];
|
266
|
+
if (toInsert) {
|
267
|
+
for (const [key, value] of toInsert) {
|
268
|
+
requests.push(objectStore.put(value, key));
|
269
|
+
}
|
270
|
+
}
|
271
|
+
if (toDelete) {
|
272
|
+
for (const key of toDelete) {
|
273
|
+
requests.push(objectStore.delete(key));
|
274
|
+
}
|
275
|
+
}
|
276
|
+
return requests;
|
277
|
+
});
|
278
|
+
return true;
|
279
|
+
}
|
280
|
+
async optimize() {
|
281
|
+
}
|
282
|
+
async close() {
|
283
|
+
const db = await this.whenConnected;
|
284
|
+
await this.pendingUpdate;
|
285
|
+
return db.close();
|
286
|
+
}
|
287
|
+
async clear() {
|
288
|
+
const db = await this.whenConnected;
|
289
|
+
await db.runInTransaction(IndexedDBStorageDatabase.STORAGE_OBJECT_STORE, 'readwrite', objectStore => objectStore.clear());
|
290
|
+
}
|
291
|
+
}
|
292
|
+
|
293
|
+
export { BrowserStorageService, IndexedDBStorageDatabase };
|