@theia/filesystem 1.55.1 → 1.57.0-next.7
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/breadcrumbs/filepath-breadcrumbs-container.d.ts +1 -2
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.d.ts.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js +0 -4
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js.map +1 -1
- package/lib/browser/filesystem-preferences.d.ts +1 -0
- package/lib/browser/filesystem-preferences.d.ts.map +1 -1
- package/lib/browser/filesystem-preferences.js +6 -0
- package/lib/browser/filesystem-preferences.js.map +1 -1
- package/lib/browser-only/browser-only-filesystem-frontend-module.js +7 -7
- package/lib/browser-only/browser-only-filesystem-frontend-module.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.d.ts +11 -0
- package/lib/browser-only/opfs-filesystem-initialization.d.ts.map +1 -0
- package/lib/browser-only/opfs-filesystem-initialization.js +33 -0
- package/lib/browser-only/opfs-filesystem-initialization.js.map +1 -0
- package/lib/browser-only/opfs-filesystem-provider.d.ts +31 -0
- package/lib/browser-only/opfs-filesystem-provider.d.ts.map +1 -0
- package/lib/browser-only/opfs-filesystem-provider.js +323 -0
- package/lib/browser-only/opfs-filesystem-provider.js.map +1 -0
- package/package.json +4 -5
- package/src/browser/breadcrumbs/filepath-breadcrumbs-container.ts +1 -4
- package/src/browser/filesystem-preferences.ts +7 -0
- package/src/browser-only/browser-only-filesystem-frontend-module.ts +7 -7
- package/src/browser-only/opfs-filesystem-initialization.ts +36 -0
- package/src/browser-only/opfs-filesystem-provider.ts +347 -0
- package/lib/browser-only/browserfs-filesystem-initialization.d.ts +0 -13
- package/lib/browser-only/browserfs-filesystem-initialization.d.ts.map +0 -1
- package/lib/browser-only/browserfs-filesystem-initialization.js +0 -55
- package/lib/browser-only/browserfs-filesystem-initialization.js.map +0 -1
- package/lib/browser-only/browserfs-filesystem-provider.d.ts +0 -46
- package/lib/browser-only/browserfs-filesystem-provider.d.ts.map +0 -1
- package/lib/browser-only/browserfs-filesystem-provider.js +0 -440
- package/lib/browser-only/browserfs-filesystem-provider.js.map +0 -1
- package/src/browser-only/browserfs-filesystem-initialization.ts +0 -61
- package/src/browser-only/browserfs-filesystem-provider.ts +0 -462
|
@@ -95,6 +95,12 @@ export const filesystemPreferenceSchema: PreferenceSchema = {
|
|
|
95
95
|
description: nls.localizeByDefault('When enabled, will trim trailing whitespace when saving a file.'),
|
|
96
96
|
scope: 'language-overridable'
|
|
97
97
|
},
|
|
98
|
+
'files.insertFinalNewline': {
|
|
99
|
+
type: 'boolean',
|
|
100
|
+
default: false,
|
|
101
|
+
description: nls.localizeByDefault('When enabled, insert a final new line at the end of the file when saving it.'),
|
|
102
|
+
scope: 'language-overridable'
|
|
103
|
+
},
|
|
98
104
|
'files.maxConcurrentUploads': {
|
|
99
105
|
type: 'integer',
|
|
100
106
|
default: 1,
|
|
@@ -116,6 +122,7 @@ export interface FileSystemConfiguration {
|
|
|
116
122
|
'files.participants.timeout': number
|
|
117
123
|
'files.maxFileSizeMB': number
|
|
118
124
|
'files.trimTrailingWhitespace': boolean
|
|
125
|
+
'files.insertFinalNewline': boolean
|
|
119
126
|
'files.maxConcurrentUploads': number
|
|
120
127
|
}
|
|
121
128
|
|
|
@@ -16,19 +16,19 @@
|
|
|
16
16
|
|
|
17
17
|
import { ContainerModule } from '@theia/core/shared/inversify';
|
|
18
18
|
import { FileSystemProvider } from '../common/files';
|
|
19
|
-
import {
|
|
19
|
+
import { OPFSFileSystemProvider } from './opfs-filesystem-provider';
|
|
20
20
|
import { RemoteFileSystemProvider, RemoteFileSystemServer } from '../common/remote-file-system-provider';
|
|
21
|
-
import {
|
|
21
|
+
import { OPFSInitialization, DefaultOPFSInitialization } from './opfs-filesystem-initialization';
|
|
22
22
|
import { BrowserOnlyFileSystemProviderServer } from './browser-only-filesystem-provider-server';
|
|
23
23
|
|
|
24
24
|
export default new ContainerModule((bind, _unbind, isBound, rebind) => {
|
|
25
|
-
bind(
|
|
26
|
-
bind(
|
|
27
|
-
bind(
|
|
25
|
+
bind(DefaultOPFSInitialization).toSelf();
|
|
26
|
+
bind(OPFSFileSystemProvider).toSelf();
|
|
27
|
+
bind(OPFSInitialization).toService(DefaultOPFSInitialization);
|
|
28
28
|
if (isBound(FileSystemProvider)) {
|
|
29
|
-
rebind(FileSystemProvider).to(
|
|
29
|
+
rebind(FileSystemProvider).to(OPFSFileSystemProvider).inSingletonScope();
|
|
30
30
|
} else {
|
|
31
|
-
bind(FileSystemProvider).to(
|
|
31
|
+
bind(FileSystemProvider).to(OPFSFileSystemProvider).inSingletonScope();
|
|
32
32
|
}
|
|
33
33
|
if (isBound(RemoteFileSystemProvider)) {
|
|
34
34
|
rebind(RemoteFileSystemServer).to(BrowserOnlyFileSystemProviderServer).inSingletonScope();
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 EclipseSource and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import type { OPFSFileSystemProvider } from './opfs-filesystem-provider';
|
|
18
|
+
import { injectable } from '@theia/core/shared/inversify';
|
|
19
|
+
|
|
20
|
+
export const OPFSInitialization = Symbol('OPFSInitialization');
|
|
21
|
+
export interface OPFSInitialization {
|
|
22
|
+
getRootDirectory(): Promise<FileSystemDirectoryHandle>
|
|
23
|
+
initializeFS(provider: OPFSFileSystemProvider): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@injectable()
|
|
27
|
+
export class DefaultOPFSInitialization implements OPFSInitialization {
|
|
28
|
+
|
|
29
|
+
getRootDirectory(): Promise<FileSystemDirectoryHandle> {
|
|
30
|
+
return navigator.storage.getDirectory();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async initializeFS(provider: OPFSFileSystemProvider): Promise<void> {
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2024 EclipseSource and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
18
|
+
import {
|
|
19
|
+
FileChange, FileChangeType, FileDeleteOptions,
|
|
20
|
+
FileOverwriteOptions, FileSystemProviderCapabilities,
|
|
21
|
+
FileSystemProviderError,
|
|
22
|
+
FileSystemProviderErrorCode,
|
|
23
|
+
FileSystemProviderWithFileReadWriteCapability,
|
|
24
|
+
FileType, FileWriteOptions, Stat, WatchOptions, createFileSystemProviderError
|
|
25
|
+
} from '../common/files';
|
|
26
|
+
import { Emitter, Event, URI, Disposable, Path } from '@theia/core';
|
|
27
|
+
import { OPFSInitialization } from './opfs-filesystem-initialization';
|
|
28
|
+
|
|
29
|
+
/** Options to be used when traversing the file system handles */
|
|
30
|
+
interface CreateFileSystemHandleOptions {
|
|
31
|
+
isDirectory?: boolean;
|
|
32
|
+
create?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@injectable()
|
|
36
|
+
export class OPFSFileSystemProvider implements FileSystemProviderWithFileReadWriteCapability {
|
|
37
|
+
capabilities: FileSystemProviderCapabilities = FileSystemProviderCapabilities.FileReadWrite;
|
|
38
|
+
onDidChangeCapabilities: Event<void> = Event.None;
|
|
39
|
+
|
|
40
|
+
private readonly onDidChangeFileEmitter = new Emitter<readonly FileChange[]>();
|
|
41
|
+
readonly onDidChangeFile = this.onDidChangeFileEmitter.event;
|
|
42
|
+
onFileWatchError: Event<void> = Event.None;
|
|
43
|
+
|
|
44
|
+
@inject(OPFSInitialization)
|
|
45
|
+
protected readonly initialization: OPFSInitialization;
|
|
46
|
+
|
|
47
|
+
private directoryHandle: FileSystemDirectoryHandle;
|
|
48
|
+
private initialized: Promise<true>;
|
|
49
|
+
|
|
50
|
+
@postConstruct()
|
|
51
|
+
protected init(): void {
|
|
52
|
+
const setup = async (): Promise<true> => {
|
|
53
|
+
this.directoryHandle = await this.initialization.getRootDirectory();
|
|
54
|
+
await this.initialization.initializeFS(new Proxy(this, {
|
|
55
|
+
get(target, prop, receiver): unknown {
|
|
56
|
+
if (prop === 'initialized') {
|
|
57
|
+
return Promise.resolve(true);
|
|
58
|
+
}
|
|
59
|
+
return Reflect.get(target, prop, receiver);
|
|
60
|
+
}
|
|
61
|
+
}));
|
|
62
|
+
return true;
|
|
63
|
+
};
|
|
64
|
+
this.initialized = setup();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
watch(_resource: URI, _opts: WatchOptions): Disposable {
|
|
68
|
+
return Disposable.NULL;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async exists(resource: URI): Promise<boolean> {
|
|
72
|
+
try {
|
|
73
|
+
await this.initialized;
|
|
74
|
+
await this.toFileSystemHandle(resource);
|
|
75
|
+
return true;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async stat(resource: URI): Promise<Stat> {
|
|
82
|
+
try {
|
|
83
|
+
await this.initialized;
|
|
84
|
+
|
|
85
|
+
const handle = await this.toFileSystemHandle(resource);
|
|
86
|
+
|
|
87
|
+
if (handle.kind === 'file') {
|
|
88
|
+
const fileHandle = handle as FileSystemFileHandle;
|
|
89
|
+
const file = await fileHandle.getFile();
|
|
90
|
+
return {
|
|
91
|
+
type: FileType.File,
|
|
92
|
+
ctime: file.lastModified,
|
|
93
|
+
mtime: file.lastModified,
|
|
94
|
+
size: file.size
|
|
95
|
+
};
|
|
96
|
+
} else if (handle.kind === 'directory') {
|
|
97
|
+
return {
|
|
98
|
+
type: FileType.Directory,
|
|
99
|
+
ctime: 0,
|
|
100
|
+
mtime: 0,
|
|
101
|
+
size: 0
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
throw createFileSystemProviderError('Unknown file handle error', FileSystemProviderErrorCode.Unknown);
|
|
106
|
+
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw createFileSystemProviderError(`Error while accessing resource ${resource.toString()}`, FileSystemProviderErrorCode.Unknown);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async mkdir(resource: URI): Promise<void> {
|
|
113
|
+
await this.initialized;
|
|
114
|
+
try {
|
|
115
|
+
await this.toFileSystemHandle(resource, { create: true, isDirectory: true });
|
|
116
|
+
this.onDidChangeFileEmitter.fire([{ resource, type: FileChangeType.ADDED }]);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
throw toFileSystemProviderError(error, true);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async readdir(resource: URI): Promise<[string, FileType][]> {
|
|
123
|
+
await this.initialized;
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
// Get the directory handle from the directoryHandle
|
|
127
|
+
const directoryHandle = await this.toFileSystemHandle(resource, { create: false, isDirectory: true }) as FileSystemDirectoryHandle;
|
|
128
|
+
|
|
129
|
+
const result: [string, FileType][] = [];
|
|
130
|
+
|
|
131
|
+
// Iterate through the entries in the directory (files and subdirectories)
|
|
132
|
+
for await (const [name, handle] of directoryHandle.entries()) {
|
|
133
|
+
// Determine the type of the entry (file or directory)
|
|
134
|
+
if (handle.kind === 'file') {
|
|
135
|
+
result.push([name, FileType.File]);
|
|
136
|
+
} else if (handle.kind === 'directory') {
|
|
137
|
+
result.push([name, FileType.Directory]);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
throw toFileSystemProviderError(error, true);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async delete(resource: URI, _opts: FileDeleteOptions): Promise<void> {
|
|
148
|
+
await this.initialized;
|
|
149
|
+
try {
|
|
150
|
+
const parentURI = resource.parent;
|
|
151
|
+
const parentHandle = await this.toFileSystemHandle(parentURI, { create: false, isDirectory: true });
|
|
152
|
+
if (parentHandle.kind !== 'directory') {
|
|
153
|
+
throw createFileSystemProviderError(new Error('Parent is not a directory'), FileSystemProviderErrorCode.FileNotADirectory);
|
|
154
|
+
}
|
|
155
|
+
const name = resource.path.base;
|
|
156
|
+
return (parentHandle as FileSystemDirectoryHandle).removeEntry(name, { recursive: _opts.recursive });
|
|
157
|
+
} catch (error) {
|
|
158
|
+
throw toFileSystemProviderError(error);
|
|
159
|
+
} finally {
|
|
160
|
+
this.onDidChangeFileEmitter.fire([{ resource, type: FileChangeType.DELETED }]);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async rename(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void> {
|
|
165
|
+
await this.initialized;
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const fromHandle = await this.toFileSystemHandle(from);
|
|
169
|
+
// Check whether the source is a file or directory
|
|
170
|
+
if (fromHandle.kind === 'directory') {
|
|
171
|
+
// Create the new directory and get the handle
|
|
172
|
+
await this.mkdir(to);
|
|
173
|
+
const toHandle = await this.toFileSystemHandle(to) as FileSystemDirectoryHandle;
|
|
174
|
+
await copyDirectoryContents(fromHandle as FileSystemDirectoryHandle, toHandle);
|
|
175
|
+
|
|
176
|
+
// Delete the old directory
|
|
177
|
+
await this.delete(from, { recursive: true, useTrash: false });
|
|
178
|
+
} else {
|
|
179
|
+
const content = await this.readFile(from);
|
|
180
|
+
await this.writeFile(to, content, { create: true, overwrite: opts.overwrite });
|
|
181
|
+
await this.delete(from, { recursive: true, useTrash: false });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
this.onDidChangeFileEmitter.fire([{ resource: to, type: FileChangeType.ADDED }]);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
throw toFileSystemProviderError(error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async readFile(resource: URI): Promise<Uint8Array> {
|
|
191
|
+
await this.initialized;
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
// Get the file handle from the directoryHandle
|
|
195
|
+
const fileHandle = await this.toFileSystemHandle(resource, { create: false, isDirectory: false }) as FileSystemFileHandle;
|
|
196
|
+
|
|
197
|
+
// Get the file itself (which includes the content)
|
|
198
|
+
const file = await fileHandle.getFile();
|
|
199
|
+
|
|
200
|
+
// Read the file as an ArrayBuffer and convert it to Uint8Array
|
|
201
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
202
|
+
return new Uint8Array(arrayBuffer);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
throw toFileSystemProviderError(error, false);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> {
|
|
209
|
+
await this.initialized;
|
|
210
|
+
let writeableHandle: FileSystemWritableFileStream | undefined = undefined;
|
|
211
|
+
try {
|
|
212
|
+
// Validate target unless { create: true, overwrite: true }
|
|
213
|
+
if (!opts.create || !opts.overwrite) {
|
|
214
|
+
const fileExists = await this.stat(resource).then(() => true, () => false);
|
|
215
|
+
if (fileExists) {
|
|
216
|
+
if (!opts.overwrite) {
|
|
217
|
+
throw createFileSystemProviderError('File already exists', FileSystemProviderErrorCode.FileExists);
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
if (!opts.create) {
|
|
221
|
+
throw createFileSystemProviderError('File does not exist', FileSystemProviderErrorCode.FileNotFound);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const handle = await this.toFileSystemHandle(resource, { create: true, isDirectory: false }) as FileSystemFileHandle;
|
|
227
|
+
|
|
228
|
+
// Open
|
|
229
|
+
writeableHandle = await handle?.createWritable();
|
|
230
|
+
|
|
231
|
+
// Write content at once
|
|
232
|
+
await writeableHandle?.write(content);
|
|
233
|
+
|
|
234
|
+
this.onDidChangeFileEmitter.fire([{ resource: resource, type: FileChangeType.UPDATED }]);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
throw toFileSystemProviderError(error, false);
|
|
237
|
+
} finally {
|
|
238
|
+
if (typeof writeableHandle !== 'undefined') {
|
|
239
|
+
await writeableHandle.close();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Returns the FileSystemHandle for the given resource given by a URI.
|
|
246
|
+
* @param resource URI/path of the resource
|
|
247
|
+
* @param options Options for the creation of the handle while traversing the path
|
|
248
|
+
* @returns FileSystemHandle for the given resource
|
|
249
|
+
*/
|
|
250
|
+
private async toFileSystemHandle(resource: URI, options?: CreateFileSystemHandleOptions): Promise<FileSystemHandle> {
|
|
251
|
+
const pathParts = resource.path.toString().split(Path.separator).filter(Boolean);
|
|
252
|
+
|
|
253
|
+
return recursiveFileSystemHandle(this.directoryHandle, pathParts, options);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// #region Helper functions
|
|
258
|
+
async function recursiveFileSystemHandle(handle: FileSystemHandle, pathParts: string[], options?: CreateFileSystemHandleOptions): Promise<FileSystemHandle> {
|
|
259
|
+
// We reached the end of the path, this happens only when not creating
|
|
260
|
+
if (pathParts.length === 0) {
|
|
261
|
+
return handle;
|
|
262
|
+
}
|
|
263
|
+
// If there are parts left, the handle must be a directory
|
|
264
|
+
if (handle.kind !== 'directory') {
|
|
265
|
+
throw FileSystemProviderErrorCode.FileNotADirectory;
|
|
266
|
+
}
|
|
267
|
+
const dirHandle = handle as FileSystemDirectoryHandle;
|
|
268
|
+
// We need to create it and thus we need to stop early to create the file or directory
|
|
269
|
+
if (pathParts.length === 1 && options?.create) {
|
|
270
|
+
if (options?.isDirectory) {
|
|
271
|
+
return dirHandle.getDirectoryHandle(pathParts[0], { create: options.create });
|
|
272
|
+
} else {
|
|
273
|
+
return dirHandle.getFileHandle(pathParts[0], { create: options.create });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Continue to resolve the path
|
|
278
|
+
const part = pathParts.shift()!;
|
|
279
|
+
for await (const entry of dirHandle.entries()) {
|
|
280
|
+
// Check the entry name in the current directory
|
|
281
|
+
if (entry[0] === part) {
|
|
282
|
+
return recursiveFileSystemHandle(entry[1], pathParts, options);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// If we haven't found the part, we need to create it along the way
|
|
287
|
+
if (options?.create) {
|
|
288
|
+
const newHandle = await dirHandle.getDirectoryHandle(part, { create: true });
|
|
289
|
+
return recursiveFileSystemHandle(newHandle, pathParts, options);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
throw FileSystemProviderErrorCode.FileNotFound;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Function to copy directory contents recursively
|
|
296
|
+
async function copyDirectoryContents(sourceHandle: FileSystemDirectoryHandle, destinationHandle: FileSystemDirectoryHandle): Promise<void> {
|
|
297
|
+
for await (const [name, handle] of sourceHandle.entries()) {
|
|
298
|
+
if (handle.kind === 'file') {
|
|
299
|
+
const file = await (handle as FileSystemFileHandle).getFile();
|
|
300
|
+
const newFileHandle = await destinationHandle.getFileHandle(name, { create: true });
|
|
301
|
+
const writable = await newFileHandle.createWritable();
|
|
302
|
+
try {
|
|
303
|
+
await writable.write(await file.arrayBuffer());
|
|
304
|
+
} finally {
|
|
305
|
+
await writable.close();
|
|
306
|
+
}
|
|
307
|
+
} else if (handle.kind === 'directory') {
|
|
308
|
+
const newSubDirHandle = await destinationHandle.getDirectoryHandle(name, { create: true });
|
|
309
|
+
await copyDirectoryContents(handle as FileSystemDirectoryHandle, newSubDirHandle);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function toFileSystemProviderError(error: DOMException, is_dir?: boolean): FileSystemProviderError {
|
|
315
|
+
if (error instanceof FileSystemProviderError) {
|
|
316
|
+
return error; // avoid double conversion
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let code: FileSystemProviderErrorCode;
|
|
320
|
+
switch (error.name) {
|
|
321
|
+
case 'NotFoundError':
|
|
322
|
+
code = FileSystemProviderErrorCode.FileNotFound;
|
|
323
|
+
break;
|
|
324
|
+
case 'InvalidModificationError':
|
|
325
|
+
code = FileSystemProviderErrorCode.FileExists;
|
|
326
|
+
break;
|
|
327
|
+
case 'NotAllowedError':
|
|
328
|
+
code = FileSystemProviderErrorCode.NoPermissions;
|
|
329
|
+
break;
|
|
330
|
+
case 'TypeMismatchError':
|
|
331
|
+
if (!is_dir) {
|
|
332
|
+
code = FileSystemProviderErrorCode.FileIsADirectory;
|
|
333
|
+
} else {
|
|
334
|
+
code = FileSystemProviderErrorCode.FileNotADirectory;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
break;
|
|
338
|
+
case 'QuotaExceededError':
|
|
339
|
+
code = FileSystemProviderErrorCode.FileTooLarge;
|
|
340
|
+
break;
|
|
341
|
+
default:
|
|
342
|
+
code = FileSystemProviderErrorCode.Unknown;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return createFileSystemProviderError(error, code);
|
|
346
|
+
}
|
|
347
|
+
// #endregion
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { FSModule } from 'browserfs/dist/node/core/FS';
|
|
2
|
-
import type { BrowserFSFileSystemProvider } from './browserfs-filesystem-provider';
|
|
3
|
-
import MountableFileSystem from 'browserfs/dist/node/backend/MountableFileSystem';
|
|
4
|
-
export declare const BrowserFSInitialization: unique symbol;
|
|
5
|
-
export interface BrowserFSInitialization {
|
|
6
|
-
createMountableFileSystem(): Promise<MountableFileSystem>;
|
|
7
|
-
initializeFS: (fs: FSModule, provider: BrowserFSFileSystemProvider) => Promise<void>;
|
|
8
|
-
}
|
|
9
|
-
export declare class DefaultBrowserFSInitialization implements BrowserFSInitialization {
|
|
10
|
-
createMountableFileSystem(): Promise<MountableFileSystem>;
|
|
11
|
-
initializeFS(fs: FSModule, provider: BrowserFSFileSystemProvider): Promise<void>;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=browserfs-filesystem-initialization.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browserfs-filesystem-initialization.d.ts","sourceRoot":"","sources":["../../src/browser-only/browserfs-filesystem-initialization.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAGnF,OAAO,mBAAmB,MAAM,iDAAiD,CAAC;AAElF,eAAO,MAAM,uBAAuB,eAAoC,CAAC;AACzE,MAAM,WAAW,uBAAuB;IACpC,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACzD,YAAY,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,2BAA2B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxF;AAED,qBACa,8BAA+B,YAAW,uBAAuB;IAE1E,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IA0BnD,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzF"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// *****************************************************************************
|
|
3
|
-
// Copyright (C) 2023 EclipseSource and others.
|
|
4
|
-
//
|
|
5
|
-
// This program and the accompanying materials are made available under the
|
|
6
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
-
//
|
|
9
|
-
// This Source Code may also be made available under the following Secondary
|
|
10
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
-
// with the GNU Classpath Exception which is available at
|
|
13
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
-
//
|
|
15
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
-
// *****************************************************************************
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.DefaultBrowserFSInitialization = exports.BrowserFSInitialization = void 0;
|
|
19
|
-
const tslib_1 = require("tslib");
|
|
20
|
-
const inversify_1 = require("@theia/core/shared/inversify");
|
|
21
|
-
const browserfs_1 = require("browserfs");
|
|
22
|
-
exports.BrowserFSInitialization = Symbol('BrowserFSInitialization');
|
|
23
|
-
let DefaultBrowserFSInitialization = class DefaultBrowserFSInitialization {
|
|
24
|
-
createMountableFileSystem() {
|
|
25
|
-
return new Promise(resolve => {
|
|
26
|
-
browserfs_1.FileSystem.IndexedDB.Create({}, (e, persistedFS) => {
|
|
27
|
-
if (e) {
|
|
28
|
-
throw e;
|
|
29
|
-
}
|
|
30
|
-
if (!persistedFS) {
|
|
31
|
-
throw Error('Could not create filesystem');
|
|
32
|
-
}
|
|
33
|
-
browserfs_1.FileSystem.MountableFileSystem.Create({
|
|
34
|
-
'/home': persistedFS
|
|
35
|
-
}, (error, mountableFS) => {
|
|
36
|
-
if (error) {
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
39
|
-
if (!mountableFS) {
|
|
40
|
-
throw Error('Could not create filesystem');
|
|
41
|
-
}
|
|
42
|
-
(0, browserfs_1.initialize)(mountableFS);
|
|
43
|
-
resolve(mountableFS);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
async initializeFS(fs, provider) {
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
exports.DefaultBrowserFSInitialization = DefaultBrowserFSInitialization;
|
|
52
|
-
exports.DefaultBrowserFSInitialization = DefaultBrowserFSInitialization = tslib_1.__decorate([
|
|
53
|
-
(0, inversify_1.injectable)()
|
|
54
|
-
], DefaultBrowserFSInitialization);
|
|
55
|
-
//# sourceMappingURL=browserfs-filesystem-initialization.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browserfs-filesystem-initialization.js","sourceRoot":"","sources":["../../src/browser-only/browserfs-filesystem-initialization.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,+CAA+C;AAC/C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAIhF,4DAA0D;AAC1D,yCAAmD;AAGtC,QAAA,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAOlE,IAAM,8BAA8B,GAApC,MAAM,8BAA8B;IAEvC,yBAAyB;QACrB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YACzB,sBAAU,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE;gBAC/C,IAAI,CAAC,EAAE,CAAC;oBACJ,MAAM,CAAC,CAAC;gBACZ,CAAC;gBACD,IAAI,CAAC,WAAW,EAAE,CAAC;oBACf,MAAM,KAAK,CAAC,6BAA6B,CAAC,CAAC;gBAC/C,CAAC;gBACD,sBAAU,CAAC,mBAAmB,CAAC,MAAM,CAAC;oBAClC,OAAO,EAAE,WAAW;iBAEvB,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;oBACtB,IAAI,KAAK,EAAE,CAAC;wBACR,MAAM,KAAK,CAAC;oBAChB,CAAC;oBACD,IAAI,CAAC,WAAW,EAAE,CAAC;wBACf,MAAM,KAAK,CAAC,6BAA6B,CAAC,CAAC;oBAC/C,CAAC;oBACD,IAAA,sBAAU,EAAC,WAAW,CAAC,CAAC;oBACxB,OAAO,CAAC,WAAW,CAAC,CAAC;gBACzB,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAY,EAAE,QAAqC;IAEtE,CAAC;CACJ,CAAA;AA/BY,wEAA8B;yCAA9B,8BAA8B;IAD1C,IAAA,sBAAU,GAAE;GACA,8BAA8B,CA+B1C"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { FileChange, FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileReadStreamOptions, FileSystemProviderCapabilities, FileSystemProviderWithFileReadWriteCapability, FileType, FileUpdateOptions, FileUpdateResult, FileWriteOptions, Stat, WatchOptions } from '../common/files';
|
|
2
|
-
import { Event, URI, Disposable, CancellationToken } from '@theia/core';
|
|
3
|
-
import { TextDocumentContentChangeEvent } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
4
|
-
import { ReadableStreamEvents } from '@theia/core/lib/common/stream';
|
|
5
|
-
import type { FileSystem } from 'browserfs/dist/node/core/file_system';
|
|
6
|
-
import { BrowserFSInitialization } from './browserfs-filesystem-initialization';
|
|
7
|
-
export declare class BrowserFSFileSystemProvider implements FileSystemProviderWithFileReadWriteCapability {
|
|
8
|
-
readonly initialization: BrowserFSInitialization;
|
|
9
|
-
capabilities: FileSystemProviderCapabilities;
|
|
10
|
-
onDidChangeCapabilities: Event<void>;
|
|
11
|
-
onDidChangeFile: Event<readonly FileChange[]>;
|
|
12
|
-
onFileWatchError: Event<void>;
|
|
13
|
-
private mapHandleToPos;
|
|
14
|
-
private writeHandles;
|
|
15
|
-
private canFlush;
|
|
16
|
-
private fs;
|
|
17
|
-
private mountableFS;
|
|
18
|
-
private initialized;
|
|
19
|
-
constructor(initialization: BrowserFSInitialization);
|
|
20
|
-
mount(mountPoint: string, fs: FileSystem): Promise<void>;
|
|
21
|
-
watch(_resource: URI, _opts: WatchOptions): Disposable;
|
|
22
|
-
stat(resource: URI): Promise<Stat>;
|
|
23
|
-
mkdir(resource: URI): Promise<void>;
|
|
24
|
-
readdir(resource: URI): Promise<[string, FileType][]>;
|
|
25
|
-
delete(resource: URI, _opts: FileDeleteOptions): Promise<void>;
|
|
26
|
-
rename(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void>;
|
|
27
|
-
copy?(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void>;
|
|
28
|
-
readFile(resource: URI): Promise<Uint8Array>;
|
|
29
|
-
writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void>;
|
|
30
|
-
readFileStream?(resource: URI, opts: FileReadStreamOptions, token: CancellationToken): ReadableStreamEvents<Uint8Array>;
|
|
31
|
-
open(resource: URI, opts: FileOpenOptions): Promise<number>;
|
|
32
|
-
close(fd: number): Promise<void>;
|
|
33
|
-
read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number>;
|
|
34
|
-
write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number>;
|
|
35
|
-
private doWrite;
|
|
36
|
-
private normalizePos;
|
|
37
|
-
private updatePos;
|
|
38
|
-
access?(resource: URI, mode?: number | undefined): Promise<void>;
|
|
39
|
-
fsPath?(resource: URI): Promise<string>;
|
|
40
|
-
updateFile?(resource: URI, changes: TextDocumentContentChangeEvent[], opts: FileUpdateOptions): Promise<FileUpdateResult>;
|
|
41
|
-
private toFilePath;
|
|
42
|
-
private toType;
|
|
43
|
-
private promisify;
|
|
44
|
-
private toFileSystemProviderError;
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=browserfs-filesystem-provider.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browserfs-filesystem-provider.d.ts","sourceRoot":"","sources":["../../src/browser-only/browserfs-filesystem-provider.ts"],"names":[],"mappings":"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"}
|