fake-node 0.3.0 → 0.4.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.
package/src/fs.ts CHANGED
@@ -1,517 +1,230 @@
1
1
 
2
- import * as process from './process';
3
- import {resolve} from 'path';
4
- import {Buffer} from 'buffer';
5
-
6
-
7
- const F_OK = 0;
8
- const X_OK = 1;
9
- const W_OK = 2;
10
- const R_OK = 4;
11
-
12
- const COPYFILE_EXCL = 1;
13
- const COPYFILE_FICLONE = 2;
14
- const COPYFILE_FICLONE_FORCE = 4;
15
-
16
- const O_RDONLY = 1;
17
- const O_WRONLY = 2;
18
- const O_RDWR = O_RDONLY | O_WRONLY;
19
- const O_CREAT = 4;
20
- const O_EXCL = 8;
21
- const O_NOCTTY = 16;
22
- const O_TRUNC = 32;
23
- const O_APPEND = 64;
24
- const O_DIRECTORY = 128;
25
- const O_NOATIME = 256;
26
- const O_NOFOLLOW = 512;
27
- const O_SYNC = 1024;
28
- const O_DSYNC = 2048;
29
- const O_SYMLINK = 4096;
30
- const O_DIRECT = 8192;
31
- const O_NONBLOCK = 16384;
32
- const UV_FS_O_FILEMAP = 32768;
33
-
34
- const S_IMFT = 0xF000;
35
- const S_IFREG = 0x8000;
36
- const S_IFDIR = 0x4000;
37
- const S_IFCHR = 0x2000;
38
- const S_IFBLK = 0x6000;
39
- const S_IFIFO = 0x1000;
40
- const S_IFLNK = 0xA000;
41
- const S_IFSOCK = 0xC000;
42
-
43
- const S_IRWXU = 0o700;
44
- const S_IRUSR = 0o400;
45
- const S_IWUSR = 0o200;
46
- const S_IXUSR = 0o100;
47
- const S_IRWXG = 0o070;
48
- const S_IRGRP = 0o040;
49
- const S_IWGRP = 0o020;
50
- const S_IXGRP = 0o010;
51
- const S_IRWXO = 0o007;
52
- const S_IROTH = 0o004;
53
- const S_IWOTH = 0o002;
54
- const S_IXOTH = 0o001;
55
-
56
-
57
- export const constants = {F_OK, X_OK, W_OK, R_OK, COPYFILE_EXCL, COPYFILE_FICLONE, COPYFILE_FICLONE_FORCE, O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, O_DIRECTORY, O_NOATIME, O_NOFOLLOW, O_SYNC, O_DSYNC, O_SYMLINK, O_DIRECT, O_NONBLOCK, UV_FS_O_FILEMAP, S_IMFT, S_IFREG, S_IFDIR, S_IFCHR, S_IFBLK, S_IFIFO, S_IFLNK, S_IFSOCK, S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH};
58
-
59
-
60
- const encoder = new TextEncoder();
61
-
62
- let fileDescriptors: string[] = [];
63
-
64
-
65
- type PathArg = string | URL | Buffer | number;
66
-
67
- function parsePathArg(arg: PathArg): string {
68
- if (typeof arg === 'string') {
69
- return resolve(arg);
70
- } else if (typeof arg === 'number') {
71
- if (fileDescriptors[arg] === null) {
72
- throw new TypeError(`file descriptor ${arg} is closed`);
73
- }
74
- return fileDescriptors[arg];
75
- } else if (arg instanceof Buffer) {
76
- return resolve(arg.toString('utf8'));
77
- } else if (arg instanceof URL) {
78
- if (arg.protocol === 'file:') {
79
- return resolve(arg.pathname);
80
- } else {
81
- throw new TypeError(`invalid file URL: ${arg}`);
82
- }
83
- } else {
84
- throw new TypeError(`invalid path: ${arg}`);
85
- }
86
- }
2
+ /// <reference path="./in_fake_node.d.ts" />
3
+ import {type TypedArray} from './util';
4
+ import {dirname, basename, resolve} from './path';
5
+ import {Buffer, type BufferEncoding} from './buffer';
6
+ import {constants, parsePathArg, Directory, FileSystem} from './_fs';
7
+ import type {PathArg, ModeArg, DataArg, TimeArg, Flag, Stats, BigIntStats, StatFs, BigIntStatFs} from './_fs';
87
8
 
