@theia/filesystem 1.65.0-next.55 → 1.65.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/lib/browser/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser/download/file-download-command-contribution.js +3 -3
- package/lib/browser/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser/download/file-download-frontend-module.d.ts.map +1 -1
- package/lib/browser/download/file-download-frontend-module.js +2 -1
- package/lib/browser/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser/download/file-download-service.d.ts +2 -10
- package/lib/browser/download/file-download-service.d.ts.map +1 -1
- package/lib/browser/download/file-download-service.js +8 -7
- package/lib/browser/download/file-download-service.js.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.d.ts +1 -1
- package/lib/browser/file-tree/file-tree-widget.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.js +3 -3
- package/lib/browser/file-tree/file-tree-widget.js.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.d.ts +2 -2
- package/lib/browser/filesystem-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.js +3 -3
- package/lib/browser/filesystem-frontend-contribution.js.map +1 -1
- package/lib/browser/filesystem-frontend-module.d.ts.map +1 -1
- package/lib/browser/filesystem-frontend-module.js +3 -2
- package/lib/browser/filesystem-frontend-module.js.map +1 -1
- package/lib/browser/{file-upload-service.d.ts → upload/file-upload-service-impl.d.ts} +16 -52
- package/lib/browser/upload/file-upload-service-impl.d.ts.map +1 -0
- package/lib/browser/{file-upload-service.js → upload/file-upload-service-impl.js} +27 -27
- package/lib/browser/upload/file-upload-service-impl.js.map +1 -0
- package/lib/browser-only/browser-only-filesystem-frontend-module.d.ts.map +1 -1
- package/lib/browser-only/browser-only-filesystem-frontend-module.js +8 -0
- package/lib/browser-only/browser-only-filesystem-frontend-module.js.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts +15 -0
- package/lib/browser-only/download/file-download-command-contribution.d.ts.map +1 -0
- package/lib/browser-only/download/file-download-command-contribution.js +55 -0
- package/lib/browser-only/download/file-download-command-contribution.js.map +1 -0
- package/lib/browser-only/download/file-download-frontend-module.d.ts +4 -0
- package/lib/browser-only/download/file-download-frontend-module.d.ts.map +1 -0
- package/lib/browser-only/download/file-download-frontend-module.js +27 -0
- package/lib/browser-only/download/file-download-frontend-module.js.map +1 -0
- package/lib/browser-only/download/file-download-service.d.ts +86 -0
- package/lib/browser-only/download/file-download-service.d.ts.map +1 -0
- package/lib/browser-only/download/file-download-service.js +551 -0
- package/lib/browser-only/download/file-download-service.js.map +1 -0
- package/lib/browser-only/file-search.d.ts +38 -0
- package/lib/browser-only/file-search.d.ts.map +1 -0
- package/lib/browser-only/file-search.js +153 -0
- package/lib/browser-only/file-search.js.map +1 -0
- package/lib/browser-only/opfs-filesystem-initialization.d.ts +4 -2
- package/lib/browser-only/opfs-filesystem-initialization.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.js +4 -1
- package/lib/browser-only/opfs-filesystem-initialization.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.d.ts +89 -12
- package/lib/browser-only/opfs-filesystem-provider.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.js +345 -181
- package/lib/browser-only/opfs-filesystem-provider.js.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.d.ts +67 -0
- package/lib/browser-only/upload/file-upload-service-impl.d.ts.map +1 -0
- package/lib/browser-only/upload/file-upload-service-impl.js +328 -0
- package/lib/browser-only/upload/file-upload-service-impl.js.map +1 -0
- package/lib/common/download/file-download.d.ts +17 -0
- package/lib/common/download/file-download.d.ts.map +1 -0
- package/lib/common/download/{file-download-data.js → file-download.js} +3 -2
- package/lib/common/download/file-download.js.map +1 -0
- package/lib/common/files.d.ts +8 -1
- package/lib/common/files.d.ts.map +1 -1
- package/lib/common/files.js +35 -1
- package/lib/common/files.js.map +1 -1
- package/lib/common/io.js +7 -1
- package/lib/common/io.js.map +1 -1
- package/lib/common/upload/file-upload.d.ts +45 -0
- package/lib/common/upload/file-upload.d.ts.map +1 -0
- package/{src/common/download/file-download-data.ts → lib/common/upload/file-upload.js} +6 -13
- package/lib/common/upload/file-upload.js.map +1 -0
- package/lib/node/disk-file-system-provider.d.ts.map +1 -1
- package/lib/node/disk-file-system-provider.js +2 -4
- package/lib/node/disk-file-system-provider.js.map +1 -1
- package/lib/node/download/file-download-handler.js +2 -2
- package/lib/node/download/file-download-handler.js.map +1 -1
- package/lib/node/filesystem-backend-module.js +1 -1
- package/lib/node/filesystem-backend-module.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts +2 -2
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.js.map +1 -1
- package/lib/node/upload/node-file-upload-service.d.ts.map +1 -0
- package/lib/node/{node-file-upload-service.js → upload/node-file-upload-service.js} +1 -1
- package/lib/node/upload/node-file-upload-service.js.map +1 -0
- package/package.json +10 -5
- package/src/browser/download/file-download-command-contribution.ts +1 -1
- package/src/browser/download/file-download-frontend-module.ts +3 -2
- package/src/browser/download/file-download-service.ts +7 -12
- package/src/browser/file-tree/file-tree-widget.tsx +1 -1
- package/src/browser/filesystem-frontend-contribution.ts +2 -2
- package/src/browser/filesystem-frontend-module.ts +3 -2
- package/src/browser/{file-upload-service.ts → upload/file-upload-service-impl.ts} +31 -72
- package/src/browser-only/browser-only-filesystem-frontend-module.ts +10 -0
- package/src/browser-only/download/file-download-command-contribution.ts +56 -0
- package/src/browser-only/download/file-download-frontend-module.ts +26 -0
- package/src/browser-only/download/file-download-service.ts +726 -0
- package/src/browser-only/file-search.ts +170 -0
- package/src/browser-only/opfs-filesystem-initialization.ts +7 -4
- package/src/browser-only/opfs-filesystem-provider.ts +402 -189
- package/src/browser-only/upload/file-upload-service-impl.ts +408 -0
- package/src/common/download/file-download.ts +40 -0
- package/src/common/files.ts +42 -1
- package/src/common/io.ts +6 -1
- package/src/common/upload/file-upload.ts +65 -0
- package/src/node/disk-file-system-provider.ts +3 -4
- package/src/node/download/file-download-handler.ts +1 -1
- package/src/node/filesystem-backend-module.ts +1 -1
- package/src/node/parcel-watcher/parcel-filesystem-service.ts +2 -2
- package/src/node/{node-file-upload-service.ts → upload/node-file-upload-service.ts} +1 -1
- package/lib/browser/file-upload-service.d.ts.map +0 -1
- package/lib/browser/file-upload-service.js.map +0 -1
- package/lib/common/download/file-download-data.d.ts +0 -7
- package/lib/common/download/file-download-data.d.ts.map +0 -1
- package/lib/common/download/file-download-data.js.map +0 -1
- package/lib/node/node-file-upload-service.d.ts.map +0 -1
- package/lib/node/node-file-upload-service.js.map +0 -1
- /package/lib/node/{node-file-upload-service.d.ts → upload/node-file-upload-service.d.ts} +0 -0
|
@@ -20,18 +20,42 @@ const tslib_1 = require("tslib");
|
|
|
20
20
|
const inversify_1 = require("@theia/core/shared/inversify");
|
|
21
21
|
const files_1 = require("../common/files");
|
|
22
22
|
const core_1 = require("@theia/core");
|
|
23
|
+
const encoding_service_1 = require("@theia/core/lib/common/encoding-service");
|
|
24
|
+
const buffer_1 = require("@theia/core/lib/common/buffer");
|
|
25
|
+
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
|
|
26
|
+
const opfs_worker_1 = require("opfs-worker");
|
|
23
27
|
const opfs_filesystem_initialization_1 = require("./opfs-filesystem-initialization");
|
|
28
|
+
const stream_1 = require("@theia/core/lib/common/stream");
|
|
29
|
+
const io_1 = require("../common/io");
|
|
30
|
+
const file_uri_1 = require("@theia/core/lib/common/file-uri");
|
|
24
31
|
let OPFSFileSystemProvider = class OPFSFileSystemProvider {
|
|
25
32
|
constructor() {
|
|
26
|
-
this.
|
|
33
|
+
this.BUFFER_SIZE = 64 * 1024;
|
|
34
|
+
this.capabilities = 2 /* FileSystemProviderCapabilities.FileReadWrite */ |
|
|
35
|
+
4 /* FileSystemProviderCapabilities.FileOpenReadWriteClose */ |
|
|
36
|
+
8 /* FileSystemProviderCapabilities.FileFolderCopy */ |
|
|
37
|
+
33554432 /* FileSystemProviderCapabilities.Update */;
|
|
27
38
|
this.onDidChangeCapabilities = core_1.Event.None;
|
|
28
39
|
this.onDidChangeFileEmitter = new core_1.Emitter();
|
|
29
40
|
this.onDidChangeFile = this.onDidChangeFileEmitter.event;
|
|
30
41
|
this.onFileWatchError = core_1.Event.None;
|
|
42
|
+
this.toDispose = new core_1.DisposableCollection(this.onDidChangeFileEmitter);
|
|
31
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Initializes the OPFS file system provider
|
|
46
|
+
*/
|
|
32
47
|
init() {
|
|
33
48
|
const setup = async () => {
|
|
34
|
-
|
|
49
|
+
const root = await this.initialization.getRootDirectory();
|
|
50
|
+
const broadcastChannel = this.initialization.getBroadcastChannel();
|
|
51
|
+
// Set up file change listening via BroadcastChannel
|
|
52
|
+
broadcastChannel.onmessage = this.handleFileSystemChange.bind(this);
|
|
53
|
+
// Initialize the file system
|
|
54
|
+
this.fs = new opfs_worker_1.OPFSFileSystem({
|
|
55
|
+
root,
|
|
56
|
+
broadcastChannel,
|
|
57
|
+
hashAlgorithm: false,
|
|
58
|
+
});
|
|
35
59
|
await this.initialization.initializeFS(new Proxy(this, {
|
|
36
60
|
get(target, prop, receiver) {
|
|
37
61
|
if (prop === 'initialized') {
|
|
@@ -44,179 +68,360 @@ let OPFSFileSystemProvider = class OPFSFileSystemProvider {
|
|
|
44
68
|
};
|
|
45
69
|
this.initialized = setup();
|
|
46
70
|
}
|
|
47
|
-
|
|
48
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Watches a resource for file system changes
|
|
73
|
+
*/
|
|
74
|
+
watch(resource, opts) {
|
|
75
|
+
if (!resource || !resource.path) {
|
|
76
|
+
return core_1.Disposable.NULL;
|
|
77
|
+
}
|
|
78
|
+
const unwatch = this.fs.watch(formatPath(resource), {
|
|
79
|
+
recursive: opts.recursive,
|
|
80
|
+
exclude: opts.excludes,
|
|
81
|
+
});
|
|
82
|
+
return core_1.Disposable.create(unwatch);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates an index from the map of entries
|
|
86
|
+
*/
|
|
87
|
+
async createIndex(entries) {
|
|
88
|
+
const arrayEntries = [];
|
|
89
|
+
for (const [uri, content] of entries) {
|
|
90
|
+
arrayEntries.push([formatPath(uri), content]);
|
|
91
|
+
}
|
|
92
|
+
await this.fs.createIndex(arrayEntries);
|
|
49
93
|
}
|
|
50
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Retrieves the current file system index
|
|
96
|
+
*/
|
|
97
|
+
async index() {
|
|
98
|
+
const opfsIndex = await this.fs.index();
|
|
99
|
+
const index = new Map();
|
|
100
|
+
for (const [path, stats] of opfsIndex.entries()) {
|
|
101
|
+
const uri = new core_1.URI(path);
|
|
102
|
+
index.set(uri, formatStat(stats));
|
|
103
|
+
}
|
|
104
|
+
return index;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Clears the file system
|
|
108
|
+
*/
|
|
109
|
+
async clear() {
|
|
51
110
|
try {
|
|
52
|
-
await this.
|
|
53
|
-
await this.toFileSystemHandle(resource);
|
|
54
|
-
return true;
|
|
111
|
+
await this.fs.clear();
|
|
55
112
|
}
|
|
56
113
|
catch (error) {
|
|
114
|
+
throw toFileSystemProviderError(error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Checks if a resource exists
|
|
119
|
+
*/
|
|
120
|
+
async exists(resource) {
|
|
121
|
+
if (!resource || !resource.path) {
|
|
57
122
|
return false;
|
|
58
123
|
}
|
|
124
|
+
await this.initialized;
|
|
125
|
+
try {
|
|
126
|
+
return await this.fs.exists(formatPath(resource));
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
throw toFileSystemProviderError(error);
|
|
130
|
+
}
|
|
59
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Gets file system statistics for a resource
|
|
134
|
+
*/
|
|
60
135
|
async stat(resource) {
|
|
136
|
+
if (!resource || !resource.path) {
|
|
137
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid resource URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
138
|
+
}
|
|
139
|
+
await this.initialized;
|
|
61
140
|
try {
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const fileHandle = handle;
|
|
66
|
-
const file = await fileHandle.getFile();
|
|
67
|
-
return {
|
|
68
|
-
type: files_1.FileType.File,
|
|
69
|
-
ctime: file.lastModified,
|
|
70
|
-
mtime: file.lastModified,
|
|
71
|
-
size: file.size
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
else if (handle.kind === 'directory') {
|
|
75
|
-
return {
|
|
76
|
-
type: files_1.FileType.Directory,
|
|
77
|
-
ctime: 0,
|
|
78
|
-
mtime: 0,
|
|
79
|
-
size: 0
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
throw (0, files_1.createFileSystemProviderError)('Unknown file handle error', files_1.FileSystemProviderErrorCode.Unknown);
|
|
141
|
+
const path = formatPath(resource);
|
|
142
|
+
const stats = await this.fs.stat(path);
|
|
143
|
+
return formatStat(stats);
|
|
83
144
|
}
|
|
84
145
|
catch (error) {
|
|
85
146
|
throw toFileSystemProviderError(error);
|
|
86
147
|
}
|
|
87
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Creates a directory
|
|
151
|
+
*/
|
|
88
152
|
async mkdir(resource) {
|
|
153
|
+
if (!resource || !resource.path) {
|
|
154
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid resource URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
155
|
+
}
|
|
89
156
|
await this.initialized;
|
|
90
157
|
try {
|
|
91
|
-
|
|
158
|
+
const path = formatPath(resource);
|
|
159
|
+
await this.fs.mkdir(path, { recursive: true });
|
|
92
160
|
this.onDidChangeFileEmitter.fire([{ resource, type: 1 /* FileChangeType.ADDED */ }]);
|
|
93
161
|
}
|
|
94
162
|
catch (error) {
|
|
95
|
-
throw toFileSystemProviderError(error
|
|
163
|
+
throw toFileSystemProviderError(error);
|
|
96
164
|
}
|
|
97
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Reads directory contents
|
|
168
|
+
*/
|
|
98
169
|
async readdir(resource) {
|
|
170
|
+
if (!resource || !resource.path) {
|
|
171
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid resource URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
172
|
+
}
|
|
99
173
|
await this.initialized;
|
|
100
174
|
try {
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (handle.kind === 'file') {
|
|
108
|
-
result.push([name, files_1.FileType.File]);
|
|
109
|
-
}
|
|
110
|
-
else if (handle.kind === 'directory') {
|
|
111
|
-
result.push([name, files_1.FileType.Directory]);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return result;
|
|
175
|
+
const path = formatPath(resource);
|
|
176
|
+
const entries = await this.fs.readDir(path);
|
|
177
|
+
return entries.map(entry => [
|
|
178
|
+
entry.name,
|
|
179
|
+
entry.isFile ? files_1.FileType.File : files_1.FileType.Directory
|
|
180
|
+
]);
|
|
115
181
|
}
|
|
116
182
|
catch (error) {
|
|
117
|
-
throw toFileSystemProviderError(error
|
|
183
|
+
throw toFileSystemProviderError(error);
|
|
118
184
|
}
|
|
119
185
|
}
|
|
120
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Deletes a resource
|
|
188
|
+
*/
|
|
189
|
+
async delete(resource, opts) {
|
|
190
|
+
if (!resource || !resource.path) {
|
|
191
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid resource URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
192
|
+
}
|
|
121
193
|
await this.initialized;
|
|
122
194
|
try {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
if (parentHandle.kind !== 'directory') {
|
|
126
|
-
throw (0, files_1.createFileSystemProviderError)(new Error('Parent is not a directory'), files_1.FileSystemProviderErrorCode.FileNotADirectory);
|
|
127
|
-
}
|
|
128
|
-
const name = resource.path.base;
|
|
129
|
-
return parentHandle.removeEntry(name, { recursive: _opts.recursive });
|
|
195
|
+
const path = formatPath(resource);
|
|
196
|
+
await this.fs.remove(path, { recursive: opts.recursive });
|
|
130
197
|
}
|
|
131
198
|
catch (error) {
|
|
132
199
|
throw toFileSystemProviderError(error);
|
|
133
200
|
}
|
|
134
|
-
finally {
|
|
135
|
-
this.onDidChangeFileEmitter.fire([{ resource, type: 2 /* FileChangeType.DELETED */ }]);
|
|
136
|
-
}
|
|
137
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Renames a resource from one location to another
|
|
204
|
+
*/
|
|
138
205
|
async rename(from, to, opts) {
|
|
206
|
+
if (!from || !from.path || !to || !to.path) {
|
|
207
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid source or destination URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
208
|
+
}
|
|
139
209
|
await this.initialized;
|
|
140
210
|
try {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const toHandle = await this.toFileSystemHandle(to);
|
|
147
|
-
await copyDirectoryContents(fromHandle, toHandle);
|
|
148
|
-
// Delete the old directory
|
|
149
|
-
await this.delete(from, { recursive: true, useTrash: false });
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
const content = await this.readFile(from);
|
|
153
|
-
await this.writeFile(to, content, { create: true, overwrite: opts.overwrite });
|
|
154
|
-
await this.delete(from, { recursive: true, useTrash: false });
|
|
155
|
-
}
|
|
156
|
-
this.onDidChangeFileEmitter.fire([{ resource: to, type: 1 /* FileChangeType.ADDED */ }]);
|
|
211
|
+
const fromPath = formatPath(from);
|
|
212
|
+
const toPath = formatPath(to);
|
|
213
|
+
await this.fs.rename(fromPath, toPath, {
|
|
214
|
+
overwrite: opts.overwrite,
|
|
215
|
+
});
|
|
157
216
|
}
|
|
158
217
|
catch (error) {
|
|
159
218
|
throw toFileSystemProviderError(error);
|
|
160
219
|
}
|
|
161
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Copies a resource from one location to another
|
|
223
|
+
*/
|
|
224
|
+
async copy(from, to, opts) {
|
|
225
|
+
if (!from || !from.path || !to || !to.path) {
|
|
226
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid source or destination URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
227
|
+
}
|
|
228
|
+
await this.initialized;
|
|
229
|
+
try {
|
|
230
|
+
const fromPath = formatPath(from);
|
|
231
|
+
const toPath = formatPath(to);
|
|
232
|
+
await this.fs.copy(fromPath, toPath, {
|
|
233
|
+
overwrite: opts.overwrite,
|
|
234
|
+
recursive: true,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
throw toFileSystemProviderError(error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Reads file content as binary data
|
|
243
|
+
*/
|
|
162
244
|
async readFile(resource) {
|
|
245
|
+
if (!resource || !resource.path) {
|
|
246
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid resource URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
247
|
+
}
|
|
163
248
|
await this.initialized;
|
|
164
249
|
try {
|
|
165
|
-
|
|
166
|
-
const fileHandle = await this.toFileSystemHandle(resource, { create: false, isDirectory: false });
|
|
167
|
-
// Get the file itself (which includes the content)
|
|
168
|
-
const file = await fileHandle.getFile();
|
|
169
|
-
// Read the file as an ArrayBuffer and convert it to Uint8Array
|
|
170
|
-
const arrayBuffer = await file.arrayBuffer();
|
|
171
|
-
return new Uint8Array(arrayBuffer);
|
|
250
|
+
return await this.fs.readFile(formatPath(resource), 'binary');
|
|
172
251
|
}
|
|
173
252
|
catch (error) {
|
|
174
|
-
throw toFileSystemProviderError(error
|
|
253
|
+
throw toFileSystemProviderError(error);
|
|
175
254
|
}
|
|
176
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Reads file content as a stream
|
|
258
|
+
*/
|
|
259
|
+
readFileStream(resource, opts, token) {
|
|
260
|
+
const stream = (0, stream_1.newWriteableStream)(chunks => buffer_1.BinaryBuffer.concat(chunks.map(chunk => buffer_1.BinaryBuffer.wrap(chunk))).buffer);
|
|
261
|
+
(0, io_1.readFileIntoStream)(this, resource, stream, data => data.buffer, {
|
|
262
|
+
...opts,
|
|
263
|
+
bufferSize: this.BUFFER_SIZE
|
|
264
|
+
}, token);
|
|
265
|
+
return stream;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Writes binary content to a file
|
|
269
|
+
*/
|
|
177
270
|
async writeFile(resource, content, opts) {
|
|
178
271
|
await this.initialized;
|
|
179
|
-
let
|
|
272
|
+
let handle = undefined;
|
|
273
|
+
if (!resource || !resource.path) {
|
|
274
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid resource URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
275
|
+
}
|
|
276
|
+
if (!content || !(content instanceof Uint8Array)) {
|
|
277
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid content: must be Uint8Array', files_1.FileSystemProviderErrorCode.Unknown);
|
|
278
|
+
}
|
|
180
279
|
try {
|
|
181
|
-
|
|
280
|
+
const path = formatPath(resource);
|
|
182
281
|
if (!opts.create || !opts.overwrite) {
|
|
183
|
-
const fileExists = await this.
|
|
282
|
+
const fileExists = await this.fs.exists(path);
|
|
184
283
|
if (fileExists) {
|
|
185
284
|
if (!opts.overwrite) {
|
|
186
285
|
throw (0, files_1.createFileSystemProviderError)('File already exists', files_1.FileSystemProviderErrorCode.FileExists);
|
|
187
286
|
}
|
|
188
287
|
}
|
|
189
|
-
else {
|
|
190
|
-
|
|
191
|
-
throw (0, files_1.createFileSystemProviderError)('File does not exist', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
192
|
-
}
|
|
288
|
+
else if (!opts.create) {
|
|
289
|
+
throw (0, files_1.createFileSystemProviderError)('File does not exist', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
193
290
|
}
|
|
194
291
|
}
|
|
195
|
-
const handle = await this.toFileSystemHandle(resource, { create: true, isDirectory: false });
|
|
196
292
|
// Open
|
|
197
|
-
|
|
293
|
+
handle = await this.open(resource, { create: true });
|
|
198
294
|
// Write content at once
|
|
199
|
-
await (
|
|
200
|
-
this.onDidChangeFileEmitter.fire([{ resource: resource, type: 0 /* FileChangeType.UPDATED */ }]);
|
|
295
|
+
await this.write(handle, 0, content, 0, content.byteLength);
|
|
201
296
|
}
|
|
202
297
|
catch (error) {
|
|
203
|
-
throw toFileSystemProviderError(error
|
|
298
|
+
throw toFileSystemProviderError(error);
|
|
204
299
|
}
|
|
205
300
|
finally {
|
|
206
|
-
if (typeof
|
|
207
|
-
await
|
|
301
|
+
if (typeof handle === 'number') {
|
|
302
|
+
await this.close(handle);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// #region Open/Read/Write/Close Operations
|
|
307
|
+
/**
|
|
308
|
+
* Opens a file and returns a file descriptor
|
|
309
|
+
*/
|
|
310
|
+
async open(resource, opts) {
|
|
311
|
+
await this.initialized;
|
|
312
|
+
if (!resource || !resource.path) {
|
|
313
|
+
throw (0, files_1.createFileSystemProviderError)('Invalid resource URI', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
const path = formatPath(resource);
|
|
317
|
+
const fileExists = await this.fs.exists(path);
|
|
318
|
+
if (!opts.create && !fileExists) {
|
|
319
|
+
throw (0, files_1.createFileSystemProviderError)('File does not exist', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
208
320
|
}
|
|
321
|
+
const fd = await this.fs.open(path, {
|
|
322
|
+
create: opts.create,
|
|
323
|
+
truncate: opts.create
|
|
324
|
+
});
|
|
325
|
+
return fd;
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
throw toFileSystemProviderError(error);
|
|
209
329
|
}
|
|
210
330
|
}
|
|
211
331
|
/**
|
|
212
|
-
*
|
|
213
|
-
* @param resource URI/path of the resource
|
|
214
|
-
* @param options Options for the creation of the handle while traversing the path
|
|
215
|
-
* @returns FileSystemHandle for the given resource
|
|
332
|
+
* Closes a file descriptor
|
|
216
333
|
*/
|
|
217
|
-
async
|
|
218
|
-
|
|
219
|
-
|
|
334
|
+
async close(fd) {
|
|
335
|
+
try {
|
|
336
|
+
await this.fs.close(fd);
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
throw toFileSystemProviderError(error);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Reads data from a file descriptor
|
|
344
|
+
*/
|
|
345
|
+
async read(fd, pos, data, offset, length) {
|
|
346
|
+
try {
|
|
347
|
+
const result = await this.fs.read(fd, data, offset, length, pos);
|
|
348
|
+
return result.bytesRead;
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
throw toFileSystemProviderError(error);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Writes data to a file descriptor
|
|
356
|
+
*/
|
|
357
|
+
async write(fd, pos, data, offset, length) {
|
|
358
|
+
try {
|
|
359
|
+
return await this.fs.write(fd, data, offset, length, pos, true);
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
throw toFileSystemProviderError(error);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// #endregion
|
|
366
|
+
// #region Text File Updates
|
|
367
|
+
/**
|
|
368
|
+
* Updates a text file with content changes
|
|
369
|
+
*/
|
|
370
|
+
async updateFile(resource, changes, opts) {
|
|
371
|
+
try {
|
|
372
|
+
const content = await this.readFile(resource);
|
|
373
|
+
const decoded = this.encodingService.decode(buffer_1.BinaryBuffer.wrap(content), opts.readEncoding);
|
|
374
|
+
const newContent = vscode_languageserver_textdocument_1.TextDocument.update(vscode_languageserver_textdocument_1.TextDocument.create('', '', 1, decoded), changes, 2).getText();
|
|
375
|
+
const encoding = await this.encodingService.toResourceEncoding(opts.writeEncoding, {
|
|
376
|
+
overwriteEncoding: opts.overwriteEncoding,
|
|
377
|
+
read: async (length) => {
|
|
378
|
+
const fd = await this.open(resource, { create: false });
|
|
379
|
+
try {
|
|
380
|
+
const data = new Uint8Array(length);
|
|
381
|
+
await this.read(fd, 0, data, 0, length);
|
|
382
|
+
return data;
|
|
383
|
+
}
|
|
384
|
+
finally {
|
|
385
|
+
await this.close(fd);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
const encoded = this.encodingService.encode(newContent, encoding);
|
|
390
|
+
await this.writeFile(resource, encoded.buffer, { create: false, overwrite: true });
|
|
391
|
+
const stat = await this.stat(resource);
|
|
392
|
+
return Object.assign(stat, { encoding: encoding.encoding });
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
throw toFileSystemProviderError(error);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// #endregion
|
|
399
|
+
/**
|
|
400
|
+
* Handles file system change events from BroadcastChannel
|
|
401
|
+
*/
|
|
402
|
+
async handleFileSystemChange(event) {
|
|
403
|
+
var _a;
|
|
404
|
+
if (!((_a = event.data) === null || _a === void 0 ? void 0 : _a.path)) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
const resource = new core_1.URI('file://' + event.data.path);
|
|
408
|
+
let changeType;
|
|
409
|
+
if (event.data.type === opfs_worker_1.WatchEventType.Added) {
|
|
410
|
+
changeType = 1 /* FileChangeType.ADDED */;
|
|
411
|
+
}
|
|
412
|
+
else if (event.data.type === opfs_worker_1.WatchEventType.Removed) {
|
|
413
|
+
changeType = 2 /* FileChangeType.DELETED */;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
changeType = 0 /* FileChangeType.UPDATED */;
|
|
417
|
+
}
|
|
418
|
+
this.onDidChangeFileEmitter.fire([{ resource, type: changeType }]);
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Disposes the file system provider
|
|
422
|
+
*/
|
|
423
|
+
dispose() {
|
|
424
|
+
this.toDispose.dispose();
|
|
220
425
|
}
|
|
221
426
|
};
|
|
222
427
|
exports.OPFSFileSystemProvider = OPFSFileSystemProvider;
|
|
@@ -224,6 +429,10 @@ tslib_1.__decorate([
|
|
|
224
429
|
(0, inversify_1.inject)(opfs_filesystem_initialization_1.OPFSInitialization),
|
|
225
430
|
tslib_1.__metadata("design:type", Object)
|
|
226
431
|
], OPFSFileSystemProvider.prototype, "initialization", void 0);
|
|
432
|
+
tslib_1.__decorate([
|
|
433
|
+
(0, inversify_1.inject)(encoding_service_1.EncodingService),
|
|
434
|
+
tslib_1.__metadata("design:type", encoding_service_1.EncodingService)
|
|
435
|
+
], OPFSFileSystemProvider.prototype, "encodingService", void 0);
|
|
227
436
|
tslib_1.__decorate([
|
|
228
437
|
(0, inversify_1.postConstruct)(),
|
|
229
438
|
tslib_1.__metadata("design:type", Function),
|
|
@@ -233,91 +442,46 @@ tslib_1.__decorate([
|
|
|
233
442
|
exports.OPFSFileSystemProvider = OPFSFileSystemProvider = tslib_1.__decorate([
|
|
234
443
|
(0, inversify_1.injectable)()
|
|
235
444
|
], OPFSFileSystemProvider);
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
// If there are parts left, the handle must be a directory
|
|
243
|
-
if (handle.kind !== 'directory') {
|
|
244
|
-
throw (0, files_1.createFileSystemProviderError)('Not a directory', files_1.FileSystemProviderErrorCode.FileNotADirectory);
|
|
245
|
-
}
|
|
246
|
-
const dirHandle = handle;
|
|
247
|
-
// We need to create it and thus we need to stop early to create the file or directory
|
|
248
|
-
if (pathParts.length === 1 && (options === null || options === void 0 ? void 0 : options.create)) {
|
|
249
|
-
if (options === null || options === void 0 ? void 0 : options.isDirectory) {
|
|
250
|
-
return dirHandle.getDirectoryHandle(pathParts[0], { create: options.create });
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
return dirHandle.getFileHandle(pathParts[0], { create: options.create });
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
// Continue to resolve the path
|
|
257
|
-
const part = pathParts.shift();
|
|
258
|
-
for await (const entry of dirHandle.entries()) {
|
|
259
|
-
// Check the entry name in the current directory
|
|
260
|
-
if (entry[0] === part) {
|
|
261
|
-
return recursiveFileSystemHandle(entry[1], pathParts, options);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
// If we haven't found the part, we need to create it along the way
|
|
265
|
-
if (options === null || options === void 0 ? void 0 : options.create) {
|
|
266
|
-
const newHandle = await dirHandle.getDirectoryHandle(part, { create: true });
|
|
267
|
-
return recursiveFileSystemHandle(newHandle, pathParts, options);
|
|
268
|
-
}
|
|
269
|
-
throw (0, files_1.createFileSystemProviderError)('File not found', files_1.FileSystemProviderErrorCode.FileNotFound);
|
|
445
|
+
/**
|
|
446
|
+
* Formats a URI or string resource to a file system path
|
|
447
|
+
*/
|
|
448
|
+
function formatPath(resource) {
|
|
449
|
+
return file_uri_1.FileUri.fsPath(resource);
|
|
270
450
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
finally {
|
|
282
|
-
await writable.close();
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
else if (handle.kind === 'directory') {
|
|
286
|
-
const newSubDirHandle = await destinationHandle.getDirectoryHandle(name, { create: true });
|
|
287
|
-
await copyDirectoryContents(handle, newSubDirHandle);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
451
|
+
/**
|
|
452
|
+
* Creates a Stat object from OPFS stats
|
|
453
|
+
*/
|
|
454
|
+
function formatStat(stats) {
|
|
455
|
+
return {
|
|
456
|
+
type: stats.isDirectory ? files_1.FileType.Directory : files_1.FileType.File,
|
|
457
|
+
ctime: new Date(stats.ctime).getTime(),
|
|
458
|
+
mtime: new Date(stats.mtime).getTime(),
|
|
459
|
+
size: stats.size
|
|
460
|
+
};
|
|
290
461
|
}
|
|
291
|
-
|
|
462
|
+
/**
|
|
463
|
+
* Converts OPFS errors to file system provider errors
|
|
464
|
+
*/
|
|
465
|
+
function toFileSystemProviderError(error) {
|
|
292
466
|
if (error instanceof files_1.FileSystemProviderError) {
|
|
293
|
-
return error;
|
|
467
|
+
return error;
|
|
294
468
|
}
|
|
295
469
|
let code;
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
else {
|
|
311
|
-
code = files_1.FileSystemProviderErrorCode.FileNotADirectory;
|
|
312
|
-
}
|
|
313
|
-
break;
|
|
314
|
-
case 'QuotaExceededError':
|
|
315
|
-
code = files_1.FileSystemProviderErrorCode.FileTooLarge;
|
|
316
|
-
break;
|
|
317
|
-
default:
|
|
318
|
-
code = files_1.FileSystemProviderErrorCode.Unknown;
|
|
470
|
+
if (error.name === 'NotFoundError' || error.name === 'ENOENT') {
|
|
471
|
+
code = files_1.FileSystemProviderErrorCode.FileNotFound;
|
|
472
|
+
}
|
|
473
|
+
else if (error.name === 'NotAllowedError' || error.name === 'SecurityError' || error.name === 'EACCES') {
|
|
474
|
+
code = files_1.FileSystemProviderErrorCode.NoPermissions;
|
|
475
|
+
}
|
|
476
|
+
else if (error.name === 'QuotaExceededError' || error.name === 'ENOSPC') {
|
|
477
|
+
code = files_1.FileSystemProviderErrorCode.FileTooLarge;
|
|
478
|
+
}
|
|
479
|
+
else if (error.name === 'PathError' || error.name === 'INVALID_PATH') {
|
|
480
|
+
code = files_1.FileSystemProviderErrorCode.FileNotADirectory;
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
code = files_1.FileSystemProviderErrorCode.Unknown;
|
|
319
484
|
}
|
|
320
485
|
return (0, files_1.createFileSystemProviderError)(error, code);
|
|
321
486
|
}
|
|
322
|
-
// #endregion
|
|
323
487
|
//# sourceMappingURL=opfs-filesystem-provider.js.map
|