@gjsify/fs 0.3.21 → 0.4.3

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 (69) hide show
  1. package/lib/esm/_virtual/_rolldown/runtime.js +1 -1
  2. package/lib/esm/callback.js +1 -1
  3. package/lib/esm/cp.js +1 -1
  4. package/lib/esm/dir.js +1 -1
  5. package/lib/esm/dirent.js +1 -1
  6. package/lib/esm/encoding.js +1 -1
  7. package/lib/esm/errors.js +1 -1
  8. package/lib/esm/fd-ops.js +1 -1
  9. package/lib/esm/file-handle.js +1 -1
  10. package/lib/esm/fs-watcher.js +1 -1
  11. package/lib/esm/glob.js +1 -1
  12. package/lib/esm/read-stream.js +1 -1
  13. package/lib/esm/stat-watcher.js +1 -1
  14. package/lib/esm/statfs.js +1 -1
  15. package/lib/esm/stats.js +1 -1
  16. package/lib/esm/sync.js +1 -1
  17. package/lib/esm/utils.js +1 -1
  18. package/lib/esm/utimes.js +1 -1
  19. package/lib/esm/write-stream.js +1 -1
  20. package/package.json +51 -48
  21. package/src/callback.spec.ts +0 -296
  22. package/src/callback.ts +0 -684
  23. package/src/cp.spec.ts +0 -181
  24. package/src/cp.ts +0 -328
  25. package/src/dir.spec.ts +0 -204
  26. package/src/dir.ts +0 -199
  27. package/src/dirent.ts +0 -165
  28. package/src/encoding.ts +0 -45
  29. package/src/errors.spec.ts +0 -389
  30. package/src/errors.ts +0 -19
  31. package/src/extended.spec.ts +0 -706
  32. package/src/fd-ops.spec.ts +0 -234
  33. package/src/fd-ops.ts +0 -251
  34. package/src/file-handle.spec.ts +0 -115
  35. package/src/file-handle.ts +0 -856
  36. package/src/fs-watcher.ts +0 -198
  37. package/src/glob.spec.ts +0 -201
  38. package/src/glob.ts +0 -205
  39. package/src/index.ts +0 -313
  40. package/src/new-apis.spec.ts +0 -505
  41. package/src/promises.spec.ts +0 -812
  42. package/src/promises.ts +0 -686
  43. package/src/read-stream.ts +0 -128
  44. package/src/stat-watcher.ts +0 -116
  45. package/src/stat.spec.ts +0 -87
  46. package/src/statfs.spec.ts +0 -67
  47. package/src/statfs.ts +0 -92
  48. package/src/stats.ts +0 -207
  49. package/src/streams.spec.ts +0 -513
  50. package/src/symlink.spec.ts +0 -188
  51. package/src/sync.spec.ts +0 -377
  52. package/src/sync.ts +0 -562
  53. package/src/test.mts +0 -27
  54. package/src/types/encoding-option.ts +0 -3
  55. package/src/types/file-read-options.ts +0 -15
  56. package/src/types/file-read-result.ts +0 -4
  57. package/src/types/flag-and-open-mode.ts +0 -6
  58. package/src/types/index.ts +0 -6
  59. package/src/types/open-flags.ts +0 -14
  60. package/src/types/read-options.ts +0 -9
  61. package/src/utils.ts +0 -31
  62. package/src/utimes.spec.ts +0 -113
  63. package/src/utimes.ts +0 -97
  64. package/src/watch.spec.ts +0 -171
  65. package/src/watchfile.spec.ts +0 -185
  66. package/src/write-stream.ts +0 -142
  67. package/test/file.txt +0 -1
  68. package/tsconfig.json +0 -29
  69. package/tsconfig.tsbuildinfo +0 -1