88
- const flags = {
89
- 'a': O_CREAT | O_APPEND,
90
- 'ax': O_CREAT | O_EXCL | O_APPEND,
91
- 'a+': O_RDONLY | O_CREAT | O_APPEND,
92
- 'ax+': O_RDONLY | O_CREAT | O_EXCL | O_APPEND,
93
- 'as': O_CREAT | O_APPEND | O_SYNC,
94
- 'as+': O_RDONLY | O_CREAT | O_APPEND | O_SYNC,
95
- 'r': O_RDONLY,
96
- 'rs': O_RDONLY | O_SYNC,
97
- 'r+': O_RDONLY | O_WRONLY,
98
- 'rs+': O_RDONLY | O_WRONLY | O_SYNC,
99
- 'w': O_WRONLY | O_CREAT | O_TRUNC,
100
- 'wx': O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
101
- 'w+': O_RDONLY | O_WRONLY | O_CREAT | O_TRUNC,
102
- 'wx+': O_RDONLY | O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
103
- }
104
-
105
- export type Flag = number | keyof typeof flags;
106
-
107
- function parseFlag(flag: Flag): number {
108
- if (typeof flag === 'string') {
109
- return flags[flag];
110
- } else {
111
- return flag;
112
- }
113
- }
114
-
115
- export type TimeArg = number | string | bigint | Date;
116
-
117
- function parseTimeArg(time: TimeArg): bigint {
118
- if (typeof time === 'bigint') {
119
- return time;
120
- } else if (typeof time === 'number') {
121
- return BigInt(time * 1000000000);
122
- } else if (typeof time === 'string') {
123
- let timestamp = Date.parse(time);
124
- if (Number.isNaN(timestamp)) {
125
- timestamp = parseInt(time);
126
- if (Number.isNaN(timestamp)) {
127
- throw new TypeError(`invalid time argument ${time}`);
128
- } else {
129
- return BigInt(timestamp * 1000000);
130
- }
131
- } else {
132
- return BigInt(timestamp * 1000000);
133
- }
134
- } else if (time instanceof Date) {
135
- return BigInt(time.valueOf() * 1000000);
136
- } else {
137
- throw new TypeError(`invalid time value: ${time}`);
138
- }
139
- }
9
+ export {constants} from './_fs';
140
10
 
141
- type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
11
+ export {Stats, BigIntStats, StatFs, BigIntStatFs} from './_fs';
142
12
 
