@gjsify/fs 0.1.15 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/lib/esm/callback.js +22 -13
  2. package/lib/esm/cp.js +253 -0
  3. package/lib/esm/dir.js +160 -0
  4. package/lib/esm/fd-ops.js +189 -0
  5. package/lib/esm/file-handle.js +263 -84
  6. package/lib/esm/fs-watcher.js +88 -4
  7. package/lib/esm/glob.js +164 -0
  8. package/lib/esm/index.js +128 -2
  9. package/lib/esm/promises.js +90 -27
  10. package/lib/esm/read-stream.js +53 -43
  11. package/lib/esm/stat-watcher.js +121 -0
  12. package/lib/esm/statfs.js +57 -0
  13. package/lib/esm/sync.js +70 -52
  14. package/lib/esm/utils.js +7 -0
  15. package/lib/esm/utimes.js +62 -0
  16. package/lib/esm/write-stream.js +2 -5
  17. package/lib/types/cp.d.ts +18 -0
  18. package/lib/types/cp.spec.d.ts +2 -0
  19. package/lib/types/dir.d.ts +29 -0
  20. package/lib/types/dir.spec.d.ts +2 -0
  21. package/lib/types/fd-ops.d.ts +57 -0
  22. package/lib/types/fd-ops.spec.d.ts +2 -0
  23. package/lib/types/file-handle.d.ts +34 -4
  24. package/lib/types/fs-watcher.d.ts +9 -2
  25. package/lib/types/glob.d.ts +8 -0
  26. package/lib/types/glob.spec.d.ts +2 -0
  27. package/lib/types/index.d.ts +51 -1
  28. package/lib/types/promises.d.ts +31 -4
  29. package/lib/types/read-stream.d.ts +3 -1
  30. package/lib/types/stat-watcher.d.ts +21 -0
  31. package/lib/types/statfs.d.ts +35 -0
  32. package/lib/types/statfs.spec.d.ts +2 -0
  33. package/lib/types/sync.d.ts +4 -7
  34. package/lib/types/utils.d.ts +2 -0
  35. package/lib/types/utimes.d.ts +13 -0
  36. package/lib/types/utimes.spec.d.ts +2 -0
  37. package/lib/types/watch.spec.d.ts +2 -0
  38. package/lib/types/watchfile.spec.d.ts +2 -0
  39. package/lib/types/write-stream.d.ts +1 -2
  40. package/package.json +12 -12
  41. package/src/callback.ts +22 -13
  42. package/src/cp.spec.ts +181 -0
  43. package/src/cp.ts +328 -0
  44. package/src/dir.spec.ts +204 -0
  45. package/src/dir.ts +199 -0
  46. package/src/fd-ops.spec.ts +234 -0
  47. package/src/fd-ops.ts +251 -0
  48. package/src/file-handle.ts +264 -94
  49. package/src/fs-watcher.ts +101 -6
  50. package/src/glob.spec.ts +201 -0
  51. package/src/glob.ts +205 -0
  52. package/src/index.ts +74 -0
  53. package/src/promises.ts +94 -29
  54. package/src/read-stream.ts +49 -43
  55. package/src/stat-watcher.ts +116 -0
  56. package/src/statfs.spec.ts +67 -0
  57. package/src/statfs.ts +92 -0
  58. package/src/streams.spec.ts +58 -0
  59. package/src/sync.ts +75 -57
  60. package/src/test.mts +13 -2
  61. package/src/utils.ts +10 -0
  62. package/src/utimes.spec.ts +113 -0
  63. package/src/utimes.ts +97 -0
  64. package/src/watch.spec.ts +171 -0
  65. package/src/watchfile.spec.ts +185 -0
  66. package/src/write-stream.ts +5 -8
  67. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,201 @@