package/src/sync.ts DELETED
@@ -1,562 +0,0 @@
1
- // Reference: Node.js lib/fs.js (sync API)
2
- // Reimplemented for GJS using Gio.File synchronous operations
3
-
4
- import GLib from '@girs/glib-2.0';
5
- import Gio from '@girs/gio-2.0';
6
- import { existsSync } from '@gjsify/utils';
7
- import { Buffer } from 'node:buffer';
8
- import { join } from 'node:path';
9
-
10
- import FSWatcher from './fs-watcher.js';
11
- import { getEncodingFromOptions, encodeUint8Array, decode } from './encoding.js';
12
- import { FileHandle } from './file-handle.js';
13
- import { Dirent } from './dirent.js';
14
- import { Stats, BigIntStats, STAT_ATTRIBUTES } from './stats.js';
15
- import { createNodeError, isNotFoundError } from './errors.js';
16
- import { tempDirPath, normalizePath } from './utils.js';
17
-
18
- import type { OpenFlags, EncodingOption } from './types/index.js';
19
- import type {
20
- PathLike,
21
- Mode,
22
- MakeDirectoryOptions,
23
- BufferEncodingOption,
24
- RmOptions,
25
- RmDirOptions,
26
- StatSyncOptions,
27
- } from 'node:fs'; // Types from @types/node
28
-
29
- export { existsSync }
30
-
31
- // --- stat / lstat ---
32
-
33
- export function statSync(path: PathLike, options?: StatSyncOptions): Stats | BigIntStats | undefined {
34
- const pathStr = normalizePath(path);
35
- try {
36
- const file = Gio.File.new_for_path(pathStr);
37
- const info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, null);
38
- return options?.bigint ? new BigIntStats(info, pathStr) : new Stats(info, pathStr);
39
- } catch (err: unknown) {
40
- if (options?.throwIfNoEntry === false && isNotFoundError(err)) return undefined;
41
- throw createNodeError(err, 'stat', pathStr);
42
- }
43
- }
44
-
45
- export function lstatSync(path: PathLike, options?: StatSyncOptions): Stats | BigIntStats | undefined {
46
- const pathStr = normalizePath(path);
47
- try {
48
- const file = Gio.File.new_for_path(pathStr);
49
- const info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
50
- return options?.bigint ? new BigIntStats(info, pathStr) : new Stats(info, pathStr);
51
- } catch (err: unknown) {
52
- if (options?.throwIfNoEntry === false && isNotFoundError(err)) return undefined;
53
- throw createNodeError(err, 'lstat', pathStr);
54
- }
55
- }
56
-
57
- // --- readdir ---
58
-
59
- export function readdirSync(
60
- path: PathLike,
61
- options?: { withFileTypes?: boolean; encoding?: string; recursive?: boolean }
62
- ): string[] | Dirent[] {
63
- const pathStr = normalizePath(path);
64
- const file = Gio.File.new_for_path(pathStr);
65
- const enumerator = file.enumerate_children(
66
- 'standard::name,standard::type',
67
- Gio.FileQueryInfoFlags.NONE,
68
- null,
69
- );
70
-
71
- const result: (string | Dirent)[] = [];
72
- let info = enumerator.next_file(null);
73
-
74
- while (info !== null) {
75
- const childName = info.get_name();
76
- const childPath = join(pathStr, childName);
77
-
78
- if (options?.withFileTypes) {
79
- result.push(new Dirent(childPath, childName));
80
- } else {
81
- result.push(childName);
82
- }
83
-
84
- if (options?.recursive && info.get_file_type() === Gio.FileType.DIRECTORY) {
85
- const subEntries = readdirSync(childPath, options);
86
- for (const entry of subEntries) {
87
- if (typeof entry === 'string') {
88
- result.push(join(childName, entry));
89
- } else {
90
- result.push(entry);
91
- }
92
- }
93
- }
94
-
95
- info = enumerator.next_file(null);
96
- }
97
-
98
- return result as string[] | Dirent[];
99
- }
100
-
101
- // --- realpath ---
102
-
103
- const MAX_SYMLINK_DEPTH = 40; // matches Linux MAXSYMLINKS
104
-
105
- export function realpathSync(path: PathLike): string {
106
- const pathStr = normalizePath(path);
107
- let current = Gio.File.new_for_path(pathStr);
108
- let depth = 0;
109
-
110
- while (true) {
111
- const info = current.query_info(
112
- 'standard::is-symlink,standard::symlink-target',
113
- Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
114
- null,
115
- );
116
-
117
- if (!info.get_is_symlink()) {
118
- return current.get_path()!;
119
- }
120
-
121
- const target = info.get_symlink_target()!;
122
- const parent = current.get_parent();
123
- current = parent ? parent.resolve_relative_path(target) : Gio.File.new_for_path(target);
124
-
125
- if (++depth > MAX_SYMLINK_DEPTH) {
126
- throw new Error(`ELOOP: too many levels of symbolic links, realpath '${pathStr}'`);
127
- }
128
- }
129
- }
130
- (realpathSync as unknown as { native: typeof realpathSync }).native = realpathSync;
131
-
132
- // --- symlink ---
133
-
134
- export function symlinkSync(target: PathLike, path: PathLike, _type?: 'file' | 'dir' | 'junction'): void {
135
- const pathStr = normalizePath(path);
136
- const targetStr = normalizePath(target);
137
- const file = Gio.File.new_for_path(pathStr);
138
- file.make_symbolic_link(targetStr, null);
139
- }
140
-
141
- export function readFileSync(path: PathLike, options: any = { encoding: null, flag: 'r' }) {
142
- const pathStr = normalizePath(path);
143
- const file = Gio.File.new_for_path(pathStr);
144
-
145
- try {
146
- const [ok, data] = file.load_contents(null);
147
-
148
- if (!ok) {
149
- throw createNodeError(new Error('failed to read file'), 'read', pathStr);
150
- }
151
-
152
- return encodeUint8Array(getEncodingFromOptions(options, "buffer"), data);
153
- } catch (err: unknown) {
154
- if ((err as { code?: unknown }).code && typeof (err as { code?: unknown }).code === 'string') throw err; // Already a Node error
155
- throw createNodeError(err, 'read', pathStr);
156
- }
157
- }
158
-
159
- /**
160
- * Synchronously creates a directory. Returns `undefined`, or if `recursive` is`true`, the first directory path created.
161
- * This is the synchronous version of {@link mkdir}.
162
- *
163
- * See the POSIX [`mkdir(2)`](http://man7.org/linux/man-pages/man2/mkdir.2.html) documentation for more details.
164
- * @since v0.1.21
165
- */
166
- export function mkdirSync(
167
- path: PathLike,
168
- options: MakeDirectoryOptions & {
169
- recursive: true;
170
- }
171
- ): string | undefined;
172
- /**
173
- * Synchronous mkdir(2) - create a directory.
174
- * @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
175
- * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
176
- * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
177
- */
178
- export function mkdirSync(
179
- path: PathLike,
180
- options?:
181
- | Mode
182
- | (MakeDirectoryOptions & {
183
- recursive?: false | undefined;
184
- })
185
- | null
186
- ): void;
187
- /**
188
- * Synchronous mkdir(2) - create a directory.
189
- * @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
190
- * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
191
- * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
192
- */
193
- export function mkdirSync(path: PathLike, options?: Mode | MakeDirectoryOptions | null): string | undefined | void
194
- /**
195
- * Synchronous mkdir(2) - create a directory.
196
- * @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
197
- * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
198
- * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
199
- */
200
- export function mkdirSync(path: PathLike, options?: Mode | MakeDirectoryOptions | null): string | undefined | void {
201
-
202
- let recursive = false
203
- let mode: Mode | undefined = 0o777;
204
-
205
- if (typeof options === 'object') {
206
- if(options?.recursive) recursive = options.recursive;
207
- if(options?.mode) mode = options.mode;
208
- } else {
209
- mode = options || 0o777;
210
- }
211
-
212
- path = normalizePath(path);
213
-
214
- if(typeof mode === 'string') {
215
- throw new TypeError("mode as string is currently not supported!");
216
- }
217
-
218
- if (recursive) {
219
- return mkdirSyncRecursive(path, mode as number);
220
- }
221
-
222
- // Non-recursive: create a single directory
223
- const file = Gio.File.new_for_path(path);
224
- try {
225
- file.make_directory(null);
226
- } catch (err: unknown) {
227
- throw createNodeError(err, 'mkdir', path);
228
- }
229
- return undefined;
230
- }
231
-
232
- /**
233
- * Recursively creates directories, similar to `mkdir -p`.
234
- * Returns the first directory path created, or undefined if all directories already existed.
235
- */
236
- function mkdirSyncRecursive(pathStr: string, mode: number): string | undefined {
237
- const file = Gio.File.new_for_path(pathStr);
238
-
239
- // Try to create the directory directly
240
- try {
241
- file.make_directory(null);
242
- // This directory was created successfully — it's a candidate for "first created"
243
- return pathStr;
244
- } catch (err: unknown) {
245
- const gErr = err as { code?: number };
246
- // If it already exists, nothing to create
247
- if (gErr.code === Gio.IOErrorEnum.EXISTS) {
248
- return undefined;
249
- }
250
- // If parent doesn't exist, create parent first then retry
251
- if (gErr.code === Gio.IOErrorEnum.NOT_FOUND) {
252
- const parentPath = join(pathStr, '..');
253
- const resolvedParent = Gio.File.new_for_path(parentPath).get_path()!;
254
- if (resolvedParent === pathStr) {
255
- // Reached root, cannot go further
256
- throw createNodeError(err, 'mkdir', pathStr);
257
- }
258
- const firstCreated = mkdirSyncRecursive(resolvedParent, mode);
259
- // Now create this directory
260
- const retryFile = Gio.File.new_for_path(pathStr);
261
- try {
262
- retryFile.make_directory(null);
263
- } catch (retryErr: unknown) {
264
- throw createNodeError(retryErr, 'mkdir', pathStr);
265
- }
266
- return firstCreated ?? pathStr;
267
- }
268
- throw createNodeError(err, 'mkdir', pathStr);
269
- }
270
- }
271
-
272
- /**
273
- * Synchronous [`rmdir(2)`](http://man7.org/linux/man-pages/man2/rmdir.2.html). Returns `undefined`.
274
- *
275
- * Using `fs.rmdirSync()` on a file (not a directory) results in an `ENOENT` error
276
- * on Windows and an `ENOTDIR` error on POSIX.
277
- *
278
- * To get a behavior similar to the `rm -rf` Unix command, use {@link rmSync} with options `{ recursive: true, force: true }`.
279
- * @since v0.1.21
280
- */
281
- export function rmdirSync(path: PathLike, _options?: RmDirOptions): void {
282
- const pathStr = normalizePath(path);
283
- const file = Gio.File.new_for_path(pathStr);
284
- try {
285
- // Check if it's a directory
286
- const info = file.query_info('standard::type', Gio.FileQueryInfoFlags.NONE, null);
287
- if (info.get_file_type() !== Gio.FileType.DIRECTORY) {
288
- const err = Object.assign(new Error(), { code: 4 }); // Gio.IOErrorEnum.NOT_DIRECTORY
289
- throw createNodeError(err, 'rmdir', pathStr);
290
- }
291
- // Check if empty — rmdir only removes empty directories (use rmSync for recursive)
292
- const enumerator = file.enumerate_children('standard::name', Gio.FileQueryInfoFlags.NONE, null);
293
- if (enumerator.next_file(null) !== null) {
294
- const err = Object.assign(new Error(), { code: 5 }); // Gio.IOErrorEnum.NOT_EMPTY
295
- throw createNodeError(err, 'rmdir', pathStr);
296
- }
297
- file.delete(null);
298
- } catch (err: unknown) {
299
- if ((err as { code?: unknown }).code && typeof (err as { code?: unknown }).code === 'string') throw err; // Already a Node error
300
- throw createNodeError(err, 'rmdir', pathStr);
301
- }
302
- }
303
-
304
- export function unlinkSync(path: PathLike): void {
305
- const pathStr = normalizePath(path);
306
- const file = Gio.File.new_for_path(pathStr);
307
- try {
308
- file.delete(null);
309
- } catch (err: unknown) {
310
- throw createNodeError(err, 'unlink', pathStr);
311
- }
312
- }
313
-
314
- export function writeFileSync(path: PathLike, data: string | Uint8Array) {
315
- GLib.file_set_contents(normalizePath(path), data);
316
- }
317
-
318
- // --- rename ---
319
-
320
- export function renameSync(oldPath: PathLike, newPath: PathLike): void {
321
- const oldStr = normalizePath(oldPath);
322
- const newStr = normalizePath(newPath);
323
- const src = Gio.File.new_for_path(oldStr);
324
- const dest = Gio.File.new_for_path(newStr);
325
- try {
326
- src.move(dest, Gio.FileCopyFlags.OVERWRITE, null, null);
327
- } catch (err: unknown) {
328
- throw createNodeError(err, 'rename', oldStr, newStr);
329
- }
330
- }
331
-
332
- // --- copyFile ---
333
-
334
- export function copyFileSync(src: PathLike, dest: PathLike, mode?: number): void {
335
- const srcStr = normalizePath(src);
336
- const destStr = normalizePath(dest);
337
- const srcFile = Gio.File.new_for_path(srcStr);
338
- const destFile = Gio.File.new_for_path(destStr);
339
- let flags = Gio.FileCopyFlags.NONE;
340
- // mode 0 = default (overwrite), COPYFILE_EXCL (1) = no overwrite
341
- if (mode && (mode & 1) === 0) {
342
- flags = Gio.FileCopyFlags.OVERWRITE;
343
- } else if (!mode) {
344
- flags = Gio.FileCopyFlags.OVERWRITE;
345
- }
346
- try {
347
- srcFile.copy(destFile, flags, null, null);
348
- } catch (err: unknown) {
349
- throw createNodeError(err, 'copyfile', srcStr, destStr);
350
- }
351
- }
352
-
353
- // --- access ---
354
-
355
- export function accessSync(path: PathLike, mode?: number): void {
356
- const pathStr = normalizePath(path);
357
- const file = Gio.File.new_for_path(pathStr);
358
- try {
359
- const info = file.query_info('access::*', Gio.FileQueryInfoFlags.NONE, null);
360
- // mode: F_OK=0, R_OK=4, W_OK=2, X_OK=1
361
- if (mode !== undefined && mode !== 0) {
362
- // Gio.IOErrorEnum.PERMISSION_DENIED = 14 → maps to EACCES via createNodeError
363
- const permErr = { code: 14, message: `permission denied, access '${pathStr}'` };
364
- if ((mode & 4) && !info.get_attribute_boolean('access::can-read')) {
365
- throw createNodeError(permErr, 'access', pathStr);
366
- }
367
- if ((mode & 2) && !info.get_attribute_boolean('access::can-write')) {
368
- throw createNodeError(permErr, 'access', pathStr);
369
- }
370
- if ((mode & 1) && !info.get_attribute_boolean('access::can-execute')) {
371
- throw createNodeError(permErr, 'access', pathStr);
372
- }
373
- }
374
- } catch (err: unknown) {
375
- if ((err as { code?: unknown }).code && typeof (err as { code?: unknown }).code === 'string') throw err; // Already a Node-style error
376
- throw createNodeError(err, 'access', pathStr);
377
- }
378
- }
379
-
380
- // --- appendFile ---
381
-
382
- export function appendFileSync(path: PathLike, data: string | Uint8Array, options?: { encoding?: string; mode?: number; flag?: string } | string): void {
383
- const pathStr = normalizePath(path);
384
- const file = Gio.File.new_for_path(pathStr);
385
- let bytes: Uint8Array;
386
- if (typeof data === 'string') {
387
- bytes = new TextEncoder().encode(data);
388
- } else {
389
- bytes = data;
390
- }
391
-
392
- try {
393
- const stream = file.append_to(Gio.FileCreateFlags.NONE, null);
394
- if (bytes.length > 0) {
395
- stream.write_bytes(new GLib.Bytes(bytes), null);
396
- }
397
- stream.close(null);
398
- } catch (err: unknown) {
399
- throw createNodeError(err, 'appendfile', pathStr);
400
- }
401
- }
402
-
403
- // --- readlink ---
404
-
405
- export function readlinkSync(path: PathLike, options?: { encoding?: string } | string): string | Buffer {
406
- const pathStr = normalizePath(path);
407
- const file = Gio.File.new_for_path(pathStr);
408
- try {
409
- const info = file.query_info('standard::symlink-target', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
410
- const target = info.get_symlink_target();
411
- if (!target) {
412
- throw Object.assign(new Error(`EINVAL: invalid argument, readlink '${pathStr}'`), { code: 'EINVAL', errno: -22, syscall: 'readlink', path: pathStr });
413
- }
414
- const encoding = typeof options === 'string' ? options : options?.encoding;
415
- if (encoding === 'buffer') {
416
- return Buffer.from(target);
417
- }
418
- return target;
419
- } catch (err: unknown) {
420
- if (typeof (err as { code?: unknown }).code === 'string') throw err;
421
- throw createNodeError(err, 'readlink', pathStr);
422
- }
423
- }
424
-
425
- // --- link ---
426
-
427
- export function linkSync(existingPath: PathLike, newPath: PathLike): void {
428
- const existingStr = normalizePath(existingPath);
429
- const newStr = normalizePath(newPath);
430
- // Gio doesn't have a direct hard link API, use GLib
431
- const result = GLib.spawn_command_line_sync(`ln ${existingStr} ${newStr}`);
432
- if (!result[0]) {
433
- throw Object.assign(new Error(`EPERM: operation not permitted, link '${existingStr}' -> '${newStr}'`), { code: 'EPERM', errno: -1, syscall: 'link', path: existingStr, dest: newStr });
434
- }
435
- }
436
-
437
- // --- truncate ---
438
-
439
- export function truncateSync(path: PathLike, len?: number): void {
440
- const pathStr = normalizePath(path);
441
- const file = Gio.File.new_for_path(pathStr);
442
- try {
443
- const stream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
444
- if (len && len > 0) {
445
- // Read existing content, truncate to len
446
- const [, data] = file.load_contents(null);
447
- const truncated = data.slice(0, len);
448
- if (truncated.length > 0) {
449
- stream.write_bytes(new GLib.Bytes(truncated), null);
450
- }
451
- }
452
- stream.close(null);
453
- } catch (err: unknown) {
454
- throw createNodeError(err, 'truncate', pathStr);
455
- }
456
- }
457
-
458
- // --- chmodSync ---
459
-
460
- export function chmodSync(path: PathLike, mode: Mode): void {
461
- const pathStr = normalizePath(path);
462
- const modeNum = typeof mode === 'string' ? parseInt(mode, 8) : mode;
463
- const result = GLib.spawn_command_line_sync(`chmod ${modeNum.toString(8)} ${pathStr}`);
464
- if (!result[0]) {
465
- throw Object.assign(new Error(`EPERM: operation not permitted, chmod '${pathStr}'`), { code: 'EPERM', errno: -1, syscall: 'chmod', path: pathStr });
466
- }
467
- }
468
-
469
- // --- chownSync ---
470
-
471
- export function chownSync(path: PathLike, uid: number, gid: number): void {
472
- const pathStr = normalizePath(path);
473
- const result = GLib.spawn_command_line_sync(`chown ${uid}:${gid} ${pathStr}`);
474
- if (!result[0]) {
475
- throw Object.assign(new Error(`EPERM: operation not permitted, chown '${pathStr}'`), { code: 'EPERM', errno: -1, syscall: 'chown', path: pathStr });
476
- }
477
- }
478
-
479
- export function watch(filename: PathLike, options: { persistent?: boolean; recursive?: boolean; encoding?: string } | undefined, listener: ((eventType: string, filename: string | null) => void) | undefined) {
480
- return new FSWatcher(normalizePath(filename), options, listener);
481
- }
482
-
483
- export function openSync(path: PathLike, flags?: OpenFlags | number, mode?: Mode): FileHandle {
484
- return new FileHandle({ path, flags: flags as OpenFlags | undefined, mode });
485
- }
486
-
487
- /**
488
- * Returns the created directory path.
489
- *
490
- * For detailed information, see the documentation of the asynchronous version of
491
- * this API: {@link mkdtemp}.
492
- *
493
- * The optional `options` argument can be a string specifying an encoding, or an
494
- * object with an `encoding` property specifying the character encoding to use.
495
- * @since v5.10.0
496
- */
497
- export function mkdtempSync(prefix: string, options?: EncodingOption): string;
498
- /**
499
- * Synchronously creates a unique temporary directory.
500
- * Generates six random characters to be appended behind a required prefix to create a unique temporary directory.
501
- * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
502
- */
503
- export function mkdtempSync(prefix: string, options: BufferEncodingOption): Buffer;
504
- /**
505
- * Synchronously creates a unique temporary directory.
506
- * Generates six random characters to be appended behind a required prefix to create a unique temporary directory.
507
- * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
508
- */
509
- export function mkdtempSync(prefix: string, options?: EncodingOption): string | Buffer;
510
-
511
- export function mkdtempSync(prefix: string, options?: EncodingOption | BufferEncodingOption): string | Buffer {
512
- const encoding: string | undefined = getEncodingFromOptions(options);
513
- const path = tempDirPath(prefix);
514
-
515
- mkdirSync(
516
- path,
517
- { recursive: false, mode: 0o777 }
518
- )
519
-
520
- return decode(path, encoding);
521
- }
522
-
523
- /**
524
- * Synchronously removes files and directories (modeled on the standard POSIX `rm`utility). Returns `undefined`.
525
- * @since v14.14.0
526
- */
527
- export function rmSync(path: PathLike, options?: RmOptions): void {
528
- const pathStr = normalizePath(path);
529
- const file = Gio.File.new_for_path(pathStr);
530
- const recursive = options?.recursive || false;
531
- const force = options?.force || false;
532
-
533
- let dirent: Dirent;
534
- try {
535
- dirent = new Dirent(pathStr);
536
- } catch (err: unknown) {
537
- if (force && isNotFoundError(err)) return;
538
- throw createNodeError(err, 'rm', path);
539
- }
540
-
541
- if (dirent.isDirectory()) {
542
- const childFiles = readdirSync(path, { withFileTypes: true });
543
-
544
- if (!recursive && childFiles.length) {
545
- const err = Object.assign(new Error(), { code: 5 }); // Gio.IOErrorEnum.NOT_EMPTY
546
- throw createNodeError(err, 'rm', path);
547
- }
548
-
549
- for (const childFile of childFiles) {
550
- if (typeof childFile !== 'string') {
551
- rmSync(join(pathStr, childFile.name), options);
552
- }
553
- }
554
- }
555
-
556
- try {
557
- file.delete(null);
558
- } catch (err: unknown) {
559
- if (force && isNotFoundError(err)) return;
560
- throw createNodeError(err, 'rm', path);
561
- }
562
- }
package/src/test.mts DELETED
@@ -1,27 +0,0 @@
1
- import '@gjsify/node-globals/register/process';
2
- import '@gjsify/node-globals/register/buffer';
3
- import '@gjsify/node-globals/register/timers';
4
- import '@gjsify/node-globals/register/url';
5
- import { run } from '@gjsify/unit';
6
-
7
- import testSuiteCallback from './callback.spec.js';
8
- import testSuiteFileHandle from './file-handle.spec.js';
9
- import testSuitePromise from './promises.spec.js';
10
- import testSuiteSync from './sync.spec.js';
11
- import testSuiteSymlink from './symlink.spec.js';
12
- import testSuiteStat from './stat.spec.js';
13
- import testSuiteNewApis from './new-apis.spec.js';
14
- import testSuiteExtended from './extended.spec.js';
15
-
16
- import testSuiteErrors from './errors.spec.js';
17
- import testSuiteStreams from './streams.spec.js';
18
- import testSuiteCp from './cp.spec.js';
19
- import testSuiteDir from './dir.spec.js';
20
- import testSuiteGlob from './glob.spec.js';
21
- import testSuiteWatch from './watch.spec.js';
22
- import testSuiteWatchFile from './watchfile.spec.js';
23
- import testSuiteStatFs from './statfs.spec.js';
24
- import testSuiteUtimes from './utimes.spec.js';
25
- import testSuiteFdOps from './fd-ops.spec.js';
26
-
27
- run({testSuiteCallback, testSuiteFileHandle, testSuitePromise, testSuiteSync, testSuiteSymlink, testSuiteStat, testSuiteNewApis, testSuiteExtended, testSuiteErrors, testSuiteStreams, testSuiteCp, testSuiteDir, testSuiteGlob, testSuiteWatch, testSuiteWatchFile, testSuiteStatFs, testSuiteUtimes, testSuiteFdOps});
@@ -1,3 +0,0 @@
1
- import type { ObjectEncodingOptions } from 'node:fs'; // Types from @types/node
2
-
3
- export type EncodingOption = ObjectEncodingOptions | BufferEncoding | undefined | null;
@@ -1,15 +0,0 @@
1
- export interface FileReadOptions<T extends NodeJS.ArrayBufferView = Buffer> {
2
- /**
3
- * @default `Buffer.alloc(0xffff)`
4
- */
5
- buffer?: T;
6
- /**
7
- * @default 0
8
- */
9
- offset?: number | null;
10
- /**
11
- * @default `buffer.byteLength`
12
- */
13
- length?: number | null;
14
- position?: number | null;
15
- }
@@ -1,4 +0,0 @@
1
- export interface FileReadResult<T extends NodeJS.ArrayBufferView> {
2
- bytesRead: number;
3
- buffer: T;
4
- }
@@ -1,6 +0,0 @@
1
- import type { Mode, OpenMode } from 'node:fs';
2
-
3
- export interface FlagAndOpenMode {
4
- mode?: Mode | undefined;
5
- flag?: OpenMode | undefined;
6
- }
@@ -1,6 +0,0 @@
1
- export * from './encoding-option.js';
2
- export * from './file-read-options.js';
3
- export * from './file-read-result.js';
4
- export * from './flag-and-open-mode.js';
5
- export * from './open-flags.js';
6
- export * from './read-options.js';
@@ -1,14 +0,0 @@
1
- export type OpenFlags =
2
- | "a"
3
- | "ax"
4
- | "a+"
5
- | "ax+"
6
- | "as"
7
- | "as+"
8
- | "r"
9
- | "r+"
10
- | "rs+"
11
- | "w"
12
- | "wx"
13
- | "w+"
14
- | "wx+";
@@ -1,9 +0,0 @@
1
- import type { Abortable } from 'node:events';
2
- import type { ObjectEncodingOptions, OpenMode } from 'node:fs'; // Types from @types/node
3
-
4
- export type ReadOptions =
5
- | (ObjectEncodingOptions & Abortable & {
6
- flag?: OpenMode | undefined;
7
- })
8
- | BufferEncoding
9
- | null
package/src/utils.ts DELETED
@@ -1,31 +0,0 @@
1
- // Shared filesystem utilities for GJS — original implementation using Gio
2
-
3
- import { existsSync } from './sync.js';
4
- import { fileURLToPath, URL as NodeURL } from 'node:url';
5
-
6
- import type { PathLike } from 'node:fs';
7
-
8
- // Gio.File.new_for_path only accepts strings; convert URL/Buffer accordingly.
9
- export function normalizePath(path: PathLike): string {
10
- if (path instanceof URL || path instanceof NodeURL) return fileURLToPath(path as URL);
11
- if (typeof path === 'string') return path;
12
- return (path as Buffer).toString();
13
- }
14
-
15
- const CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
16
-
17
- export function randomName(): string {
18
- return [...Array(6)].map(() =>
19
- CHARS[Math.floor(Math.random() * CHARS.length)]
20
- ).join("");
21
- }
22
-
23
- // credits: https://github.com/denoland/deno_std/blob/63be40277264e71af60f9b118a2cb569e02beeab/node/_fs/_fs_mkdtemp.ts#L98
24
- export function tempDirPath(prefix: string): string {
25
- let path: string;
26
- do {
27
- path = prefix + randomName();
28
- } while (existsSync(path));
29
-
30
- return path;
31
- }