@gjsify/fs 0.0.1 → 0.0.2

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.
Files changed (80) hide show
  1. package/README.md +6 -8
  2. package/lib/cjs/callback.js +131 -0
  3. package/lib/cjs/dirent.js +127 -0
  4. package/lib/cjs/encoding.js +53 -0
  5. package/lib/cjs/file-handle.js +473 -0
  6. package/lib/cjs/fs-watcher.js +79 -0
  7. package/lib/cjs/index.js +95 -0
  8. package/lib/cjs/promises.js +189 -0
  9. package/lib/cjs/read-stream.js +107 -0
  10. package/lib/cjs/stats.js +74 -0
  11. package/lib/cjs/sync.js +155 -0
  12. package/lib/cjs/types/encoding-option.js +15 -0
  13. package/lib/cjs/types/file-read-options.js +15 -0
  14. package/lib/cjs/types/file-read-result.js +15 -0
  15. package/lib/cjs/types/flag-and-open-mode.js +15 -0
  16. package/lib/cjs/types/index.js +22 -0
  17. package/lib/cjs/types/open-flags.js +15 -0
  18. package/lib/cjs/types/read-options.js +15 -0
  19. package/lib/cjs/utils.js +37 -0
  20. package/lib/cjs/write-stream.js +135 -0
  21. package/lib/esm/callback.js +112 -0
  22. package/lib/esm/dirent.js +98 -0
  23. package/lib/esm/encoding.js +34 -0
  24. package/lib/esm/file-handle.js +444 -0
  25. package/lib/esm/fs-watcher.js +50 -0
  26. package/lib/esm/index.js +95 -0
  27. package/lib/esm/promises.js +160 -0
  28. package/lib/esm/read-stream.js +78 -0
  29. package/lib/esm/stats.js +45 -0
  30. package/lib/esm/sync.js +126 -0
  31. package/lib/esm/types/encoding-option.js +0 -0
  32. package/lib/esm/types/file-read-options.js +0 -0
  33. package/lib/esm/types/file-read-result.js +0 -0
  34. package/lib/esm/types/flag-and-open-mode.js +0 -0
  35. package/lib/esm/types/index.js +6 -0
  36. package/lib/esm/types/open-flags.js +0 -0
  37. package/lib/esm/types/read-options.js +0 -0
  38. package/lib/esm/utils.js +18 -0
  39. package/lib/esm/write-stream.js +116 -0
  40. package/package.json +52 -17
  41. package/src/callback.spec.ts +42 -0
  42. package/src/callback.ts +362 -0
  43. package/src/dirent.ts +117 -0
  44. package/src/encoding.ts +40 -0
  45. package/src/file-handle.spec.ts +34 -0
  46. package/src/file-handle.ts +606 -0
  47. package/{fs-watcher.js → src/fs-watcher.ts} +10 -9
  48. package/src/index.ts +95 -0
  49. package/src/promises.spec.ts +172 -0
  50. package/src/promises.ts +349 -0
  51. package/src/read-stream.ts +98 -0
  52. package/src/stat.spec.ts +79 -0
  53. package/src/stats.ts +106 -0
  54. package/src/symlink.spec.ts +38 -0
  55. package/src/sync.spec.ts +205 -0
  56. package/src/sync.ts +239 -0
  57. package/src/test.mts +11 -0
  58. package/src/types/encoding-option.ts +3 -0
  59. package/src/types/file-read-options.ts +15 -0
  60. package/src/types/file-read-result.ts +4 -0
  61. package/src/types/flag-and-open-mode.ts +6 -0
  62. package/src/types/index.ts +6 -0
  63. package/src/types/open-flags.ts +14 -0
  64. package/src/types/read-options.ts +9 -0
  65. package/src/utils.ts +19 -0
  66. package/src/write-stream.ts +143 -0
  67. package/test/file.txt +1 -0
  68. package/test/watch.js +1 -0
  69. package/test.gjs.js +35359 -0
  70. package/test.gjs.js.map +7 -0
  71. package/test.gjs.mjs +40570 -0
  72. package/test.gjs.mjs.meta.json +1 -0
  73. package/test.node.js +1479 -0
  74. package/test.node.js.map +7 -0
  75. package/test.node.mjs +710 -0
  76. package/tsconfig.json +18 -0
  77. package/tsconfig.types.json +8 -0
  78. package/index.js +0 -114
  79. package/test/index.js +0 -90
  80. package/test/resources/file.txt +0 -1
