@react-native-gpui/fs 0.0.0-stage → 0.0.1-alpha.1
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +36 -2
- package/desktop/Cargo.toml +29 -0
- package/desktop/build.rs +3 -0
- package/desktop/src/dialogs.rs +394 -0
- package/desktop/src/dirs.rs +363 -0
- package/desktop/src/download.rs +329 -0
- package/desktop/src/errors.rs +149 -0
- package/desktop/src/files.rs +640 -0
- package/desktop/src/handles.rs +697 -0
- package/desktop/src/lib.rs +286 -0
- package/desktop/src/links.rs +336 -0
- package/desktop/src/module.rs +192 -0
- package/desktop/src/paths.rs +231 -0
- package/desktop/src/upload.rs +237 -0
- package/desktop/src/watching.rs +392 -0
- package/package.json +38 -4
- package/react-native.config.js +9 -0
- package/src/NativeFs.ts +235 -0
- package/src/constants.ts +43 -0
- package/src/download.ts +110 -0
- package/src/index.ts +788 -0
- package/src/promises.ts +771 -0
- package/src/shared.ts +539 -0
- package/src/stats.ts +196 -0
- package/src/upload.ts +97 -0
- package/src/watch.ts +141 -0
package/src/constants.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fs.constants`, with Node's numbers.
|
|
3
|
+
*
|
|
4
|
+
* The `O_*` values are Node's table rather than the platform's `open(2)` flags,
|
|
5
|
+
* because that is what the Rust side decodes: it translates them into
|
|
6
|
+
* `OpenOptions` instead of passing them through. The numbers here must stay in
|
|
7
|
+
* step with `modules/fs/desktop/src/module.rs`, which owns the other half of the
|
|
8
|
+
* contract.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const constants = {
|
|
12
|
+
// `access` modes.
|
|
13
|
+
F_OK: 0,
|
|
14
|
+
X_OK: 1,
|
|
15
|
+
W_OK: 2,
|
|
16
|
+
R_OK: 4,
|
|
17
|
+
|
|
18
|
+
// `open` flags.
|
|
19
|
+
O_RDONLY: 0,
|
|
20
|
+
O_WRONLY: 1,
|
|
21
|
+
O_RDWR: 2,
|
|
22
|
+
O_CREAT: 64,
|
|
23
|
+
O_EXCL: 128,
|
|
24
|
+
O_TRUNC: 512,
|
|
25
|
+
O_APPEND: 1024,
|
|
26
|
+
|
|
27
|
+
// `copyFile` modes.
|
|
28
|
+
COPYFILE_EXCL: 1,
|
|
29
|
+
|
|
30
|
+
// File-type bits, for the predicates on `Stats` that cannot be answered from
|
|
31
|
+
// the module's coarse `kind` alone (a socket and a block device are both
|
|
32
|
+
// "other" there).
|
|
33
|
+
S_IFMT: 0o170000,
|
|
34
|
+
S_IFREG: 0o100000,
|
|
35
|
+
S_IFDIR: 0o040000,
|
|
36
|
+
S_IFLNK: 0o120000,
|
|
37
|
+
S_IFBLK: 0o060000,
|
|
38
|
+
S_IFCHR: 0o020000,
|
|
39
|
+
S_IFIFO: 0o010000,
|
|
40
|
+
S_IFSOCK: 0o140000,
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
export type Constants = typeof constants;
|
package/src/download.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `download`: an HTTP response streamed into a file.
|
|
3
|
+
*
|
|
4
|
+
* The body goes to `<path>.part` as it arrives and is renamed onto `path` once it
|
|
5
|
+
* is complete, so `path` never holds half a file. The partial file is removed when
|
|
6
|
+
* the request fails or is aborted.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import NativeFs from './NativeFs';
|
|
10
|
+
import { nodeError, toPath, withContext, type NodeError } from './shared';
|
|
11
|
+
|
|
12
|
+
export interface DownloadOptions {
|
|
13
|
+
/** `GET` unless set. No request body is sent. */
|
|
14
|
+
method?: string;
|
|
15
|
+
headers?: Record<string, string>;
|
|
16
|
+
/** Called while the body arrives; `total` is `-1` when the server did not say. */
|
|
17
|
+
onProgress?: (received: number, total: number) => void;
|
|
18
|
+
/** Aborting rejects with an `AbortError` and removes the partial file. */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DownloadResult {
|
|
23
|
+
status: number;
|
|
24
|
+
/** Response headers, lower-cased; repeated headers are joined with `, `. */
|
|
25
|
+
headers: Record<string, string>;
|
|
26
|
+
/** The size of the file that was written. */
|
|
27
|
+
bytes: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** What a non-2xx response rejects with. */
|
|
31
|
+
export interface DownloadHttpError extends NodeError {
|
|
32
|
+
status: number;
|
|
33
|
+
headers: Record<string, string>;
|
|
34
|
+
/** The first part of the response body. */
|
|
35
|
+
body: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let nextId = 1;
|
|
39
|
+
|
|
40
|
+
function abortError(): NodeError {
|
|
41
|
+
const error = nodeError('ABORT_ERR', 'The download was aborted');
|
|
42
|
+
error.name = 'AbortError';
|
|
43
|
+
return error;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function toRecord(list: Array<{ name: string; value: string }>) {
|
|
47
|
+
const record: Record<string, string> = {};
|
|
48
|
+
for (const { name, value } of list) {
|
|
49
|
+
record[name] = value;
|
|
50
|
+
}
|
|
51
|
+
return record;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function download(
|
|
55
|
+
url: string,
|
|
56
|
+
path: string,
|
|
57
|
+
options: DownloadOptions = {},
|
|
58
|
+
): Promise<DownloadResult> {
|
|
59
|
+
const { signal, onProgress } = options;
|
|
60
|
+
if (signal?.aborted) {
|
|
61
|
+
throw abortError();
|
|
62
|
+
}
|
|
63
|
+
const target = toPath(path);
|
|
64
|
+
const id = nextId++;
|
|
65
|
+
const subscription = onProgress
|
|
66
|
+
? NativeFs.onDownloadProgress(event => {
|
|
67
|
+
if (event.id === id) {
|
|
68
|
+
onProgress(event.received, event.total);
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
: null;
|
|
72
|
+
const onAbort = () => {
|
|
73
|
+
NativeFs.cancelDownload(id);
|
|
74
|
+
};
|
|
75
|
+
signal?.addEventListener('abort', onAbort);
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const result = await NativeFs.download(url, target, {
|
|
79
|
+
id,
|
|
80
|
+
method: options.method ?? 'GET',
|
|
81
|
+
headers: Object.entries(options.headers ?? {}).map(([name, value]) => ({
|
|
82
|
+
name,
|
|
83
|
+
value,
|
|
84
|
+
})),
|
|
85
|
+
});
|
|
86
|
+
const headers = toRecord(result.headers);
|
|
87
|
+
if (result.status < 200 || result.status >= 300) {
|
|
88
|
+
const error = nodeError(
|
|
89
|
+
'ERR_HTTP_STATUS',
|
|
90
|
+
`HTTP ${result.status} downloading ${url}`,
|
|
91
|
+
) as DownloadHttpError;
|
|
92
|
+
error.status = result.status;
|
|
93
|
+
error.headers = headers;
|
|
94
|
+
error.body = result.body ?? '';
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
return { status: result.status, headers, bytes: result.bytes };
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (signal?.aborted) {
|
|
100
|
+
throw abortError();
|
|
101
|
+
}
|
|
102
|
+
if ((error as NodeError)?.code === 'ABORT_ERR') {
|
|
103
|
+
throw abortError();
|
|
104
|
+
}
|
|
105
|
+
throw withContext(error, 'download', target);
|
|
106
|
+
} finally {
|
|
107
|
+
signal?.removeEventListener('abort', onAbort);
|
|
108
|
+
subscription?.remove();
|
|
109
|
+
}
|
|
110
|
+
}
|