@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.
- package/README.md +6 -8
- package/lib/cjs/callback.js +131 -0
- package/lib/cjs/dirent.js +127 -0
- package/lib/cjs/encoding.js +53 -0
- package/lib/cjs/file-handle.js +473 -0
- package/lib/cjs/fs-watcher.js +79 -0
- package/lib/cjs/index.js +95 -0
- package/lib/cjs/promises.js +189 -0
- package/lib/cjs/read-stream.js +107 -0
- package/lib/cjs/stats.js +74 -0
- package/lib/cjs/sync.js +155 -0
- package/lib/cjs/types/encoding-option.js +15 -0
- package/lib/cjs/types/file-read-options.js +15 -0
- package/lib/cjs/types/file-read-result.js +15 -0
- package/lib/cjs/types/flag-and-open-mode.js +15 -0
- package/lib/cjs/types/index.js +22 -0
- package/lib/cjs/types/open-flags.js +15 -0
- package/lib/cjs/types/read-options.js +15 -0
- package/lib/cjs/utils.js +37 -0
- package/lib/cjs/write-stream.js +135 -0
- package/lib/esm/callback.js +112 -0
- package/lib/esm/dirent.js +98 -0
- package/lib/esm/encoding.js +34 -0
- package/lib/esm/file-handle.js +444 -0
- package/lib/esm/fs-watcher.js +50 -0
- package/lib/esm/index.js +95 -0
- package/lib/esm/promises.js +160 -0
- package/lib/esm/read-stream.js +78 -0
- package/lib/esm/stats.js +45 -0
- package/lib/esm/sync.js +126 -0
- package/lib/esm/types/encoding-option.js +0 -0
- package/lib/esm/types/file-read-options.js +0 -0
- package/lib/esm/types/file-read-result.js +0 -0
- package/lib/esm/types/flag-and-open-mode.js +0 -0
- package/lib/esm/types/index.js +6 -0
- package/lib/esm/types/open-flags.js +0 -0
- package/lib/esm/types/read-options.js +0 -0
- package/lib/esm/utils.js +18 -0
- package/lib/esm/write-stream.js +116 -0
- package/package.json +52 -17
- package/src/callback.spec.ts +42 -0
- package/src/callback.ts +362 -0
- package/src/dirent.ts +117 -0
- package/src/encoding.ts +40 -0
- package/src/file-handle.spec.ts +34 -0
- package/src/file-handle.ts +606 -0
- package/{fs-watcher.js → src/fs-watcher.ts} +10 -9
- package/src/index.ts +95 -0
- package/src/promises.spec.ts +172 -0
- package/src/promises.ts +349 -0
- package/src/read-stream.ts +98 -0
- package/src/stat.spec.ts +79 -0
- package/src/stats.ts +106 -0
- package/src/symlink.spec.ts +38 -0
- package/src/sync.spec.ts +205 -0
- package/src/sync.ts +239 -0
- package/src/test.mts +11 -0
- package/src/types/encoding-option.ts +3 -0
- package/src/types/file-read-options.ts +15 -0
- package/src/types/file-read-result.ts +4 -0
- package/src/types/flag-and-open-mode.ts +6 -0
- package/src/types/index.ts +6 -0
- package/src/types/open-flags.ts +14 -0
- package/src/types/read-options.ts +9 -0
- package/src/utils.ts +19 -0
- package/src/write-stream.ts +143 -0
- package/test/file.txt +1 -0
- package/test/watch.js +1 -0
- package/test.gjs.js +35359 -0
- package/test.gjs.js.map +7 -0
- package/test.gjs.mjs +40570 -0
- package/test.gjs.mjs.meta.json +1 -0
- package/test.node.js +1479 -0
- package/test.node.js.map +7 -0
- package/test.node.mjs +710 -0
- package/tsconfig.json +18 -0
- package/tsconfig.types.json +8 -0
- package/index.js +0 -114
- package/test/index.js +0 -90
- package/test/resources/file.txt +0 -1
package/src/stat.spec.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, it, expect } from '@gjsify/unit';
|
|
2
|
+
// import { join, dirname } from 'path';
|
|
3
|
+
// import { fileURLToPath } from "url";
|
|
4
|
+
|
|
5
|
+
// const __filename = fileURLToPath(import.meta.url)
|
|
6
|
+
// const __dirname = dirname(__filename)
|
|
7
|
+
|
|
8
|
+
import { statSync } from 'fs';
|
|
9
|
+
import { stat } from 'fs/promises';
|
|
10
|
+
|
|
11
|
+
export default async () => {
|
|
12
|
+
await describe('fs.statSync', async () => {
|
|
13
|
+
|
|
14
|
+
await it('Should return the file stat', async () => {
|
|
15
|
+
|
|
16
|
+
const s = statSync('tsconfig.json');
|
|
17
|
+
|
|
18
|
+
expect(s.atime instanceof Date).toBeTruthy();
|
|
19
|
+
expect(s.atimeMs).toBeGreaterThan(0);
|
|
20
|
+
expect(s.birthtime instanceof Date).toBeTruthy();
|
|
21
|
+
expect(s.birthtimeMs).toBeGreaterThan(0);
|
|
22
|
+
expect(s.blksize).toBeGreaterThan(0);
|
|
23
|
+
expect(s.blocks).toBeGreaterThan(0);
|
|
24
|
+
expect(s.ctime instanceof Date).toBeTruthy();
|
|
25
|
+
expect(s.ctimeMs).toBeGreaterThan(0);
|
|
26
|
+
expect(s.dev).toBeGreaterThan(0);
|
|
27
|
+
expect(s.gid).toBeGreaterThan(0);
|
|
28
|
+
expect(s.ino).toBeGreaterThan(0);
|
|
29
|
+
expect(s.mode).toBeGreaterThan(0);
|
|
30
|
+
expect(s.mtime instanceof Date).toBeTruthy();
|
|
31
|
+
expect(s.mtimeMs).toBeGreaterThan(0);
|
|
32
|
+
expect(s.nlink).toBeGreaterThan(0);
|
|
33
|
+
expect(s.rdev).toBeGreaterThan(-1);
|
|
34
|
+
expect(s.size).toBeGreaterThan(0);
|
|
35
|
+
expect(s.uid).toBeGreaterThan(0);
|
|
36
|
+
expect(s.isBlockDevice()).toBeFalsy();
|
|
37
|
+
expect(s.isCharacterDevice()).toBeFalsy();
|
|
38
|
+
expect(s.isDirectory()).toBeFalsy();
|
|
39
|
+
expect(s.isFIFO()).toBeFalsy();
|
|
40
|
+
expect(s.isFile()).toBeTruthy();
|
|
41
|
+
expect(s.isSocket()).toBeFalsy();
|
|
42
|
+
expect(s.isSymbolicLink()).toBeFalsy();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
await describe('fs.stat (promise)', async () => {
|
|
47
|
+
|
|
48
|
+
await it('Should return the file stat', async () => {
|
|
49
|
+
|
|
50
|
+
const s = await stat('tsconfig.json');
|
|
51
|
+
|
|
52
|
+
expect(s.atime instanceof Date).toBeTruthy();
|
|
53
|
+
expect(s.atimeMs).toBeGreaterThan(0);
|
|
54
|
+
expect(s.birthtime instanceof Date).toBeTruthy();
|
|
55
|
+
expect(s.birthtimeMs).toBeGreaterThan(0);
|
|
56
|
+
expect(s.blksize).toBeGreaterThan(0);
|
|
57
|
+
expect(s.blocks).toBeGreaterThan(0);
|
|
58
|
+
expect(s.ctime instanceof Date).toBeTruthy();
|
|
59
|
+
expect(s.ctimeMs).toBeGreaterThan(0);
|
|
60
|
+
expect(s.dev).toBeGreaterThan(0);
|
|
61
|
+
expect(s.gid).toBeGreaterThan(0);
|
|
62
|
+
expect(s.ino).toBeGreaterThan(0);
|
|
63
|
+
expect(s.mode).toBeGreaterThan(0);
|
|
64
|
+
expect(s.mtime instanceof Date).toBeTruthy();
|
|
65
|
+
expect(s.mtimeMs).toBeGreaterThan(0);
|
|
66
|
+
expect(s.nlink).toBeGreaterThan(0);
|
|
67
|
+
expect(s.rdev).toBeGreaterThan(-1);
|
|
68
|
+
expect(s.size).toBeGreaterThan(0);
|
|
69
|
+
expect(s.uid).toBeGreaterThan(0);
|
|
70
|
+
expect(s.isBlockDevice()).toBeFalsy();
|
|
71
|
+
expect(s.isCharacterDevice()).toBeFalsy();
|
|
72
|
+
expect(s.isDirectory()).toBeFalsy();
|
|
73
|
+
expect(s.isFIFO()).toBeFalsy();
|
|
74
|
+
expect(s.isFile()).toBeTruthy();
|
|
75
|
+
expect(s.isSocket()).toBeFalsy();
|
|
76
|
+
expect(s.isSymbolicLink()).toBeFalsy();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
package/src/stats.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import Gio from '@girs/gio-2.0';
|
|
2
|
+
import { Dirent } from './dirent.js';
|
|
3
|
+
import { basename } from 'path';
|
|
4
|
+
|
|
5
|
+
import type { Stats as NodeStats, PathLike } from 'fs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A `fs.Stats` object provides information about a file.
|
|
9
|
+
*
|
|
10
|
+
* Objects returned from {@link stat}, {@link lstat} and {@link fstat} and
|
|
11
|
+
* their synchronous counterparts are of this type.
|
|
12
|
+
* If `bigint` in the `options` passed to those methods is true, the numeric values
|
|
13
|
+
* will be `bigint` instead of `number`, and the object will contain additional
|
|
14
|
+
* nanosecond-precision properties suffixed with `Ns`.
|
|
15
|
+
*
|
|
16
|
+
* ```console
|
|
17
|
+
* Stats {
|
|
18
|
+
* dev: 2114,
|
|
19
|
+
* ino: 48064969,
|
|
20
|
+
* mode: 33188,
|
|
21
|
+
* nlink: 1,
|
|
22
|
+
* uid: 85,
|
|
23
|
+
* gid: 100,
|
|
24
|
+
* rdev: 0,
|
|
25
|
+
* size: 527,
|
|
26
|
+
* blksize: 4096,
|
|
27
|
+
* blocks: 8,
|
|
28
|
+
* atimeMs: 1318289051000.1,
|
|
29
|
+
* mtimeMs: 1318289051000.1,
|
|
30
|
+
* ctimeMs: 1318289051000.1,
|
|
31
|
+
* birthtimeMs: 1318289051000.1,
|
|
32
|
+
* atime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
33
|
+
* mtime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
34
|
+
* ctime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
35
|
+
* birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* `bigint` version:
|
|
39
|
+
*
|
|
40
|
+
* ```console
|
|
41
|
+
* BigIntStats {
|
|
42
|
+
* dev: 2114n,
|
|
43
|
+
* ino: 48064969n,
|
|
44
|
+
* mode: 33188n,
|
|
45
|
+
* nlink: 1n,
|
|
46
|
+
* uid: 85n,
|
|
47
|
+
* gid: 100n,
|
|
48
|
+
* rdev: 0n,
|
|
49
|
+
* size: 527n,
|
|
50
|
+
* blksize: 4096n,
|
|
51
|
+
* blocks: 8n,
|
|
52
|
+
* atimeMs: 1318289051000n,
|
|
53
|
+
* mtimeMs: 1318289051000n,
|
|
54
|
+
* ctimeMs: 1318289051000n,
|
|
55
|
+
* birthtimeMs: 1318289051000n,
|
|
56
|
+
* atimeNs: 1318289051000000000n,
|
|
57
|
+
* mtimeNs: 1318289051000000000n,
|
|
58
|
+
* ctimeNs: 1318289051000000000n,
|
|
59
|
+
* birthtimeNs: 1318289051000000000n,
|
|
60
|
+
* atime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
61
|
+
* mtime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
62
|
+
* ctime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
63
|
+
* birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
|
|
64
|
+
* ```
|
|
65
|
+
* @since v0.1.21
|
|
66
|
+
*/
|
|
67
|
+
export class Stats extends Dirent implements NodeStats {
|
|
68
|
+
dev: number;
|
|
69
|
+
ino: number;
|
|
70
|
+
mode: number;
|
|
71
|
+
nlink: number;
|
|
72
|
+
uid: number;
|
|
73
|
+
gid: number;
|
|
74
|
+
rdev: number;
|
|
75
|
+
size: number;
|
|
76
|
+
blksize: number;
|
|
77
|
+
blocks: number;
|
|
78
|
+
atimeMs: number;
|
|
79
|
+
mtimeMs: number;
|
|
80
|
+
ctimeMs: number;
|
|
81
|
+
/** The timestamp indicating the creation time of this file expressed in milliseconds since the POSIX Epoch. */
|
|
82
|
+
get birthtimeMs(): number {
|
|
83
|
+
const creationDateTime = this._info.get_creation_date_time();
|
|
84
|
+
return creationDateTime.get_microsecond() * 1000;
|
|
85
|
+
}
|
|
86
|
+
atime: Date;
|
|
87
|
+
mtime: Date;
|
|
88
|
+
ctime: Date;
|
|
89
|
+
/** The timestamp indicating the creation time of this file. */
|
|
90
|
+
get birthtime(): Date {
|
|
91
|
+
const creationDateTime = this._info.get_creation_date_time();
|
|
92
|
+
return new Date(creationDateTime.format_iso8601());
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected _info: Gio.FileInfo;
|
|
96
|
+
|
|
97
|
+
constructor(path: PathLike, filename?: string) {
|
|
98
|
+
const pathStr = path.toString();
|
|
99
|
+
if (!filename) filename = basename(pathStr);
|
|
100
|
+
super(pathStr, filename);
|
|
101
|
+
if(!this._file) {
|
|
102
|
+
throw new TypeError('this._file is not defined!');
|
|
103
|
+
}
|
|
104
|
+
this._info = this._file.query_info('standard::', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect } from '@gjsify/unit';
|
|
2
|
+
// import { join, dirname } from 'path';
|
|
3
|
+
// import { fileURLToPath } from "url";
|
|
4
|
+
|
|
5
|
+
// const __filename = fileURLToPath(import.meta.url)
|
|
6
|
+
// const __dirname = dirname(__filename)
|
|
7
|
+
|
|
8
|
+
import { symlink as symlinkCb, mkdtempSync, lstatSync } from 'fs';
|
|
9
|
+
import { symlink, rmdir, unlink } from 'fs/promises';
|
|
10
|
+
|
|
11
|
+
export default async () => {
|
|
12
|
+
await describe('fs.symlink', async () => {
|
|
13
|
+
|
|
14
|
+
await it('ASYNC: no callback function results in Error', () => {
|
|
15
|
+
expect(() => {
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
symlinkCb("some/path", "some/other/path", "dir");
|
|
18
|
+
}).toThrow(Error)
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// TODO FIXME
|
|
22
|
+
// await it('ASYNC: create symlink point to a dir', async () => {
|
|
23
|
+
|
|
24
|
+
// const tmpDir = mkdtempSync('test_tmp_');
|
|
25
|
+
// const linkedTmpDir = tmpDir + ".link";
|
|
26
|
+
|
|
27
|
+
// await symlink(tmpDir, linkedTmpDir)
|
|
28
|
+
// const stat = lstatSync(linkedTmpDir);
|
|
29
|
+
|
|
30
|
+
// expect(stat.isSymbolicLink).toBeTruthy();
|
|
31
|
+
|
|
32
|
+
// await rmdir(tmpDir);
|
|
33
|
+
// await unlink(linkedTmpDir);
|
|
34
|
+
// });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
}
|
package/src/sync.spec.ts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { describe, it, expect } from '@gjsify/unit';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
6
|
+
const __dirname = dirname(__filename)
|
|
7
|
+
|
|
8
|
+
import { existsSync, readdirSync, readFileSync, mkdirSync, rmdirSync, writeFileSync, unlinkSync, watch, mkdtempSync, rmSync, realpathSync, symlinkSync } from 'fs';
|
|
9
|
+
import { Buffer } from 'buffer';
|
|
10
|
+
|
|
11
|
+
export default async () => {
|
|
12
|
+
await describe('fs.existsSync', async () => {
|
|
13
|
+
|
|
14
|
+
const existingFiles = ['tsconfig.json', 'package.json', 'README.md'];
|
|
15
|
+
const nonExistingFiles = ['asdasd', '/asdasd', ''];
|
|
16
|
+
|
|
17
|
+
await it('should return true for existing files', () => {
|
|
18
|
+
for (const file of existingFiles) {
|
|
19
|
+
const result = existsSync(file);
|
|
20
|
+
expect(result).toBe(true)
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await it('should return false for non existing files', () => {
|
|
25
|
+
for (const file of nonExistingFiles) {
|
|
26
|
+
const result = existsSync(file);
|
|
27
|
+
expect(result).toBe(false)
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
await describe('fs.readdirSync', async () => {
|
|
33
|
+
await it('should return no files for an empty directory', () => {
|
|
34
|
+
const dir = mkdtempSync('fs-test-');
|
|
35
|
+
const files = readdirSync(dir);
|
|
36
|
+
expect(files.length).toBe(0);
|
|
37
|
+
|
|
38
|
+
// Clear
|
|
39
|
+
rmdirSync(dir);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await it('should return the files for non-empty directory', () => {
|
|
43
|
+
const dir = mkdtempSync('fs-test-');
|
|
44
|
+
const txt1 = join(dir, 'test1.txt');
|
|
45
|
+
const txt2 = join(dir, 'test2.txt');
|
|
46
|
+
const dir1 = join(dir, 'empty-dir');
|
|
47
|
+
writeFileSync(txt1, '');
|
|
48
|
+
writeFileSync(txt2, '');
|
|
49
|
+
mkdirSync(dir1);
|
|
50
|
+
const files = readdirSync(dir);
|
|
51
|
+
expect(files.length).toEqual(3);
|
|
52
|
+
|
|
53
|
+
// Clear
|
|
54
|
+
rmSync(txt1);
|
|
55
|
+
rmSync(txt2);
|
|
56
|
+
rmdirSync(dir1);
|
|
57
|
+
rmdirSync(dir);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await it('should return the file with the name "file.txt"', () => {
|
|
61
|
+
const dir = mkdtempSync('fs-test-');
|
|
62
|
+
const expectedFileName = 'file.txt';
|
|
63
|
+
const file = join(dir, expectedFileName);
|
|
64
|
+
|
|
65
|
+
writeFileSync(file, '');
|
|
66
|
+
|
|
67
|
+
const files = readdirSync(dir);
|
|
68
|
+
expect(files[0]).toEqual(expectedFileName);
|
|
69
|
+
|
|
70
|
+
// Clear
|
|
71
|
+
rmSync(file);
|
|
72
|
+
rmdirSync(dir);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await it('should return with file types if option "withFileTypes" is `true`', () => {
|
|
76
|
+
const dir = mkdtempSync('fs-test-');
|
|
77
|
+
const expectedFile = 'file.txt';
|
|
78
|
+
const expectedDir = 'subdir';
|
|
79
|
+
const file = join(dir, expectedFile);
|
|
80
|
+
const subdir = join(dir, expectedDir);
|
|
81
|
+
|
|
82
|
+
writeFileSync(file, '');
|
|
83
|
+
mkdirSync(subdir);
|
|
84
|
+
|
|
85
|
+
const files = readdirSync(dir, { withFileTypes: true });
|
|
86
|
+
|
|
87
|
+
expect(files.length).toBe(2);
|
|
88
|
+
|
|
89
|
+
const fileWithTypes = files.find((f) => f.name === expectedFile);
|
|
90
|
+
const dirWithTypes = files.find((f) => f.name === expectedDir);
|
|
91
|
+
|
|
92
|
+
expect(fileWithTypes.isFile()).toBeTruthy();
|
|
93
|
+
expect(fileWithTypes.isDirectory()).toBeFalsy();
|
|
94
|
+
|
|
95
|
+
expect(dirWithTypes.isFile()).toBeFalsy();
|
|
96
|
+
expect(dirWithTypes.isDirectory()).toBeTruthy();
|
|
97
|
+
|
|
98
|
+
// Clear
|
|
99
|
+
rmSync(file);
|
|
100
|
+
rmdirSync(subdir);
|
|
101
|
+
rmdirSync(dir);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await describe('fs.readFileSync', async () => {
|
|
106
|
+
await it('should return a Buffer if no encoding was specified', () => {
|
|
107
|
+
const bufferData = readFileSync('package.json');
|
|
108
|
+
expect(bufferData instanceof Buffer).toBeTruthy();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
await it('should return a string when encoding is utf-8', () => {
|
|
112
|
+
const utf8Data = readFileSync('./test/file.txt', 'utf-8');
|
|
113
|
+
expect(typeof utf8Data === 'string').toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
await it('should return a string with "Hello World"', () => {
|
|
117
|
+
const utf8Data = readFileSync('./test/file.txt', 'utf-8');
|
|
118
|
+
expect(utf8Data).toBe('Hello World');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
await describe('fs.mkdirSync', async () => {
|
|
123
|
+
const dir = './foobar';
|
|
124
|
+
|
|
125
|
+
await it(`should create the directory "${dir}" without error`, () => {
|
|
126
|
+
mkdirSync(dir);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await it(`${dir} should exists`, () => {
|
|
130
|
+
expect(existsSync(dir)).toBeTruthy();
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
await describe('fs.rmdirSync', async () => {
|
|
135
|
+
const dir = './foobar';
|
|
136
|
+
|
|
137
|
+
await it(`should be remove the directory "${dir}" without error`, () => {
|
|
138
|
+
rmdirSync(dir);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
await it(`"${dir}" should not exists (anymore)`, () => {
|
|
142
|
+
expect(existsSync(dir)).toBeFalsy();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
await describe('fs.writeFileSync', async () => {
|
|
147
|
+
const watchMe = join(__dirname, 'test/watch.js');
|
|
148
|
+
|
|
149
|
+
await it(`should be executed without error`, () => {
|
|
150
|
+
writeFileSync(watchMe, '// test');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
await it(`fs.watch should watch ${watchMe} for changes`, () => {
|
|
154
|
+
const watcher = watch(watchMe, {persistent: true}, console.log);
|
|
155
|
+
|
|
156
|
+
watcher.on('change', console.log).on('rename', console.log);
|
|
157
|
+
|
|
158
|
+
setTimeout(() => { watcher.close(); }, 1000);
|
|
159
|
+
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
writeFileSync(watchMe, '// test');
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
unlinkSync(watchMe);
|
|
164
|
+
}, 100);
|
|
165
|
+
}, 100);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
await describe('fs.mkdtempSync', async () => {
|
|
170
|
+
|
|
171
|
+
await it('should be a function', () => {
|
|
172
|
+
expect(typeof mkdtempSync).toBe("function");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
await it('should create a new directory', () => {
|
|
176
|
+
const directory = mkdtempSync('fs-test-');
|
|
177
|
+
expect(existsSync(directory)).toBeTruthy();
|
|
178
|
+
rmdirSync(directory);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
await describe('fs.realpathSync', async () => {
|
|
183
|
+
|
|
184
|
+
await it('should be a function', () => {
|
|
185
|
+
expect(typeof realpathSync).toBe("function");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
await it('should return the real and absolute path', () => {
|
|
189
|
+
const tsConfig = "./tsconfig.json";
|
|
190
|
+
const tsConfigSymlink = "./symlink_tsconfig.json";
|
|
191
|
+
|
|
192
|
+
if(!existsSync(tsConfigSymlink)) {
|
|
193
|
+
symlinkSync(tsConfig, tsConfigSymlink);
|
|
194
|
+
|
|
195
|
+
const realPath = realpathSync(tsConfig);
|
|
196
|
+
const realSymLinkPath = realpathSync(tsConfigSymlink);
|
|
197
|
+
|
|
198
|
+
// Should point to the real file, not the symlink
|
|
199
|
+
expect(realSymLinkPath).toBe(realPath);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
unlinkSync(tsConfigSymlink);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
}
|
package/src/sync.ts
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import GLib from '@girs/glib-2.0';
|
|
2
|
+
import Gio from '@girs/gio-2.0';
|
|
3
|
+
import { existsSync } from '@gjsify/utils';
|
|
4
|
+
import { Buffer } from 'buffer';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
|
|
7
|
+
import FSWatcher from './fs-watcher.js';
|
|
8
|
+
import { getEncodingFromOptions, encodeUint8Array, decode } from './encoding.js';
|
|
9
|
+
import { FileHandle } from './file-handle.js';
|
|
10
|
+
import { Dirent } from './dirent.js';
|
|
11
|
+
import { tempDirPath } from './utils.js';
|
|
12
|
+
|
|
13
|
+
export { realpathSync } from '@gjsify/deno_std/node/_fs/_fs_realpath';
|
|
14
|
+
import { readdirSync } from '@gjsify/deno_std/node/_fs/_fs_readdir';
|
|
15
|
+
export { symlinkSync } from '@gjsify/deno_std/node/_fs/_fs_symlink';
|
|
16
|
+
export { lstatSync } from '@gjsify/deno_std/node/_fs/_fs_lstat';
|
|
17
|
+
export { statSync } from '@gjsify/deno_std/node/_fs/_fs_stat';
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
import type { OpenFlags, EncodingOption } from './types/index.js';
|
|
22
|
+
import type {
|
|
23
|
+
PathLike,
|
|
24
|
+
Mode,
|
|
25
|
+
MakeDirectoryOptions,
|
|
26
|
+
BufferEncodingOption,
|
|
27
|
+
RmOptions,
|
|
28
|
+
RmDirOptions,
|
|
29
|
+
} from 'fs'; // Types from @types/node
|
|
30
|
+
|
|
31
|
+
export { existsSync, readdirSync }
|
|
32
|
+
|
|
33
|
+
export function readFileSync(path: string, options = { encoding: null, flag: 'r' }) {
|
|
34
|
+
const file = Gio.File.new_for_path(path);
|
|
35
|
+
|
|
36
|
+
const [ok, data] = file.load_contents(null);
|
|
37
|
+
|
|
38
|
+
if (!ok) {
|
|
39
|
+
// TODO: throw a better error
|
|
40
|
+
throw new Error('failed to read file');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return encodeUint8Array(getEncodingFromOptions(options, "buffer"), data);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Synchronously creates a directory. Returns `undefined`, or if `recursive` is`true`, the first directory path created.
|
|
48
|
+
* This is the synchronous version of {@link mkdir}.
|
|
49
|
+
*
|
|
50
|
+
* See the POSIX [`mkdir(2)`](http://man7.org/linux/man-pages/man2/mkdir.2.html) documentation for more details.
|
|
51
|
+
* @since v0.1.21
|
|
52
|
+
*/
|
|
53
|
+
export function mkdirSync(
|
|
54
|
+
path: PathLike,
|
|
55
|
+
options: MakeDirectoryOptions & {
|
|
56
|
+
recursive: true;
|
|
57
|
+
}
|
|
58
|
+
): string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Synchronous mkdir(2) - create a directory.
|
|
61
|
+
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
|
|
62
|
+
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
|
|
63
|
+
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
|
|
64
|
+
*/
|
|
65
|
+
export function mkdirSync(
|
|
66
|
+
path: PathLike,
|
|
67
|
+
options?:
|
|
68
|
+
| Mode
|
|
69
|
+
| (MakeDirectoryOptions & {
|
|
70
|
+
recursive?: false | undefined;
|
|
71
|
+
})
|
|
72
|
+
| null
|
|
73
|
+
): void;
|
|
74
|
+
/**
|
|
75
|
+
* Synchronous mkdir(2) - create a directory.
|
|
76
|
+
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
|
|
77
|
+
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
|
|
78
|
+
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
|
|
79
|
+
*/
|
|
80
|
+
export function mkdirSync(path: PathLike, options?: Mode | MakeDirectoryOptions | null): string | undefined | void
|
|
81
|
+
/**
|
|
82
|
+
* Synchronous mkdir(2) - create a directory.
|
|
83
|
+
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
|
|
84
|
+
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
|
|
85
|
+
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
|
|
86
|
+
*/
|
|
87
|
+
export function mkdirSync(path: PathLike, options?: Mode | MakeDirectoryOptions | null): string | undefined | void {
|
|
88
|
+
|
|
89
|
+
let recursive = false
|
|
90
|
+
let mode: Mode | undefined = 0o777;
|
|
91
|
+
|
|
92
|
+
if (typeof options === 'object') {
|
|
93
|
+
if(options?.recursive) recursive = options.recursive;
|
|
94
|
+
if(options?.mode) mode = options.mode;
|
|
95
|
+
} else {
|
|
96
|
+
mode = options || 0o777;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (typeof path !== 'string') {
|
|
100
|
+
path = path.toString();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if(typeof mode === 'string') {
|
|
104
|
+
throw new TypeError("mode as string is currently not supported!");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (GLib.mkdir_with_parents(path, mode) !== 0) {
|
|
108
|
+
// TODO: throw a better error
|
|
109
|
+
throw new Error(`failed to make ${path} directory`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (recursive) {
|
|
113
|
+
// TODO: Returns `undefined`, or if `recursive` is`true`, the first directory path created.
|
|
114
|
+
return path.split('/')[0];
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Synchronous [`rmdir(2)`](http://man7.org/linux/man-pages/man2/rmdir.2.html). Returns `undefined`.
|
|
121
|
+
*
|
|
122
|
+
* Using `fs.rmdirSync()` on a file (not a directory) results in an `ENOENT` error
|
|
123
|
+
* on Windows and an `ENOTDIR` error on POSIX.
|
|
124
|
+
*
|
|
125
|
+
* To get a behavior similar to the `rm -rf` Unix command, use {@link rmSync} with options `{ recursive: true, force: true }`.
|
|
126
|
+
* @since v0.1.21
|
|
127
|
+
*/
|
|
128
|
+
export function rmdirSync(path: PathLike, options?: RmDirOptions): void {
|
|
129
|
+
|
|
130
|
+
const recursive = options?.recursive || false;
|
|
131
|
+
|
|
132
|
+
const childFiles = readdirSync(path, { withFileTypes: true });
|
|
133
|
+
|
|
134
|
+
if (!recursive && childFiles.length) {
|
|
135
|
+
throw new Error('Dir is not empty!');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (const childFile of childFiles) {
|
|
139
|
+
if (childFile.isDirectory()) {
|
|
140
|
+
rmdirSync(join(path.toString(), childFile.name));
|
|
141
|
+
} else if (childFile.isFile()) {
|
|
142
|
+
rmSync(join(path.toString(), childFile.name));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const result = GLib.rmdir(path.toString());
|
|
147
|
+
|
|
148
|
+
if (result !== 0) {
|
|
149
|
+
// TODO: throw a better error
|
|
150
|
+
throw new Error(`Failed to remove ${path} directory`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function unlinkSync(path: string) {
|
|
155
|
+
GLib.unlink(path);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function writeFileSync(path: string, data: any) {
|
|
159
|
+
GLib.file_set_contents(path, data);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function watch(filename: string, options, listener) {
|
|
163
|
+
return new FSWatcher(filename, options, listener);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function openSync(path: PathLike, flags?: OpenFlags, mode?: Mode): FileHandle {
|
|
167
|
+
return new FileHandle({ path, flags, mode });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Returns the created directory path.
|
|
172
|
+
*
|
|
173
|
+
* For detailed information, see the documentation of the asynchronous version of
|
|
174
|
+
* this API: {@link mkdtemp}.
|
|
175
|
+
*
|
|
176
|
+
* The optional `options` argument can be a string specifying an encoding, or an
|
|
177
|
+
* object with an `encoding` property specifying the character encoding to use.
|
|
178
|
+
* @since v5.10.0
|
|
179
|
+
*/
|
|
180
|
+
export function mkdtempSync(prefix: string, options?: EncodingOption): string;
|
|
181
|
+
/**
|
|
182
|
+
* Synchronously creates a unique temporary directory.
|
|
183
|
+
* Generates six random characters to be appended behind a required prefix to create a unique temporary directory.
|
|
184
|
+
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
|
|
185
|
+
*/
|
|
186
|
+
export function mkdtempSync(prefix: string, options: BufferEncodingOption): Buffer;
|
|
187
|
+
/**
|
|
188
|
+
* Synchronously creates a unique temporary directory.
|
|
189
|
+
* Generates six random characters to be appended behind a required prefix to create a unique temporary directory.
|
|
190
|
+
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
|
|
191
|
+
*/
|
|
192
|
+
export function mkdtempSync(prefix: string, options?: EncodingOption): string | Buffer;
|
|
193
|
+
|
|
194
|
+
export function mkdtempSync(prefix: string, options?: EncodingOption | BufferEncodingOption): string | Buffer {
|
|
195
|
+
const encoding: string | undefined = getEncodingFromOptions(options);
|
|
196
|
+
const path = tempDirPath(prefix);
|
|
197
|
+
|
|
198
|
+
mkdirSync(
|
|
199
|
+
path,
|
|
200
|
+
{ recursive: false, mode: 0o777 }
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return decode(path, encoding);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Synchronously removes files and directories (modeled on the standard POSIX `rm`utility). Returns `undefined`.
|
|
208
|
+
* @since v14.14.0
|
|
209
|
+
*/
|
|
210
|
+
export function rmSync(path: PathLike, options?: RmOptions): void {
|
|
211
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
212
|
+
const recursive = options?.recursive || false;
|
|
213
|
+
|
|
214
|
+
const dirent = new Dirent(path.toString());
|
|
215
|
+
|
|
216
|
+
if (dirent.isDirectory()) {
|
|
217
|
+
const childFiles = readdirSync(path, { withFileTypes: true });
|
|
218
|
+
|
|
219
|
+
if (!recursive && childFiles.length) {
|
|
220
|
+
throw new Error('Dir is not empty!');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
for (const childFile of childFiles) {
|
|
224
|
+
if (childFile.isDirectory()) {
|
|
225
|
+
rmdirSync(join(path.toString(), childFile.name), options);
|
|
226
|
+
} else if (childFile.isFile()) {
|
|
227
|
+
rmSync(join(path.toString(), childFile.name), options);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const ok = file.delete(null);
|
|
233
|
+
|
|
234
|
+
if (!ok) {
|
|
235
|
+
// TODO: throw a better error
|
|
236
|
+
const err = new Error('failed to remove file ' + path);
|
|
237
|
+
throw err;
|
|
238
|
+
}
|
|
239
|
+
}
|
package/src/test.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
import { run } from '@gjsify/unit';
|
|
3
|
+
|
|
4
|
+
import testSuiteCallback from './callback.spec.js';
|
|
5
|
+
import testSuiteFileHandle from './file-handle.spec.js';
|
|
6
|
+
import testSuitePromise from './promises.spec.js';
|
|
7
|
+
import testSuiteSync from './sync.spec.js';
|
|
8
|
+
import testSuiteSymlink from './symlink.spec.js';
|
|
9
|
+
import testSuiteStat from './stat.spec.js';
|
|
10
|
+
|
|
11
|
+
run({testSuiteCallback, testSuiteFileHandle, testSuitePromise, testSuiteSync, testSuiteSymlink, testSuiteStat});
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
}
|