1
+ // Ported from refs/bun/test/js/node/fs/glob.test.ts
2
+ // Original: MIT, Oven & contributors.
3
+ // Rewritten for @gjsify/unit — behavior preserved, assertion dialect adapted.
4
+
5
+ import { describe, it, expect } from '@gjsify/unit';
6
+ import {
7
+ globSync,
8
+ glob,
9
+ promises,
10
+ mkdirSync,
11
+ writeFileSync,
12
+ mkdtempSync,
13
+ rmSync,
14
+ } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ import { tmpdir } from 'node:os';
17
+
18
+ function makeTmp(): string {
19
+ return mkdtempSync(join(tmpdir(), 'gjsify-glob-'));
20
+ }
21
+
22
+ export default async () => {
23
+ await describe('fs.globSync', async () => {
24
+ await it('matches *.ts files in flat directory', async () => {
25
+ const tmp = makeTmp();
26
+ writeFileSync(join(tmp, 'a.ts'), '');
27
+ writeFileSync(join(tmp, 'b.ts'), '');
28
+ writeFileSync(join(tmp, 'c.txt'), '');
29
+
30
+ const results = globSync('*.ts', { cwd: tmp });
31
+ expect(results.sort()).toStrictEqual(['a.ts', 'b.ts']);
32
+ rmSync(tmp, { recursive: true, force: true });
33
+ });
34
+
35
+ await it('matches **/*.ts recursively', async () => {
36
+ const tmp = makeTmp();
37
+ mkdirSync(join(tmp, 'sub'));
38
+ writeFileSync(join(tmp, 'root.ts'), '');
39
+ writeFileSync(join(tmp, 'sub', 'nested.ts'), '');
40
+ writeFileSync(join(tmp, 'sub', 'other.txt'), '');
41
+
42
+ const results = globSync('**/*.ts', { cwd: tmp });
43
+ expect(results.sort()).toStrictEqual(['root.ts', 'sub/nested.ts']);
44
+ rmSync(tmp, { recursive: true, force: true });
45
+ });
46
+
47
+ await it('matches files in a subdirectory pattern', async () => {
48
+ const tmp = makeTmp();
49
+ mkdirSync(join(tmp, 'src'));
50
+ writeFileSync(join(tmp, 'src', 'index.ts'), '');
51
+ writeFileSync(join(tmp, 'src', 'util.ts'), '');
52
+ writeFileSync(join(tmp, 'index.ts'), '');
53
+
54
+ const results = globSync('src/*.ts', { cwd: tmp });
55
+ expect(results.sort()).toStrictEqual(['src/index.ts', 'src/util.ts']);
56
+ rmSync(tmp, { recursive: true, force: true });
57
+ });
58
+
59
+ await it('supports {a,b} alternation', async () => {
60
+ const tmp = makeTmp();
61
+ writeFileSync(join(tmp, 'a.ts'), '');
62
+ writeFileSync(join(tmp, 'b.ts'), '');
63
+ writeFileSync(join(tmp, 'c.ts'), '');
64
+
65
+ const results = globSync('*.{ts,js}', { cwd: tmp });
66
+ expect(results.sort()).toStrictEqual(['a.ts', 'b.ts', 'c.ts']);
67
+ rmSync(tmp, { recursive: true, force: true });
68
+ });
69
+
70
+ await it('** matches all files and directories', async () => {
71
+ const tmp = makeTmp();
72
+ mkdirSync(join(tmp, 'sub'));
73
+ writeFileSync(join(tmp, 'a.ts'), '');
74
+ writeFileSync(join(tmp, 'sub', 'b.ts'), '');
75
+
76
+ const results = globSync('**', { cwd: tmp });
77
+ // Should include '.', 'a.ts', 'sub', 'sub/b.ts'
78
+ expect(results.includes('a.ts')).toBe(true);
79
+ expect(results.includes('sub/b.ts')).toBe(true);
80
+ rmSync(tmp, { recursive: true, force: true });
81
+ });
82
+
83
+ await it('a/** matches the directory itself and its contents', async () => {
84
+ const tmp = makeTmp();
85
+ mkdirSync(join(tmp, 'sub'));
86
+ writeFileSync(join(tmp, 'sub', 'x.ts'), '');
87
+ writeFileSync(join(tmp, 'root.ts'), '');
88
+
89
+ const results = globSync('sub/**', { cwd: tmp });
90
+ expect(results.includes('sub')).toBe(true);
91
+ expect(results.includes('sub/x.ts')).toBe(true);
92
+ expect(results.includes('root.ts')).toBe(false);
93
+ rmSync(tmp, { recursive: true, force: true });
94
+ });
95
+
96
+ await it('accepts array of patterns', async () => {
97
+ const tmp = makeTmp();
98
+ writeFileSync(join(tmp, 'a.ts'), '');
99
+ writeFileSync(join(tmp, 'b.js'), '');
100
+ writeFileSync(join(tmp, 'c.txt'), '');
101
+
102
+ const results = globSync(['*.ts', '*.js'], { cwd: tmp });
103
+ expect(results.sort()).toStrictEqual(['a.ts', 'b.js']);
104
+ rmSync(tmp, { recursive: true, force: true });
105
+ });
106
+
107
+ await it('exclude function filters out matching paths', async () => {
108
+ const tmp = makeTmp();
109
+ writeFileSync(join(tmp, 'a.ts'), '');
110
+ writeFileSync(join(tmp, 'b.ts'), '');
111
+
112
+ // Use **/*.ts so Node.js native also invokes the exclude function
113
+ // (flat patterns like *.ts skip directory traversal and exclude is not called)
114
+ const results = globSync('**/*.ts', {
115
+ cwd: tmp,
116
+ exclude: (p) => p === 'a.ts',
117
+ });
118
+ expect(results).toStrictEqual(['b.ts']);
119
+ rmSync(tmp, { recursive: true, force: true });
120
+ });
121
+
122
+ await it('returns empty array when no files match', async () => {
123
+ const tmp = makeTmp();
124
+ writeFileSync(join(tmp, 'a.txt'), '');
125
+
126
+ const results = globSync('*.ts', { cwd: tmp });
127
+ expect(results).toStrictEqual([]);
128
+ rmSync(tmp, { recursive: true, force: true });
129
+ });
130
+
131
+ await it('returns empty array for non-existent cwd', async () => {
132
+ const results = globSync('*.ts', { cwd: '/nonexistent-dir-gjsify-test' });
133
+ expect(results).toStrictEqual([]);
134
+ });
135
+ });
136
+
137
+ await describe('fs.glob (callback)', async () => {
138
+ await it('calls back with matched files', async () => {
139
+ const tmp = makeTmp();
140
+ writeFileSync(join(tmp, 'hello.ts'), '');
141
+ writeFileSync(join(tmp, 'world.ts'), '');
142
+
143
+ const results = await new Promise<string[]>((resolve, reject) => {
144
+ glob('*.ts', { cwd: tmp }, (err, matches) => {
145
+ if (err) return reject(err);
146
+ resolve(matches);
147
+ });
148
+ });
149
+
150
+ expect(results.sort()).toStrictEqual(['hello.ts', 'world.ts']);
151
+ rmSync(tmp, { recursive: true, force: true });
152
+ });
153
+
154
+ await it('accepts callback as second argument (no options)', async () => {
155
+ const tmp = makeTmp();
156
+ writeFileSync(join(tmp, 'file.ts'), '');
157
+
158
+ const results = await new Promise<string[]>((resolve, reject) => {
159
+ (glob as any)('*.ts', (err: any, matches: string[]) => {
160
+ if (err) return reject(err);
161
+ resolve(matches);
162
+ });
163
+ });
164
+
165
+ // No cwd given — just verify it completes without error
166
+ expect(Array.isArray(results)).toBe(true);
167
+ rmSync(tmp, { recursive: true, force: true });
168
+ });
169
+ });
170
+
171
+ await describe('fs.promises.glob', async () => {
172
+ await it('async iterates matched files', async () => {
173
+ const tmp = makeTmp();
174
+ writeFileSync(join(tmp, 'alpha.ts'), '');
175
+ writeFileSync(join(tmp, 'beta.ts'), '');
176
+
177
+ const results: string[] = [];
178
+ for await (const match of promises.glob('*.ts', { cwd: tmp })) {
179
+ results.push(match);
180
+ }
181
+
182
+ expect(results.sort()).toStrictEqual(['alpha.ts', 'beta.ts']);
183
+ rmSync(tmp, { recursive: true, force: true });
184
+ });
185
+
186
+ await it('async iterates recursively with **/*.ts', async () => {
187
+ const tmp = makeTmp();
188
+ mkdirSync(join(tmp, 'lib'));
189
+ writeFileSync(join(tmp, 'index.ts'), '');
190
+ writeFileSync(join(tmp, 'lib', 'helper.ts'), '');
191
+
192
+ const results: string[] = [];
193
+ for await (const match of promises.glob('**/*.ts', { cwd: tmp })) {
194
+ results.push(match);
195
+ }
196
+
197
+ expect(results.sort()).toStrictEqual(['index.ts', 'lib/helper.ts']);
198
+ rmSync(tmp, { recursive: true, force: true });
199
+ });
200
+ });
201
+ };
package/src/glob.ts ADDED
@@ -0,0 +1,205 @@
1
+ // Reference: Node.js lib/internal/fs/glob.js
2
+ // Reimplemented for GJS using readdirSync (recursive) + pattern matching
3
+
4
+ import { readdirSync } from './sync.js';
5
+ import { normalizePath } from './utils.js';
6
+ import type { PathLike } from 'node:fs';
7
+
8
+ export interface GlobOptions {
9
+ cwd?: string | URL;
10
+ exclude?: string | string[] | ((path: string) => boolean);
11
+ withFileTypes?: boolean;
12
+ }
13
+
14
+ // ─── Pattern → RegExp conversion ─────────────────────────────────────────────
15
+
16
+ /** Convert a single glob segment (no `/`) to a regex source string */
17
+ function segmentToRegexSrc(seg: string): string {
18
+ // Handle extglob: !(pattern), *(pattern), +(pattern), ?(pattern), @(pattern)
19
+ const extglob = /^([!*+?@])\((.+)\)$/.exec(seg);
20
+ if (extglob) {
21
+ const [, type, inner] = extglob;
22
+ const parts = inner.split('|').map(p => segmentToRegexSrc(p));
23
+ const group = '(?:' + parts.join('|') + ')';
24
+ switch (type) {
25
+ case '!': return '(?!(?:' + parts.join('|') + '))[^/]*';
26
+ case '*': return group + '*';
27
+ case '+': return group + '+';
28
+ case '?': return group + '?';
29
+ case '@': return group;
30
+ }
31
+ }
32
+
33
+ let result = '';
34
+ let i = 0;
35
+ while (i < seg.length) {
36
+ const c = seg[i];
37
+ if (c === '*') { result += '[^/]*'; i++; continue; }
38
+ if (c === '?') { result += '[^/]'; i++; continue; }
39
+ if (c === '[') {
40
+ // Character class — pass through to regex
41
+ const end = seg.indexOf(']', i + 1);
42
+ if (end === -1) { result += '\\['; i++; continue; }
43
+ result += seg.slice(i, end + 1);
44
+ i = end + 1;
45
+ continue;
46
+ }
47
+ if (c === '{') {
48
+ // Alternation
49
+ const end = seg.indexOf('}', i + 1);
50
+ if (end === -1) { result += '\\{'; i++; continue; }
51
+ const alts = seg.slice(i + 1, end).split(',').map(a => segmentToRegexSrc(a.trim()));
52
+ result += '(?:' + alts.join('|') + ')';
53
+ i = end + 1;
54
+ continue;
55
+ }
56
+ // Escape regex special chars
57
+ if ('.+^$|()[]{}'.includes(c)) {
58
+ result += '\\' + c;
59
+ } else {
60
+ result += c;
61
+ }
62
+ i++;
63
+ }
64
+ return result;
65
+ }
66
+
67
+ /**
68
+ * Convert a glob pattern to a RegExp that matches relative POSIX paths.
69
+ */
70
+ function globToRegex(pattern: string): RegExp {
71
+ // Normalize: collapse multiple slashes, remove leading './'
72
+ pattern = pattern.replace(/\/+/g, '/').replace(/^\.\//, '');
73
+
74
+ const segments = pattern.split('/');
75
+ const parts: string[] = [];
76
+
77
+ for (let si = 0; si < segments.length; si++) {
78
+ const seg = segments[si];
79
+ const isLast = si === segments.length - 1;
80
+
81
+ if (seg === '**') {
82
+ if (isLast) {
83
+ if (parts.length > 0 && parts[parts.length - 1] === '/') {
84
+ // Remove the trailing '/' so "a/" becomes optional: "a(?:/.*)?
85
+ parts.pop();
86
+ parts.push('(?:/.+)?');
87
+ } else {
88
+ // '**' at root level: match '.' or anything
89
+ parts.push('(?:.+)?');
90
+ }
91
+ } else {
92
+ // Not last: match zero or more path segments with trailing slash
93
+ parts.push('(?:[^/]+/)*');
94
+ }
95
+ } else {
96
+ parts.push(segmentToRegexSrc(seg));
97
+ if (!isLast) parts.push('/');
98
+ }
99
+ }
100
+
101
+ return new RegExp('^(?:' + parts.join('') + ')$');
102
+ }
103
+
104
+ // ─── Exclude logic ────────────────────────────────────────────────────────────
105
+
106
+ function buildExcludePredicate(exclude: GlobOptions['exclude']): ((path: string) => boolean) | null {
107
+ if (!exclude) return null;
108
+ if (typeof exclude === 'function') return exclude;
109
+ const patterns = Array.isArray(exclude) ? exclude : [exclude];
110
+ const regexes = patterns.map(p => globToRegex(p));
111
+ return (path: string) => regexes.some(rx => rx.test(path));
112
+ }
113
+
114
+ // ─── Walk + match ─────────────────────────────────────────────────────────────
115
+
116
+ function matchAll(pattern: string, cwd: string, exclude: GlobOptions['exclude']): string[] {
117
+ const regex = globToRegex(pattern);
118
+ const isExcluded = buildExcludePredicate(exclude);
119
+
120
+ // Get all entries recursively (files + directories)
121
+ let allEntries: string[];
122
+ try {
123
+ allEntries = readdirSync(cwd, { recursive: true }) as string[];
124
+ } catch {
125
+ return [];
126
+ }
127
+
128
+ // Include '.' itself for patterns like '**' that match the root
129
+ const candidates = ['.', ...allEntries];
130
+
131
+ const results: string[] = [];
132
+ for (const entry of candidates) {
133
+ // Normalize separators for matching
134
+ const normalized = entry.replace(/\\/g, '/');
135
+ if (!regex.test(normalized)) continue;
136
+ if (isExcluded && isExcluded(normalized)) continue;
137
+ results.push(entry);
138
+ }
139
+
140
+ return results;
141
+ }
142
+
143
+ // ─── Public API ───────────────────────────────────────────────────────────────
144
+
145
+ export function globSync(
146
+ pattern: string | string[],
147
+ options?: GlobOptions,
148
+ ): string[] {
149
+ const patterns = Array.isArray(pattern) ? pattern : [pattern];
150
+ const cwd = options?.cwd
151
+ ? normalizePath(options.cwd as PathLike)
152
+ : (globalThis as any).process?.cwd?.() ?? '/';
153
+ const exclude = options?.exclude;
154
+
155
+ const seen = new Set<string>();
156
+ const results: string[] = [];
157
+
158
+ for (const p of patterns) {
159
+ for (const match of matchAll(p, cwd, exclude)) {
160
+ if (!seen.has(match)) {
161
+ seen.add(match);
162
+ results.push(match);
163
+ }
164
+ }
165
+ }
166
+
167
+ return results;
168
+ }
169
+
170
+ export function glob(
171
+ pattern: string | string[],
172
+ options: GlobOptions | ((err: NodeJS.ErrnoException | null, matches: string[]) => void),
173
+ callback?: (err: NodeJS.ErrnoException | null, matches: string[]) => void,
174
+ ): void {
175
+ let opts: GlobOptions;
176
+ let cb: (err: NodeJS.ErrnoException | null, matches: string[]) => void;
177
+
178
+ if (typeof options === 'function') {
179
+ cb = options;
180
+ opts = {};
181
+ } else {
182
+ cb = callback!;
183
+ opts = options || {};
184
+ }
185
+
186
+ Promise.resolve().then(() => {
187
+ try {
188
+ const matches = globSync(pattern, opts);
189
+ cb(null, matches);
190
+ } catch (err: unknown) {
191
+ cb(err as NodeJS.ErrnoException, []);
192
+ }
193
+ });
194
+ }
195
+
196
+ // promises.glob returns an async iterator
197
+ export async function* globAsync(
198
+ pattern: string | string[],
199
+ options?: GlobOptions,
200
+ ): AsyncIterableIterator<string> {
201
+ const matches = globSync(pattern, options);
202
+ for (const m of matches) {
203
+ yield m;
204
+ }
205
+ }
package/src/index.ts CHANGED
@@ -63,8 +63,30 @@ import {
63
63
  WriteStream
64
64
  } from './write-stream.js';
65
65
  import * as promises from './promises.js';
66
+ import { cpSync, cp } from './cp.js';
67
+ import { Dir, opendir, opendirSync } from './dir.js';
68
+ import { glob, globSync } from './glob.js';
69
+ import { StatWatcher, watchFile, unwatchFile } from './stat-watcher.js';
70
+ import { statfsSync, statfs } from './statfs.js';
66
71
  import { Stats, BigIntStats } from './stats.js';
67
72
  import { Dirent } from './dirent.js';
73
+ import {
74
+ utimesSync, utimes, lutimesSync, lutimes,
75
+ lchownSync, lchown, lchmodSync, lchmod,
76
+ } from './utimes.js';
77
+ import {
78
+ fstatSync, fstat,
79
+ ftruncateSync, ftruncate,
80
+ fdatasyncSync, fdatasync,
81
+ fsyncSync, fsync,
82
+ fchmodSync, fchmod,
83
+ fchownSync, fchown,
84
+ futimesSync, futimes,
85
+ closeSync, readSync, writeSync,
86
+ readvSync, readv,
87
+ writevSync, writev,
88
+ exists, openAsBlob,
89
+ } from './fd-ops.js';
68
90
 
69
91
  // --- fs.constants ---
70
92
  export const constants = {
@@ -115,9 +137,11 @@ export const constants = {
115
137
 
116
138
  export {
117
139
  FSWatcher,
140
+ StatWatcher,
118
141
  Stats,
119
142
  BigIntStats,
120
143
  Dirent,
144
+ Dir,
121
145
  // Sync API
122
146
  existsSync,
123
147
  readdirSync,
@@ -142,7 +166,30 @@ export {
142
166
  truncateSync,
143
167
  chmodSync,
144
168
  chownSync,
169
+ cpSync,
170
+ opendirSync,
171
+ globSync,
172
+ glob,
145
173
  watch,
174
+ watchFile,
175
+ unwatchFile,
176
+ statfsSync,
177
+ statfs,
178
+ // utimes / lutimes / lchown / lchmod
179
+ utimesSync, utimes, lutimesSync, lutimes,
180
+ lchownSync, lchown, lchmodSync, lchmod,
181
+ // fd-based ops
182
+ fstatSync, fstat,
183
+ ftruncateSync, ftruncate,
184
+ fdatasyncSync, fdatasync,
185
+ fsyncSync, fsync,
186
+ fchmodSync, fchmod,
187
+ fchownSync, fchown,
188
+ futimesSync, futimes,
189
+ closeSync, readSync, writeSync,
190
+ readvSync, readv,
191
+ writevSync, writev,
192
+ exists, openAsBlob,
146
193
  // Streams
147
194
  createReadStream,
148
195
  ReadStream,
@@ -163,6 +210,7 @@ export {
163
210
  stat,
164
211
  rename,
165
212
  copyFile,
213
+ cp,
166
214
  access,
167
215
  appendFile,
168
216
  readlink,
@@ -175,13 +223,16 @@ export {
175
223
  writeFile,
176
224
  unlink,
177
225
  link,
226
+ opendir,
178
227
  };
179
228
 
180
229
  export default {
181
230
  FSWatcher,
231
+ StatWatcher,
182
232
  Stats,
183
233
  BigIntStats,
184
234
  Dirent,
235
+ Dir,
185
236
  constants,
186
237
  existsSync,
187
238
  readdirSync,
@@ -206,7 +257,28 @@ export default {
206
257
  truncateSync,
207
258
  chmodSync,
208
259
  chownSync,
260
+ cpSync,
261
+ opendirSync,
262
+ globSync,
263
+ glob,
209
264
  watch,
265
+ watchFile,
266
+ unwatchFile,
267
+ statfsSync,
268
+ statfs,
269
+ utimesSync, utimes, lutimesSync, lutimes,
270
+ lchownSync, lchown, lchmodSync, lchmod,
271
+ fstatSync, fstat,
272
+ ftruncateSync, ftruncate,
273
+ fdatasyncSync, fdatasync,
274
+ fsyncSync, fsync,
275
+ fchmodSync, fchmod,
276
+ fchownSync, fchown,
277
+ futimesSync, futimes,
278
+ closeSync, readSync, writeSync,
279
+ readvSync, readv,
280
+ writevSync, writev,
281
+ exists, openAsBlob,
210
282
  createReadStream,
211
283
  ReadStream,
212
284
  createWriteStream,
@@ -224,6 +296,7 @@ export default {
224
296
  stat,
225
297
  rename,
226
298
  copyFile,
299
+ cp,
227
300
  access,
228
301
  appendFile,
229
302
  readlink,
@@ -236,4 +309,5 @@ export default {
236
309
  writeFile,
237
310
  unlink,
238
311
  link,
312
+ opendir,
239
313
  };