143
- type BufferEncoding = "ascii" | "utf8"
144
- | "utf-8"
145
- | "utf16le"
146
- | "ucs2"
147
- | "ucs-2"
148
- | "base64"
149
- | "latin1"
150
- | "binary"
151
- | "hex"
152
-
153
-
154
- type DataArg = string | TypedArray | DataView | Iterable<any>;
155
-
156
- function parseDataArg(data: DataArg, encoding: BufferEncoding = 'utf8'): Uint8Array {
157
- if (typeof data === 'string') {
158
- if (encoding === 'utf8') {
159
- return encoder.encode(data);
160
- } else {
161
- // @ts-ignore
162
- return new Uint8Array(Buffer.from(data, encoding));
163
- }
164
- } else if (data instanceof DataView || data instanceof Int8Array || data instanceof Uint8Array || data instanceof Uint8ClampedArray || data instanceof Int16Array || data instanceof Uint16Array || data instanceof Int32Array || data instanceof Uint32Array || data instanceof Float32Array || data instanceof Float64Array || data instanceof BigInt64Array || data instanceof BigUint64Array) {
165
- return new Uint8Array(data.buffer);
166
- } else if (data !== null && typeof data[Symbol.iterator] === 'function') {
167
- return new Uint8Array(data);
168
- } else {
169
- throw new TypeError(`invalid binary data: ${data}`);
170
- }
13
+ export function accessSync(path: PathArg, mode: number = constants.F_OK) {
14
+ __fakeNode__.fs.get(path).access(mode);
171
15
  }
172
16
 
173
- export type ModeArg = string | number;
174
-
175
- const STRING_MODE_ARG_REGEX = /^([r-][w-][x-]){3}$/;
176
-
177
- function parseModeArg(mode: ModeArg): number {
178
- if (typeof mode === 'number') {
179
- return mode;
180
- } else {
181
- if (!mode.match(STRING_MODE_ARG_REGEX)) {
182
- throw new TypeError(`invalid chmod mode: ${mode}`)
183
- }
184
- // @ts-ignore
185
- return parseInt('0b' + mode.replaceAll('-', '0').replace(/[rwx]/g, '1'));
186
- }
17
+ export function appendFileSync(path: PathArg, data: DataArg, {encoding = 'utf8', mode = 0o666, flag = 'a'}: {encoding?: BufferEncoding, mode: number, flag: string}) {
18
+ __fakeNode__.fs.getRegular(path).append(data, encoding);
187
19
  }
188
20
 
21
+ export function chmodSync(path: PathArg, mode: ModeArg): void {
22
+ __fakeNode__.fs.get(path).chmod(mode);
23
+ }
189
24
 
190
- abstract class BaseStats {
191
-
192
- abstract mode: number | bigint;
193
-
194
- isBlockDevice() {
195
- return (Number(this.mode) & S_IFBLK) === S_IFBLK;
196
- }
197
-
198
- isCharacterDevice() {
199
- return (Number(this.mode) & S_IFCHR) === S_IFCHR;
200
- }
201
-
202
- isDirectory() {
203
- return (Number(this.mode) & S_IFDIR) === S_IFDIR;
204
- }
205
-
206
- isFIFO() {
207
- return (Number(this.mode) & S_IFIFO) === S_IFIFO;
208
- }
25
+ export function chownSync(path: PathArg, uid: number, gid: number): void {
26
+ __fakeNode__.fs.get(path).chown(uid, gid);
27
+ }
209
28
 
210
- isFile() {
211
- return (Number(this.mode) & S_IFREG) === S_IFREG;
212
- }
29
+ export function closeSync(fd: number): void {
30
+ __fakeNode__.fs.fileDescriptors[fd] = null;
31
+ }
213
32
 
214
- isSocket() {
215
- return (Number(this.mode) & S_IFSOCK) === S_IFSOCK;
33
+ export function copyFileSync(src: PathArg, dest: PathArg, mode: number = 0): void {
34
+ if ((mode & constants.COPYFILE_EXCL) === constants.COPYFILE_EXCL && __fakeNode__.fs.exists(dest)) {
35
+ throw new TypeError(`${dest} exists`);
216
36
  }
217
-
218
- isSymbolicLink() {
219
- return (Number(this.mode) & S_IFLNK) === S_IFLNK;
37
+ if ((mode & constants.COPYFILE_FICLONE_FORCE) === constants.COPYFILE_FICLONE_FORCE) {
38
+ throw new TypeError('fake-node does not support copy-on-write');
220
39
  }
221
-
40
+ __fakeNode__.fs.getRegular(dest).write(__fakeNode__.fs.getRegular(src).read());
222
41
  }
223
42
 
224
- export class Stats extends BaseStats {
225
-
226
- dev: number;
227
- ino: number;
228
- mode: number;
229
- nlink: number;
230
- uid: number;
231
- gid: number;
232
- rdev: number;
233
- size: number;
234
- blksize: number;
235
- blocks: number;
236
- atimeMs: number;
237
- mtimeMs: number;
238
- ctimeMs: number;
239
- birthtimeMs: number;
240
- atime: Date;
241
- mtime: Date;
242
- ctime: Date;
243
- birthtime: Date;
244
-
43
+ export function existsSync(path: PathArg): boolean {
44
+ return __fakeNode__.fs.exists(path);
245
45
  }
246
46
 
247
- export class BigIntStats extends BaseStats {
248
-
249
- dev: bigint;
250
- ino: bigint;
251
- mode: bigint;
252
- nlink: bigint;
253
- uid: bigint;
254
- gid: bigint;
255
- rdev: bigint;
256
- size: bigint;
257
- blksize: bigint;
258
- blocks: bigint;
259
- atimeMs: bigint;
260
- mtimeMs: bigint;
261
- ctimeMs: bigint;
262
- birthtimeMs: bigint;
263
- atimeNs: bigint;
264
- mtimeNs: bigint;
265
- ctimeNs: bigint;
266
- birthtimeNs: bigint;
267
- atime: Date;
268
- mtime: Date;
269
- ctime: Date;
270
- birthtime: Date;
271
-
47
+ export function fchmodSync(fd: number, mode: ModeArg): void {
48
+ __fakeNode__.fs.getfd(fd).chmod(mode);
272
49
  }
273
50
 
274
-
275
- export class StatFs {
276
-
277
- bavail: number;
278
- bfree: number;
279
- blocks: number;
280
- bsize: number;
281
- ffree: number;
282
- files: number;
283
- type: number;
284
-
51
+ export function fchownsync(fd: number, uid: number, gid: number): void {
52
+ __fakeNode__.fs.getfd(fd).chown(uid, gid);
285
53
  }
286
54
 
55
+ export function fdatasyncSync(fd: number): void {
56
+ return;
57
+ }
287
58
 
288
- export class BigIntStatFs {
289
-
290
- bavail: bigint;
291
- bfree: bigint;
292
- blocks: bigint;
293
- bsize: bigint;
294
- ffree: bigint;
295
- files: bigint;
296
- type: bigint;
59
+ export function fstatSync(fd: number): Stats {
60
+ return __fakeNode__.fs.getfd(fd).stat();
61
+ }
297
62
 
63
+ export function fsyncSync(fd: number): void {
64
+ return;
298
65
  }
299
66
 
67
+ export function ftruncateSync(fd: number, len: number): void {
68
+ let file = __fakeNode__.fs.getfdRegular(fd);
69
+ file.data = file.data.slice(0, len);
70
+ }
300
71
 
301
- export interface FileParams {
302
- mode?: number;
303
- uid?: number;
304
- gid?: number;
72
+ export function futimesSync(fd: number, atime: TimeArg, ctime: TimeArg): void {
73
+ __fakeNode__.fs.getfd(fd).utimes(atime, ctime);
305
74
  }
306
75
 
307
- export class FileObject {
76
+ export function globSync(pattern: string | string[]): string[] {
77
+ throw new TypeError('globs are not supported in fake-node');
78
+ }
308
79
 
309
- mode: number;
310
- uid: number;
311
- gid: number;
312
- links: Directory[];
313
- birthtime: bigint;
314
- atime: bigint;
315
- mtime: bigint;
316
- ctime: bigint;
317
- rdev: number = -1;
80
+ export function lchmodSync(path: PathArg, mode: number): void {
81
+ __fakeNode__.fs.lget(path).chmod(mode);
82
+ }
318
83
 
319
- constructor({mode, uid, gid}: FileParams) {
320
- this.mode = mode ?? (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
321
- this.uid = uid ?? __fakeNode_process__.uid;
322
- this.gid = gid ?? __fakeNode_process__.gid;
323
- this.birthtime = process.hrtime.bigint();
324
- this.atime = this.birthtime;
325
- this.mtime = this.birthtime;
326
- this.ctime = this.birthtime;
327
- }
84
+ export function lchownSync(path: PathArg, uid: number, gid: number): void {
85
+ __fakeNode__.fs.lget(path).chown(uid, gid);
86
+ }
328
87
 
329
- setAtime() {
330
- this.atime = process.hrtime.bigint();
331
- }
88
+ export function lutimesSync(path: PathArg, atime: TimeArg, mtime: TimeArg): void {
89
+ __fakeNode__.fs.lget(path).utimes(atime, mtime);
90
+ }
332
91
 
333
- setMtime() {
334
- this.mtime = process.hrtime.bigint();
335
- }
92
+ export function linkSync(existingPath: PathArg, newPath: PathArg): void {
93
+ __fakeNode__.fs.getDir(dirname(parsePathArg(existingPath))).link(basename(parsePathArg(newPath)), __fakeNode__.fs.get(existingPath));
94
+ }
336
95
 
337
- setCtime() {
338
- this.ctime = process.hrtime.bigint();
96
+ export function lstatSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: false, throwIfNoEntry: false}): Stats;
97
+ export function lstatSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: false, throwIfNoEntry: true}): Stats | undefined;
98
+ export function lstatSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: true, throwIfNoEntry: false}): BigIntStats;
99
+ export function lstatSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: true, throwIfNoEntry: true}): BigIntStats | undefined;
100
+ export function lstatSync(path: PathArg, {bigint = false, throwIfNoEntry = false}: {bigint?: boolean, throwIfNoEntry?: boolean} = {}): Stats | BigIntStats | undefined {
101
+ if (!throwIfNoEntry && !__fakeNode__.fs.exists(path)) {
102
+ return undefined;
339
103
  }
104
+ // @ts-ignore // why is it doing this
105
+ return __fakeNode__.fs.lget(path).stat(bigint);
106
+ }
340
107
 
341
- access(mode: number = F_OK): void {
342
- const chmodInfo = (this.mode >> 3) & 0o777;
343
- let perms: number;
344
- if (process.getuid() === this.uid) {
345
- perms = (chmodInfo >> 6) & 7;
346
- } else if (process.getgid() === this.gid) {
347
- perms = (chmodInfo >> 3) & 7;
348
- } else {
349
- perms = chmodInfo & 7;
350
- }
351
- if ((((mode & X_OK) === X_OK) && !((perms & X_OK) === X_OK)) || (((mode & W_OK) === W_OK) && !((perms & W_OK) === W_OK)) || (((mode & R_OK) === R_OK) && !((perms & R_OK) === R_OK))) {
352
- throw new Error(`mode ${mode} and permissions ${chmodInfo} are not compatible`);
353
- }
108
+ export function mkdirSync(path: PathArg, options: {recursive?: boolean, mode?: ModeArg} | ModeArg = 0o777): void {
109
+ let recursive: boolean;
110
+ let mode: ModeArg;
111
+ if (typeof options === 'number' || typeof options === 'string') {
112
+ recursive = false;
113
+ mode = options;
114
+ } else {
115
+ recursive = options.recursive ?? false;
116
+ mode = options.mode ?? 0o777;
354
117
  }
118
+ __fakeNode__.fs.mkdir(path, recursive, mode);
119
+ }
355
120
 
356
- chmod(mode: string | number): void {
357
- mode = parseModeArg(mode);
358
- this.mode &= 0o170007;
359
- this.mode |= mode << 3;
360
- this.setCtime();
361
- }
121
+ export function mkdtempSync(prefix: PathArg, options: {encoding?: string} | string = 'utf8'): void {
122
+ throw new TypeError('fs.mkdtemp is not supported in fake-node');
123
+ }
362
124
 
363
- chown(uid: string | number, gid: string | number): void {
364
- this.uid = __fakeNode__.getUIDFromUser(uid);
365
- this.gid = __fakeNode__.getGIDFromGroup(gid);
366
- this.setCtime();
367
- }
125
+ export function opendirSync(path: PathArg, {encoding = 'utf8', bufferSize = 32, recursive = false}: {encoding?: string, bufferSize?: number, recursive?: boolean} = {}): void {
126
+ throw new TypeError('fs.opendir is not supported in fake-node');
127
+ }
368
128
 
369
- cp(): FileObject {
370
- return new FileObject({mode: this.mode, uid: this.uid, gid: this.gid});
371
- }
129
+ export function openSync(path: PathArg, flags: Flag, mode: ModeArg = 'r'): number {
130
+ return __fakeNode__.fs.open(path, flags, mode);
131
+ }
372
132
 
373
- cpr(): FileObject {
374
- return this.cp();
375
- }
133
+ export function readdirSync(path: PathArg, options: {encoding?: string, withFileTypes?: boolean, recursive?: boolean} | string = 'utf8') {
134
+ throw new TypeError('fs.readdir is not supported in fake-node');
135
+ }
376
136
 
377
- get size(): number {
378
- return -1;
379
- }
137
+ export function readFileSync(path: PathArg, options: {encoding?: null | 'buffer', flag?: string} | 'buffer'): Buffer;
138
+ export function readFileSync(path: PathArg, options: {encoding: BufferEncoding, flag?: string} | BufferEncoding): string;
139
+ export function readFileSync(path: PathArg, options: {encoding?: BufferEncoding | null | 'buffer', flag?: string} | BufferEncoding | 'buffer' = {encoding: null, flag: 'r'}): string | Buffer {
140
+ // @ts-ignore // why is it doing this
141
+ return __fakeNode__.fs.getRegular(path).read(typeof options === 'string' ? options : options.encoding ?? 'buffer');
142
+ }
380
143
 
381
- utimes(atime: TimeArg, mtime: TimeArg) {
382
- this.atime = parseTimeArg(atime);
383
- this.mtime = parseTimeArg(mtime);
384
- }
144
+ export function readlinkSync(path: PathArg, options: {encoding?: string} | string = 'utf8'): string | Buffer {
145
+ throw new TypeError('fs.readlink is not supported in fake-node');
146
+ }
385
147
 
386
- stat({bigint}: {bigint?: false}): Stats;
387
- stat({bigint}: {bigint: true}): BigIntStats;
388
- stat({bigint}: {bigint?: boolean}): Stats | BigIntStats {
389
- if (bigint) {
390
- let out = new BigIntStats();
391
- out.dev = 0n;
392
- out.ino = 0n;
393
- out.mode = BigInt(this.mode);
394
- out.nlink = BigInt(this.links.length);
395
- out.uid = BigInt(this.uid);
396
- out.gid = BigInt(this.gid);
397
- out.rdev = BigInt(this.rdev);
398
- out.size = BigInt(this.size);
399
- out.blksize = 4096n;
400
- out.blocks = BigInt(Math.ceil(this.size / 4096));
401
- out.atimeMs = this.atime / 1000000n;
402
- out.mtimeMs = this.mtime / 1000000n;
403
- out.ctimeMs = this.ctime / 1000000n;
404
- out.birthtimeMs = this.birthtime / 1000000n;
405
- out.atimeNs = this.atime;
406
- out.mtimeNs = this.mtime;
407
- out.ctimeNs = this.ctime;
408
- out.birthtimeNs = this.birthtime;
409
- out.atime = new Date(Number(this.atime / 1000000n));
410
- out.mtime = new Date(Number(this.mtime / 1000000n));
411
- out.ctime = new Date(Number(this.ctime / 1000000n));
412
- out.birthtime = new Date(Number(this.birthtime / 1000000n));
413
- return out;
414
- } else {
415
- let out = new Stats();
416
- out.dev = 0;
417
- out.ino = 0;
418
- out.mode = this.mode;
419
- out.nlink = this.links.length;
420
- out.uid = this.uid;
421
- out.gid = this.gid;
422
- out.rdev = this.rdev;
423
- out.size = this.size;
424
- out.blksize = 4096;
425
- out.blocks = Math.ceil(this.size / 4096);
426
- out.atimeMs = Number(this.atime / 1000000n);
427
- out.mtimeMs = Number(this.mtime / 1000000n);
428
- out.ctimeMs = Number(this.ctime / 1000000n);
429
- out.birthtimeMs = Number(this.birthtime / 1000000n);
430
- out.atime = new Date(Number(this.atime / 1000000n));
431
- out.mtime = new Date(Number(this.mtime / 1000000n));
432
- out.ctime = new Date(Number(this.ctime / 1000000n));
433
- out.birthtime = new Date(Number(this.birthtime / 1000000n));
434
- return out;
148
+ export function readSync(fd: number, buffer: Buffer | TypedArray | DataView, offset: number, length: number, position: number | bigint | null = null): number {
149
+ position = Number(position ?? 0);
150
+ const data = __fakeNode__.fs.getfdRegular(fd).read('uint8array', offset, length);
151
+ if (buffer instanceof DataView) {
152
+ for (let i = position; i < data.length; i++) {
153
+ buffer.setUint8(i, data[i]);
435
154
  }
155
+ } else {
156
+ // @ts-ignore // why is it doing this
157
+ buffer.set(data, position);
436
158
  }
437
-
159
+ return length;
438
160
  }
439
161
 
162
+ export function readvSync(fd: number, buffers: ArrayBufferView[], position: number | null = null): number {
163
+ throw new TypeError('fs.readv is not supported in fake-node');
164
+ }
440
165
 
441
- export class RegularFile extends FileObject {
442
-
443
- data: Uint8Array;
166
+ export function realpathSync(path: PathArg, {encoding}: {encoding: string} = {encoding: 'utf8'}): string {
167
+ return resolve(parsePathArg(path));
168
+ }
169
+ realpathSync.native = realpathSync;
444
170
 
445
- constructor(data: DataArg, {mode = 0o6440, encoding, ...params}: FileParams & {encoding?: string}) {
446
- super({mode: mode | S_IFREG, ...params});
447
- this.write(data);
448
- }
171
+ export function renameSync(oldPath: PathArg, newPath: PathArg): void {
172
+ const parsedOldPath = parsePathArg(oldPath);
173
+ const parsedNewPath = parsePathArg(newPath);
174
+ const file = __fakeNode__.fs.getDir(dirname(parsedOldPath)).unlink(basename(parsedOldPath));
175
+ __fakeNode__.fs.getDir(dirname(parsedNewPath)).link(basename(parsedNewPath), file);
176
+ }
449
177
 
450
- cp(): RegularFile {
451
- return new RegularFile(new Uint8Array(this.data), {mode: this.mode, uid: this.uid, gid: this.gid});
178
+ export function rmdirSync(path: PathArg): void {
179
+ const file = __fakeNode__.fs.get(path);
180
+ if (!(file instanceof Directory)) {
181
+ throw new TypeError(`cannot remove directory ${path}: is not a directory`);
182
+ } else if (!(file.size === 0)) {
183
+ throw new TypeError(`cannot remove directory ${path}: is not empty`);
452
184
  }
185
+ __fakeNode__.fs.unlink(path);
186
+ }
453
187
 
454
- read(encoding: BufferEncoding, start: number, length: number): string;
455
- read(encoding: 'uint8array', start: number, length: number): Uint8Array;
456
- read(encoding: 'buffer', start: number, length: number): Buffer;
457
- read(encoding: BufferEncoding | 'uint8array' | 'buffer' = 'utf8', start: number = 0, length: number = -1): string | Uint8Array | Buffer {
458
- if (encoding === 'uint8array') {
459
- return this.data;
460
- } else if (encoding === 'buffer') {
461
- return Buffer.from(this.data);
462
- } else {
463
- return (new TextDecoder(encoding)).decode(this.data);
464
- }
465
- }
188
+ export function rmSync(path: PathArg): void {
189
+ __fakeNode__.fs.unlink(path);
190
+ }
466
191
 
467
- write(data: string, position?: number, encoding?: BufferEncoding): void;
468
- write(data: TypedArray | DataView | Iterable<any>, offset?: number, length?: number): void;
469
- write(data: DataArg, position?: number, encoding_or_length?: number | BufferEncoding): void {
470
- const encoding = typeof encoding_or_length === 'string' ? encoding_or_length : 'utf8';
471
- const length = typeof encoding_or_length === 'number' ? encoding_or_length : -1;
472
- const array = parseDataArg(data, encoding);
473
- if (position === 0 && length === -1) {
474
- this.data = array;
475
- } else if (length === -1) {
476
- this.data.set(array, position);
477
- } else {
478
- this.data.set(array.slice(0, length), position);
479
- }
192
+ export function statSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: false, throwIfNoEntry: false}): Stats;
193
+ export function statSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: false, throwIfNoEntry: true}): Stats | undefined;
194
+ export function statSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: true, throwIfNoEntry: false}): BigIntStats;
195
+ export function statSync(path: PathArg, {bigint, throwIfNoEntry}: {bigint?: true, throwIfNoEntry: true}): BigIntStats | undefined;
196
+ export function statSync(path: PathArg, {bigint = false, throwIfNoEntry = false}: {bigint?: boolean, throwIfNoEntry?: boolean} = {}): Stats | BigIntStats | undefined {
197
+ if (!throwIfNoEntry && !__fakeNode__.fs.exists(path)) {
198
+ return undefined;
480
199
  }
481
-
200
+ // @ts-ignore // why is it doing this
201
+ return __fakeNode__.fs.get(path).stat(bigint);
482
202
  }
483
203
 
484
-
485
- export class Directory extends FileObject {
486
-
487
- files: Map<string, FileObject>;
488
-
489
- constructor(files: Map<string, FileObject>, {mode, ...params}: FileParams);
490
- constructor(files: {[key: string]: FileObject}, {mode, ...params}: FileParams);
491
- constructor(files: MapIterator<[string, FileObject]>, {mode, ...params}: FileParams);
492
- constructor(files: Map<string, FileObject> | {[key: string]: FileObject} | MapIterator<[string, FileObject]> = new Map(), {mode = 0o6440, ...params}: FileParams) {
493
- super({mode: mode | S_IFDIR, ...params});
494
- if (files instanceof Map) {
495
- this.files = files;
496
- } else {
497
- this.files = new Map(Object.entries(files));
498
- }
204
+ export function statfsSync(path: PathArg, {bigint}: {bigint?: false}): StatFs;
205
+ export function statfsSync(path: PathArg, {bigint}: {bigint?: true}): BigIntStatFs;
206
+ export function statfsSync(path: PathArg, {bigint = false}: {bigint?: boolean} = {}): StatFs | BigIntStatFs {
207
+ let file = __fakeNode__.fs.get(path);
208
+ if (!(file instanceof FileSystem)) {
209
+ throw new TypeError(`cannot get fs stat for ${path}: is not a file system`);
499
210
  }
211
+ // @ts-ignore // why is it doing this
212
+ return file.statfs(bigint);
213
+ }
500
214
 
501
- get(path: PathArg): FileObject {
502
- const file = this.files.get(parsePathArg(path));
503
- if (file === undefined) {
504
- throw new TypeError(`file ${path} does not exist`);
505
- }
506
- return file;
507
- }
215
+ export function symlinkSync(target: PathArg, path: PathArg): void {
216
+ __fakeNode__.fs.symlink(target, path);
217
+ }
508
218
 
509
- cp(): Directory {
510
- return new Directory(this.files.entries(), {mode: this.mode, uid: this.uid, gid: this.gid});
511
- }
219
+ export function truncateSync(path: PathArg, len: number = 0): void {
220
+ let file = __fakeNode__.fs.getRegular(path);
221
+ file.data = file.data.slice(0, len);
222
+ }
512
223
 
513
- cpr(): Directory {
514
- return new Directory(new Map(Array.from(this.files.entries()).map(([name, file]) => [name, file.cpr()])), {mode: this.mode, uid: this.uid, gid: this.gid});
515
- }
224
+ export function unlinkSync(path: PathArg): void {
225
+ __fakeNode__.fs.unlink(path);
226
+ }
516
227
 
228
+ export function utimesSync(path: PathArg, atime: TimeArg, mtime: TimeArg) {
229
+ __fakeNode__.fs.get(path).utimes(atime, mtime);
517
230
  }