@@ -0,0 +1,606 @@
1
+ import { warnNotImplemented, notImplemented } from '@gjsify/utils';
2
+ import { ReadStream } from "./read-stream.js";
3
+ import { WriteStream } from "./write-stream.js";
4
+ import { Stats } from "./stats.js";
5
+ import { getEncodingFromOptions, encodeUint8Array } from './encoding.js';
6
+ import GLib from '@girs/glib-2.0';
7
+ import { ReadableStream } from "stream/web";
8
+ import { Buffer } from "buffer";
9
+
10
+ import type { Abortable } from 'events';
11
+ import type {
12
+ FlagAndOpenMode,
13
+ FileReadResult,
14
+ FileReadOptions,
15
+ OpenFlags,
16
+ } from './types/index.js';
17
+ import type { FileHandle as IFileHandle, CreateReadStreamOptions, CreateWriteStreamOptions } from 'fs/promises';
18
+ import type {
19
+ ObjectEncodingOptions,
20
+ Mode,
21
+ OpenMode,
22
+ PathLike,
23
+ StatOptions,
24
+ BigIntStats,
25
+ WriteVResult,
26
+ ReadVResult,
27
+ ReadPosition,
28
+ } from 'fs';
29
+ import type { Interface as ReadlineInterface } from 'node:readline';
30
+
31
+ export class FileHandle implements IFileHandle {
32
+
33
+ /** Not part of the default implementation, used internal by gjsify */
34
+ private _file: GLib.IOChannel;
35
+
36
+ /** Not part of the default implementation, used internal by gjsify */
37
+ private static instances: {[fd: number]: FileHandle} = {};
38
+
39
+ constructor(readonly options: {
40
+ path: PathLike,
41
+ flags?: OpenFlags,
42
+ mode?: Mode
43
+ }) {
44
+ this.options.flags ||= "r";
45
+ this.options.mode ||= 0o666;
46
+ this._file = GLib.IOChannel.new_file(options.path.toString(), this.options.flags);
47
+ this.fd = this._file.unix_get_fd();
48
+
49
+ FileHandle.instances[this.fd] = this;
50
+ return FileHandle.getInstance(this.fd);
51
+ }
52
+
53
+
54
+ /**
55
+ * The numeric file descriptor managed by the {FileHandle} object.
56
+ * @since v10.0.0
57
+ */
58
+ readonly fd: number;
59
+
60
+ /** Not part of the default implementation, used internal by gjsify */
61
+ static getInstance(fd: number) {
62
+ const instance = FileHandle.instances[fd];
63
+ if(!instance) {
64
+ throw new Error("No instance found for fd!");
65
+ }
66
+ return FileHandle.instances[fd];
67
+ }
68
+
69
+ /**
70
+ * Alias of `filehandle.writeFile()`.
71
+ *
72
+ * When operating on file handles, the mode cannot be changed from what it was set
73
+ * to with `fsPromises.open()`. Therefore, this is equivalent to `filehandle.writeFile()`.
74
+ * @since v10.0.0
75
+ * @return Fulfills with `undefined` upon success.
76
+ */
77
+ async appendFile(data: string | Uint8Array, options?: (ObjectEncodingOptions & FlagAndOpenMode) | BufferEncoding | null): Promise<void> {
78
+ const encoding = getEncodingFromOptions(options);
79
+ if (typeof data === 'string') {
80
+ data = Buffer.from(data);
81
+ }
82
+
83
+ if (encoding) this._file.set_encoding(encoding);
84
+
85
+ const [status, written] = this._file.write_chars(data, data.length);
86
+
87
+ if(status === GLib.IOStatus.ERROR) {
88
+ throw new Error("Error on append to file!")
89
+ }
90
+
91
+ }
92
+ /**
93
+ * Changes the ownership of the file. A wrapper for [`chown(2)`](http://man7.org/linux/man-pages/man2/chown.2.html).
94
+ * @since v10.0.0
95
+ * @param uid The file's new owner's user id.
96
+ * @param gid The file's new group's group id.
97
+ * @return Fulfills with `undefined` upon success.
98
+ */
99
+ async chown(uid: number, gid: number): Promise<void> {
100
+ warnNotImplemented('fs.FileHandle.chown');
101
+ }
102
+ /**
103
+ * Modifies the permissions on the file. See [`chmod(2)`](http://man7.org/linux/man-pages/man2/chmod.2.html).
104
+ * @since v10.0.0
105
+ * @param mode the file mode bit mask.
106
+ * @return Fulfills with `undefined` upon success.
107
+ */
108
+ async chmod(mode: Mode): Promise<void> {
109
+ warnNotImplemented('fs.FileHandle.chmod');
110
+ }
111
+ /**
112
+ * Unlike the 16 kb default `highWaterMark` for a `stream.Readable`, the stream
113
+ * returned by this method has a default `highWaterMark` of 64 kb.
114
+ *
115
+ * `options` can include `start` and `end` values to read a range of bytes from
116
+ * the file instead of the entire file. Both `start` and `end` are inclusive and
117
+ * start counting at 0, allowed values are in the
118
+ * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. If `start` is
119
+ * omitted or `undefined`, `filehandle.createReadStream()` reads sequentially from
120
+ * the current file position. The `encoding` can be any one of those accepted by `Buffer`.
121
+ *
122
+ * If the `FileHandle` points to a character device that only supports blocking
123
+ * reads (such as keyboard or sound card), read operations do not finish until data
124
+ * is available. This can prevent the process from exiting and the stream from
125
+ * closing naturally.
126
+ *
127
+ * By default, the stream will emit a `'close'` event after it has been
128
+ * destroyed. Set the `emitClose` option to `false` to change this behavior.
129
+ *
130
+ * ```js
131
+ * import { open } from 'fs/promises';
132
+ *
133
+ * const fd = await open('/dev/input/event0');
134
+ * // Create a stream from some character device.
135
+ * const stream = fd.createReadStream();
136
+ * setTimeout(() => {
137
+ * stream.close(); // This may not close the stream.
138
+ * // Artificially marking end-of-stream, as if the underlying resource had
139
+ * // indicated end-of-file by itself, allows the stream to close.
140
+ * // This does not cancel pending read operations, and if there is such an
141
+ * // operation, the process may still not be able to exit successfully
142
+ * // until it finishes.
143
+ * stream.push(null);
144
+ * stream.read(0);
145
+ * }, 100);
146
+ * ```
147
+ *
148
+ * If `autoClose` is false, then the file descriptor won't be closed, even if
149
+ * there's an error. It is the application's responsibility to close it and make
150
+ * sure there's no file descriptor leak. If `autoClose` is set to true (default
151
+ * behavior), on `'error'` or `'end'` the file descriptor will be closed
152
+ * automatically.
153
+ *
154
+ * An example to read the last 10 bytes of a file which is 100 bytes long:
155
+ *
156
+ * ```js
157
+ * import { open } from 'fs/promises';
158
+ *
159
+ * const fd = await open('sample.txt');
160
+ * fd.createReadStream({ start: 90, end: 99 });
161
+ * ```
162
+ * @since v16.11.0
163
+ */
164
+ createReadStream(options?: CreateReadStreamOptions): ReadStream {
165
+ return new ReadStream(this.options.path, options);
166
+ }
167
+ /**
168
+ * `options` may also include a `start` option to allow writing data at some
169
+ * position past the beginning of the file, allowed values are in the
170
+ * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than
171
+ * replacing it may require the `flags` `open` option to be set to `r+` rather than
172
+ * the default `r`. The `encoding` can be any one of those accepted by `Buffer`.
173
+ *
174
+ * If `autoClose` is set to true (default behavior) on `'error'` or `'finish'`the file descriptor will be closed automatically. If `autoClose` is false,
175
+ * then the file descriptor won't be closed, even if there's an error.
176
+ * It is the application's responsibility to close it and make sure there's no
177
+ * file descriptor leak.
178
+ *
179
+ * By default, the stream will emit a `'close'` event after it has been
180
+ * destroyed. Set the `emitClose` option to `false` to change this behavior.
181
+ * @since v16.11.0
182
+ */
183
+ createWriteStream(options?: CreateWriteStreamOptions): WriteStream {
184
+ return new WriteStream(this.options.path, options);
185
+ }
186
+ /**
187
+ * Forces all currently queued I/O operations associated with the file to the
188
+ * operating system's synchronized I/O completion state. Refer to the POSIX [`fdatasync(2)`](http://man7.org/linux/man-pages/man2/fdatasync.2.html) documentation for details.
189
+ *
190
+ * Unlike `filehandle.sync` this method does not flush modified metadata.
191
+ * @since v10.0.0
192
+ * @return Fulfills with `undefined` upon success.
193
+ */
194
+ async datasync(): Promise<void> {
195
+ warnNotImplemented('fs.FileHandle.datasync');
196
+ }
197
+ /**
198
+ * Request that all data for the open file descriptor is flushed to the storage
199
+ * device. The specific implementation is operating system and device specific.
200
+ * Refer to the POSIX [`fsync(2)`](http://man7.org/linux/man-pages/man2/fsync.2.html) documentation for more detail.
201
+ * @since v10.0.0
202
+ * @return Fufills with `undefined` upon success.
203
+ */
204
+ async sync(): Promise<void> {
205
+ warnNotImplemented('fs.FileHandle.sync');
206
+ }
207
+ /**
208
+ * Reads data from the file and stores that in the given buffer.
209
+ *
210
+ * If the file is not modified concurrently, the end-of-file is reached when the
211
+ * number of bytes read is zero.
212
+ * @since v10.0.0
213
+ * @param buffer A buffer that will be filled with the file data read.
214
+ * @param offset The location in the buffer at which to start filling.
215
+ * @param length The number of bytes to read.
216
+ * @param position The location where to begin reading data from the file. If `null`, data will be read from the current file position, and the position will be updated. If `position` is an
217
+ * integer, the current file position will remain unchanged.
218
+ * @return Fulfills upon success with an object with two properties:
219
+ */
220
+ async read<T extends NodeJS.ArrayBufferView>(buffer: T, offset?: number | null, length?: number | null, position?: ReadPosition | null): Promise<FileReadResult<T>>
221
+ async read<T extends NodeJS.ArrayBufferView = Buffer>(options?: FileReadOptions<T>): Promise<FileReadResult<T>>
222
+
223
+ async read<T extends NodeJS.ArrayBufferView = Buffer>(args: any[]): Promise<FileReadResult<T>> {
224
+ let buffer: T | undefined;
225
+ let offset: number | null | undefined;
226
+ let length: number | null | undefined;
227
+ let position: number | null | undefined;
228
+
229
+ if (typeof args[0] === 'object') {
230
+ const options: FileReadOptions<T> = args[0];
231
+ buffer = options.buffer;
232
+ offset = options.offset;
233
+ length = options.length;
234
+ position = options.position;
235
+ } else {
236
+ buffer = args[0];
237
+ offset = args[1];
238
+ length = args[2];
239
+ position = args[3];
240
+ }
241
+
242
+ if(offset) {
243
+ const status = this._file.seek_position(offset, GLib.SeekType.CUR);
244
+ if(status === GLib.IOStatus.ERROR) {
245
+ throw new Error("Error on set offset!")
246
+ }
247
+ }
248
+ if(length) this._file.set_buffer_size(length);
249
+ if(position) {
250
+ const status = this._file.seek_position(position, GLib.SeekType.SET);
251
+ if(status === GLib.IOStatus.ERROR) {
252
+ throw new Error("Error on set position!")
253
+ }
254
+ }
255
+
256
+ const [status, buf, bytesRead] = this._file.read_chars();
257
+ if(status === GLib.IOStatus.ERROR) {
258
+ throw new Error("Error on read!")
259
+ }
260
+
261
+ buffer = buf as T;
262
+
263
+ return {
264
+ bytesRead,
265
+ buffer,
266
+ }
267
+ }
268
+ /**
269
+ * Returns a `ReadableStream` that may be used to read the files data.
270
+ *
271
+ * An error will be thrown if this method is called more than once or is called after the `FileHandle` is closed
272
+ * or closing.
273
+ *
274
+ * ```js
275
+ * import { open } from 'fs/promises';
276
+ *
277
+ * const file = await open('./some/file/to/read');
278
+ *
279
+ * for await (const chunk of file.readableWebStream())
280
+ * console.log(chunk);
281
+ *
282
+ * await file.close();
283
+ * ```
284
+ *
285
+ * While the `ReadableStream` will read the file to completion, it will not close the `FileHandle` automatically. User code must still call the `fileHandle.close()` method.
286
+ *
287
+ * @since v17.0.0
288
+ * @experimental
289
+ */
290
+ readableWebStream(): ReadableStream {
291
+ return new ReadableStream();
292
+ }
293
+ /**
294
+ * Asynchronously reads the entire contents of a file.
295
+ *
296
+ * If `options` is a string, then it specifies the `encoding`.
297
+ *
298
+ * The `FileHandle` has to support reading.
299
+ *
300
+ * If one or more `filehandle.read()` calls are made on a file handle and then a`filehandle.readFile()` call is made, the data will be read from the current
301
+ * position till the end of the file. It doesn't always read from the beginning
302
+ * of the file.
303
+ * @since v10.0.0
304
+ * @return Fulfills upon a successful read with the contents of the file. If no encoding is specified (using `options.encoding`), the data is returned as a {Buffer} object. Otherwise, the
305
+ * data will be a string.
306
+ */
307
+ async readFile(
308
+ options?: {
309
+ encoding?: null | undefined;
310
+ flag?: OpenMode | undefined;
311
+ } | null
312
+ ): Promise<Buffer>
313
+ /**
314
+ * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
315
+ * The `FileHandle` must have been opened for reading.
316
+ * @param options An object that may contain an optional flag.
317
+ * If a flag is not provided, it defaults to `'r'`.
318
+ */
319
+ async readFile(
320
+ options:
321
+ | {
322
+ encoding: BufferEncoding;
323
+ flag?: OpenMode | undefined;
324
+ }
325
+ | BufferEncoding
326
+ ): Promise<string>
327
+ /**
328
+ * Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
329
+ * The `FileHandle` must have been opened for reading.
330
+ * @param options An object that may contain an optional flag.
331
+ * If a flag is not provided, it defaults to `'r'`.
332
+ */
333
+ async readFile(
334
+ options?:
335
+ | (ObjectEncodingOptions & {
336
+ flag?: OpenMode | undefined;
337
+ })
338
+ | BufferEncoding
339
+ | null
340
+ ): Promise<string | Buffer> {
341
+ const encoding = getEncodingFromOptions(options, 'buffer');
342
+ if (encoding) this._file.set_encoding(encoding);
343
+
344
+ const [status, buf] = this._file.read_to_end();
345
+
346
+ if(status === GLib.IOStatus.ERROR) {
347
+ throw new Error("Error on read from file!")
348
+ }
349
+
350
+ const res = encodeUint8Array(encoding, buf);
351
+
352
+ return res;
353
+ }
354
+ /**
355
+ * Convenience method to create a `readline` interface and stream over the file. For example:
356
+ *
357
+ * ```js
358
+ * import { open } from 'node:fs/promises';
359
+ *
360
+ * const file = await open('./some/file/to/read');
361
+ *
362
+ * for await (const line of file.readLines()) {
363
+ * console.log(line);
364
+ * }
365
+ * ```
366
+ *
367
+ * @since v18.11.0
368
+ * @param options See `filehandle.createReadStream()` for the options.
369
+ */
370
+ readLines(options?: CreateReadStreamOptions): ReadlineInterface {
371
+ notImplemented('fs.FileHandle.readLines');
372
+ }
373
+ /**
374
+ * @since v10.0.0
375
+ * @return Fulfills with an {fs.Stats} for the file.
376
+ */
377
+ async stat(
378
+ opts?: StatOptions & {
379
+ bigint?: false | undefined;
380
+ }
381
+ ): Promise<Stats>
382
+ async stat(
383
+ opts: StatOptions & {
384
+ bigint: true;
385
+ }
386
+ ): Promise<BigIntStats>
387
+ async stat(opts?: StatOptions): Promise<Stats | BigIntStats> {
388
+ warnNotImplemented('fs.FileHandle.stat');
389
+ return new Stats(this.options.path.toString());
390
+ }
391
+ /**
392
+ * Truncates the file.
393
+ *
394
+ * If the file was larger than `len` bytes, only the first `len` bytes will be
395
+ * retained in the file.
396
+ *
397
+ * The following example retains only the first four bytes of the file:
398
+ *
399
+ * ```js
400
+ * import { open } from 'fs/promises';
401
+ *
402
+ * let filehandle = null;
403
+ * try {
404
+ * filehandle = await open('temp.txt', 'r+');
405
+ * await filehandle.truncate(4);
406
+ * } finally {
407
+ * await filehandle?.close();
408
+ * }
409
+ * ```
410
+ *
411
+ * If the file previously was shorter than `len` bytes, it is extended, and the
412
+ * extended part is filled with null bytes (`'\0'`):
413
+ *
414
+ * If `len` is negative then `0` will be used.
415
+ * @since v10.0.0
416
+ * @param [len=0]
417
+ * @return Fulfills with `undefined` upon success.
418
+ */
419
+ async truncate(len?: number): Promise<void> {
420
+ warnNotImplemented('fs.FileHandle.truncate');
421
+ }
422
+ /**
423
+ * Change the file system timestamps of the object referenced by the `FileHandle` then resolves the promise with no arguments upon success.
424
+ * @since v10.0.0
425
+ */
426
+ async utimes(atime: string | number | Date, mtime: string | number | Date): Promise<void> {
427
+ warnNotImplemented('fs.FileHandle.utimes');
428
+ }
429
+ /**
430
+ * Asynchronously writes data to a file, replacing the file if it already exists.`data` can be a string, a buffer, an
431
+ * [AsyncIterable](https://tc39.github.io/ecma262/#sec-asynciterable-interface) or
432
+ * [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) object.
433
+ * The promise is resolved with no arguments upon success.
434
+ *
435
+ * If `options` is a string, then it specifies the `encoding`.
436
+ *
437
+ * The `FileHandle` has to support writing.
438
+ *
439
+ * It is unsafe to use `filehandle.writeFile()` multiple times on the same file
440
+ * without waiting for the promise to be resolved (or rejected).
441
+ *
442
+ * If one or more `filehandle.write()` calls are made on a file handle and then a`filehandle.writeFile()` call is made, the data will be written from the
443
+ * current position till the end of the file. It doesn't always write from the
444
+ * beginning of the file.
445
+ * @since v10.0.0
446
+ */
447
+ async writeFile(data: string | Uint8Array, options?: (ObjectEncodingOptions & FlagAndOpenMode & Abortable) | BufferEncoding | null): Promise<void> {
448
+ warnNotImplemented('fs.FileHandle.writeFile');
449
+ }
450
+ /**
451
+ * Write `buffer` to the file.
452
+ *
453
+ * The promise is resolved with an object containing two properties:
454
+ *
455
+ * It is unsafe to use `filehandle.write()` multiple times on the same file
456
+ * without waiting for the promise to be resolved (or rejected). For this
457
+ * scenario, use `filehandle.createWriteStream()`.
458
+ *
459
+ * On Linux, positional writes do not work when the file is opened in append mode.
460
+ * The kernel ignores the position argument and always appends the data to
461
+ * the end of the file.
462
+ * @since v10.0.0
463
+ * @param [offset=0] The start position from within `buffer` where the data to write begins.
464
+ * @param [length=buffer.byteLength - offset] The number of bytes from `buffer` to write.
465
+ * @param position The offset from the beginning of the file where the data from `buffer` should be written. If `position` is not a `number`, the data will be written at the current position.
466
+ * See the POSIX pwrite(2) documentation for more detail.
467
+ */
468
+ async write<TBuffer extends NodeJS.ArrayBufferView>(
469
+ buffer: TBuffer,
470
+ offset?: number | null,
471
+ length?: number | null,
472
+ position?: number | null
473
+ ): Promise<{
474
+ bytesWritten: number;
475
+ buffer: TBuffer;
476
+ }>;
477
+ async write(
478
+ data: string,
479
+ position?: number | null,
480
+ encoding?: BufferEncoding | null
481
+ ): Promise<{
482
+ bytesWritten: number;
483
+ buffer: string;
484
+ }>
485
+ async write<TBuffer extends NodeJS.ArrayBufferView>(
486
+ data: string | TBuffer,
487
+ ...args: any[]
488
+ ): Promise<{
489
+ bytesWritten: number;
490
+ buffer: string | TBuffer;
491
+ }> {
492
+ let position: number | null = null;
493
+ let encoding: BufferEncoding | 'buffer' | null = null;
494
+ let offset: number | null = null;
495
+ let length: number | null = null;
496
+
497
+ if(typeof data === 'string') {
498
+ position = args[0];
499
+ encoding = args[1];
500
+ } else {
501
+ offset = args[0];
502
+ length = args[1];
503
+ position = args[2];
504
+ }
505
+
506
+ encoding = getEncodingFromOptions(encoding, typeof data === 'string' ? 'utf8' : null);
507
+ if (encoding) {
508
+ console.log("set_encoding", encoding, this._file.get_encoding(), typeof data);
509
+
510
+ this._file.set_encoding(encoding === 'buffer' ? null : encoding);
511
+ }
512
+
513
+ if(offset) {
514
+ const status = this._file.seek_position(offset, GLib.SeekType.CUR);
515
+ if(status === GLib.IOStatus.ERROR) {
516
+ throw new Error("Error on set offset!")
517
+ }
518
+ }
519
+ if(length) this._file.set_buffer_size(length);
520
+
521
+ if(position) {
522
+ const status = this._file.seek_position(position, GLib.SeekType.SET);
523
+ if(status === GLib.IOStatus.ERROR) {
524
+ throw new Error("Error on set position!")
525
+ }
526
+ }
527
+
528
+ let bytesWritten = 0;
529
+ let status: GLib.IOStatus;
530
+
531
+ if(typeof data === 'string') {
532
+ status = this._file.write_unichar(data);
533
+ bytesWritten = data.length;
534
+ } else {
535
+ const [_status, _bytesWritten] = this._file.write_chars(data as Uint8Array, length);
536
+ bytesWritten = _bytesWritten;
537
+ status = _status;
538
+ }
539
+
540
+ if(status === GLib.IOStatus.ERROR) {
541
+ throw new Error("Error on write to file!")
542
+ }
543
+
544
+ return {
545
+ bytesWritten,
546
+ buffer: data
547
+ }
548
+ }
549
+
550
+
551
+ /**
552
+ * Write an array of [ArrayBufferView](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) s to the file.
553
+ *
554
+ * The promise is resolved with an object containing a two properties:
555
+ *
556
+ * It is unsafe to call `writev()` multiple times on the same file without waiting
557
+ * for the promise to be resolved (or rejected).
558
+ *
559
+ * On Linux, positional writes don't work when the file is opened in append mode.
560
+ * The kernel ignores the position argument and always appends the data to
561
+ * the end of the file.
562
+ * @since v12.9.0
563
+ * @param position The offset from the beginning of the file where the data from `buffers` should be written. If `position` is not a `number`, the data will be written at the current
564
+ * position.
565
+ */
566
+ async writev(buffers: ReadonlyArray<NodeJS.ArrayBufferView>, position?: number): Promise<WriteVResult> {
567
+ warnNotImplemented('fs.FileHandle.writev');
568
+ return {
569
+ bytesWritten: 0,
570
+ buffers: [],
571
+ }
572
+ }
573
+ /**
574
+ * Read from a file and write to an array of [ArrayBufferView](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) s
575
+ * @since v13.13.0, v12.17.0
576
+ * @param position The offset from the beginning of the file where the data should be read from. If `position` is not a `number`, the data will be read from the current position.
577
+ * @return Fulfills upon success an object containing two properties:
578
+ */
579
+ async readv(buffers: ReadonlyArray<NodeJS.ArrayBufferView>, position?: number): Promise<ReadVResult> {
580
+ warnNotImplemented('fs.FileHandle.readv');
581
+ return {
582
+ bytesRead: 0,
583
+ buffers: [],
584
+ }
585
+ }
586
+ /**
587
+ * Closes the file handle after waiting for any pending operation on the handle to
588
+ * complete.
589
+ *
590
+ * ```js
591
+ * import { open } from 'fs/promises';
592
+ *
593
+ * let filehandle;
594
+ * try {
595
+ * filehandle = await open('thefile.txt', 'r');
596
+ * } finally {
597
+ * await filehandle?.close();
598
+ * }
599
+ * ```
600
+ * @since v10.0.0
601
+ * @return Fulfills with `undefined` upon success.
602
+ */
603
+ async close(): Promise<void> {
604
+ this._file.close();
605
+ }
606
+ }
@@ -1,13 +1,12 @@
1
- const Gio = imports.gi.Gio;
2
- const mainloop = imports.cgjs.mainloop;
3
-
4
- const EventEmitter = require('events').EventEmitter;
5
-
1
+ import Gio from '@girs/gio-2.0';
2
+ import { EventEmitter } from 'events';
6
3
  const privates = new WeakMap;
7
4
 
8
- module.exports = class FSWatcher extends EventEmitter {
5
+ import type { FSWatcher as IFSWatcher } from 'fs';
9
6
 
10
- constructor(filename, options, listener) {
7
+ export class FSWatcher extends EventEmitter implements IFSWatcher {
8
+
9
+ constructor(filename: string, options, listener) {
11
10
  super();
12
11
  if (!options || typeof options !== 'object')
13
12
  options = {persistent: true};
@@ -26,14 +25,14 @@ module.exports = class FSWatcher extends EventEmitter {
26
25
  watcher
27
26
  });
28
27
  if (listener) this.on('change', listener);
29
- if (options.persistent) mainloop.wait();
28
+ // TODO: if (options.persistent) mainloop.wait();
30
29
  }
31
30
 
32
31
  close() {
33
32
  const {cancellable, persistent} = privates.get(this);
34
33
  if (!cancellable.is_cancelled()) {
35
34
  cancellable.cancel();
36
- if (persistent) mainloop.go();
35
+ // TODO: if (persistent) mainloop.go();
37
36
  }
38
37
  }
39
38
 
@@ -53,3 +52,5 @@ function changed(watcher, file, otherFile, eventType) {
53
52
  break;
54
53
  }
55
54
  }
55
+
56
+ export default FSWatcher;