@zenfs/core 2.0.0 → 2.1.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/dist/backends/backend.js +6 -5
- package/dist/backends/cow.d.ts +2 -2
- package/dist/backends/cow.js +39 -58
- package/dist/backends/fetch.js +27 -29
- package/dist/backends/passthrough.d.ts +2 -3
- package/dist/backends/passthrough.js +84 -199
- package/dist/backends/port.d.ts +16 -3
- package/dist/backends/port.js +61 -30
- package/dist/backends/single_buffer.d.ts +52 -46
- package/dist/backends/single_buffer.js +462 -219
- package/dist/backends/store/fs.d.ts +16 -10
- package/dist/backends/store/fs.js +227 -242
- package/dist/backends/store/store.d.ts +3 -3
- package/dist/backends/store/store.js +11 -10
- package/dist/config.d.ts +2 -2
- package/dist/config.js +10 -11
- package/dist/internal/devices.d.ts +2 -2
- package/dist/internal/devices.js +39 -49
- package/dist/internal/error.d.ts +9 -204
- package/dist/internal/error.js +19 -288
- package/dist/internal/file_index.d.ts +1 -1
- package/dist/internal/file_index.js +9 -9
- package/dist/internal/filesystem.d.ts +23 -8
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index_fs.d.ts +2 -2
- package/dist/internal/index_fs.js +19 -19
- package/dist/internal/inode.d.ts +81 -103
- package/dist/internal/inode.js +336 -195
- package/dist/mixins/async.js +32 -28
- package/dist/mixins/mutexed.d.ts +4 -4
- package/dist/mixins/mutexed.js +39 -39
- package/dist/mixins/readonly.d.ts +2 -2
- package/dist/mixins/readonly.js +20 -20
- package/dist/mixins/sync.js +2 -2
- package/dist/polyfills.js +1 -1
- package/dist/readline.js +1 -1
- package/dist/utils.d.ts +8 -5
- package/dist/utils.js +14 -17
- package/dist/vfs/acl.d.ts +8 -8
- package/dist/vfs/acl.js +66 -47
- package/dist/vfs/async.d.ts +2 -2
- package/dist/vfs/async.js +6 -8
- package/dist/vfs/dir.d.ts +1 -1
- package/dist/vfs/dir.js +3 -4
- package/dist/vfs/file.js +33 -24
- package/dist/vfs/flags.js +3 -3
- package/dist/vfs/ioctl.d.ts +8 -7
- package/dist/vfs/ioctl.js +132 -27
- package/dist/vfs/promises.d.ts +3 -3
- package/dist/vfs/promises.js +200 -235
- package/dist/vfs/shared.d.ts +1 -12
- package/dist/vfs/shared.js +7 -35
- package/dist/vfs/streams.js +9 -9
- package/dist/vfs/sync.d.ts +1 -2
- package/dist/vfs/sync.js +158 -170
- package/dist/vfs/watchers.js +8 -8
- package/dist/vfs/xattr.js +89 -106
- package/package.json +4 -2
- package/scripts/test.js +2 -2
- package/tests/assignment.ts +1 -1
- package/tests/backend/port.test.ts +4 -4
- package/tests/backend/single-buffer.test.ts +39 -10
- package/tests/backend/single-buffer.worker.js +30 -0
- package/tests/common/context.test.ts +2 -2
- package/tests/common/mutex.test.ts +9 -9
- package/tests/fetch/fetch.ts +1 -1
- package/tests/fs/append.test.ts +4 -4
- package/tests/fs/directory.test.ts +25 -25
- package/tests/fs/errors.test.ts +15 -19
- package/tests/fs/links.test.ts +3 -2
- package/tests/fs/open.test.ts +4 -21
- package/tests/fs/permissions.test.ts +8 -13
- package/tests/fs/read.test.ts +10 -9
- package/tests/fs/readFile.test.ts +8 -24
- package/tests/fs/rename.test.ts +4 -9
- package/tests/fs/stat.test.ts +2 -2
- package/tests/fs/times.test.ts +6 -6
- package/tests/fs/truncate.test.ts +8 -36
- package/tests/fs/watch.test.ts +10 -10
- package/tests/fs/write.test.ts +77 -13
- package/tests/fs/xattr.test.ts +7 -7
- package/tests/logs.js +2 -2
- package/tests/setup/port.ts +6 -0
- package/dist/internal/log.d.ts +0 -139
- package/dist/internal/log.js +0 -219
- package/tests/fs/writeFile.test.ts +0 -70
package/tests/fs/write.test.ts
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path/posix';
|
|
2
4
|
import { suite, test } from 'node:test';
|
|
3
5
|
import { fs } from '../common.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
import { data as dataPath } from '../setup.js';
|
|
7
|
+
|
|
8
|
+
const fileName = 'write.txt';
|
|
9
|
+
const utf8example = readFileSync(join(dataPath, 'utf8.txt'), 'utf8');
|
|
10
|
+
|
|
11
|
+
suite('Writes', () => {
|
|
12
|
+
test('Using FileHandle and UTF-8', async () => {
|
|
7
13
|
const expected = 'ümlaut.';
|
|
8
14
|
|
|
9
|
-
const handle = await fs.promises.open(
|
|
15
|
+
const handle = await fs.promises.open(fileName, 'w', 0o644);
|
|
10
16
|
await handle.write('', 0, 'utf8');
|
|
11
17
|
const { bytesWritten } = await handle.write(expected, 0, 'utf8');
|
|
12
18
|
assert.equal(bytesWritten, Buffer.from(expected).length);
|
|
13
19
|
await handle.close();
|
|
14
20
|
|
|
15
|
-
const data = await fs.promises.readFile(
|
|
21
|
+
const data = await fs.promises.readFile(fileName, 'utf8');
|
|
16
22
|
assert.equal(data, expected);
|
|
17
23
|
|
|
18
|
-
await fs.promises.unlink(
|
|
24
|
+
await fs.promises.unlink(fileName);
|
|
19
25
|
});
|
|
20
26
|
|
|
21
|
-
test('
|
|
27
|
+
test('Using FileHandle with buffer', async () => {
|
|
22
28
|
const expected = Buffer.from('hello');
|
|
23
29
|
|
|
24
|
-
const handle = await fs.promises.open(
|
|
30
|
+
const handle = await fs.promises.open(fileName, 'w', 0o644);
|
|
25
31
|
|
|
26
32
|
const written = await handle.write(expected, 0, expected.length, null);
|
|
27
33
|
|
|
@@ -29,13 +35,13 @@ suite('write', () => {
|
|
|
29
35
|
|
|
30
36
|
await handle.close();
|
|
31
37
|
|
|
32
|
-
assert.deepEqual(await fs.promises.readFile(
|
|
38
|
+
assert.deepEqual(await fs.promises.readFile(fileName), expected);
|
|
33
39
|
|
|
34
|
-
await fs.promises.unlink(
|
|
40
|
+
await fs.promises.unlink(fileName);
|
|
35
41
|
});
|
|
36
42
|
|
|
37
|
-
test('
|
|
38
|
-
const fd = fs.openSync(
|
|
43
|
+
test('Using sync path functions', () => {
|
|
44
|
+
const fd = fs.openSync(fileName, 'w');
|
|
39
45
|
|
|
40
46
|
let written = fs.writeSync(fd, '');
|
|
41
47
|
assert.equal(written, 0);
|
|
@@ -48,6 +54,64 @@ suite('write', () => {
|
|
|
48
54
|
|
|
49
55
|
fs.closeSync(fd);
|
|
50
56
|
|
|
51
|
-
assert.equal(fs.readFileSync(
|
|
57
|
+
assert.equal(fs.readFileSync(fileName, 'utf8'), 'foobár');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('Using promises API', async () => {
|
|
61
|
+
const filename = 'test.txt';
|
|
62
|
+
await fs.promises.writeFile(filename, utf8example);
|
|
63
|
+
const data = await fs.promises.readFile(filename);
|
|
64
|
+
assert.equal(data.length, Buffer.from(utf8example).length);
|
|
65
|
+
await fs.promises.unlink(filename);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('Using promises API with buffer', async () => {
|
|
69
|
+
const filename = 'test2.txt';
|
|
70
|
+
const expected = Buffer.from(utf8example, 'utf8');
|
|
71
|
+
|
|
72
|
+
await fs.promises.writeFile(filename, expected);
|
|
73
|
+
const actual = await fs.promises.readFile(filename);
|
|
74
|
+
assert.equal(actual.length, expected.length);
|
|
75
|
+
|
|
76
|
+
await fs.promises.unlink(filename);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('Promises API with base64 data', async () => {
|
|
80
|
+
const data = readFileSync(join(dataPath, 'image.jpg'), 'base64');
|
|
81
|
+
|
|
82
|
+
const buffer = Buffer.from(data, 'base64');
|
|
83
|
+
const filePath = 'test.jpg';
|
|
84
|
+
|
|
85
|
+
await fs.promises.writeFile(filePath, buffer);
|
|
86
|
+
|
|
87
|
+
const read = await fs.promises.readFile(filePath, 'base64');
|
|
88
|
+
assert.equal(read, data);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('Using sync path functions with custom mode', () => {
|
|
92
|
+
const file = 'testWriteFileSync.txt';
|
|
93
|
+
const mode = 0o755;
|
|
94
|
+
|
|
95
|
+
fs.writeFileSync(file, '123', { mode });
|
|
96
|
+
|
|
97
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
98
|
+
assert.equal(content, '123');
|
|
99
|
+
assert.equal(fs.statSync(file).mode & 0o777, mode);
|
|
100
|
+
|
|
101
|
+
fs.unlinkSync(file);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('Appending to a file synchronously with custom mode', () => {
|
|
105
|
+
const file = 'testAppendFileSync.txt';
|
|
106
|
+
const mode = 0o755;
|
|
107
|
+
|
|
108
|
+
fs.appendFileSync(file, 'abc', { mode });
|
|
109
|
+
|
|
110
|
+
const content = fs.readFileSync(file, { encoding: 'utf8' });
|
|
111
|
+
assert.equal(content, 'abc');
|
|
112
|
+
|
|
113
|
+
assert.equal(fs.statSync(file).mode & 0o777, mode);
|
|
114
|
+
|
|
115
|
+
fs.unlinkSync(file);
|
|
52
116
|
});
|
|
53
117
|
});
|
package/tests/fs/xattr.test.ts
CHANGED
|
@@ -11,8 +11,8 @@ suite('Extended Attributes', () => {
|
|
|
11
11
|
test.before(() => fs.promises.writeFile(testFile, 'test content'));
|
|
12
12
|
test.after(() => fs.promises.unlink(testFile));
|
|
13
13
|
|
|
14
|
-
test('Non-user attribute set fails', () => {
|
|
15
|
-
assert.rejects(fs.xattr.set(testFile, 'system.test', 'value'), { code: '
|
|
14
|
+
test('Non-user attribute set fails', async () => {
|
|
15
|
+
await assert.rejects(fs.xattr.set(testFile, 'system.test', 'value'), { code: 'ENOTSUP' });
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
test('set and get attributes', async () => {
|
|
@@ -32,7 +32,7 @@ suite('Extended Attributes', () => {
|
|
|
32
32
|
await fs.xattr.set(testFile, 'user.to-remove', testValue);
|
|
33
33
|
await fs.xattr.remove(testFile, 'user.to-remove');
|
|
34
34
|
|
|
35
|
-
assert.rejects(fs.xattr.get(testFile, 'user.to-remove', { encoding: 'utf8' }), { code: 'ENODATA' });
|
|
35
|
+
await assert.rejects(fs.xattr.get(testFile, 'user.to-remove', { encoding: 'utf8' }), { code: 'ENODATA' });
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
test('list attributes', async () => {
|
|
@@ -49,17 +49,17 @@ suite('Extended Attributes', () => {
|
|
|
49
49
|
|
|
50
50
|
await fs.xattr.set(testFile, flagTestName, 'original', { create: true });
|
|
51
51
|
|
|
52
|
-
assert.rejects(fs.xattr.set(testFile, flagTestName, 'new value', { create: true }), { code: 'EEXIST' });
|
|
52
|
+
await assert.rejects(fs.xattr.set(testFile, flagTestName, 'new value', { create: true }), { code: 'EEXIST' });
|
|
53
53
|
|
|
54
54
|
await fs.xattr.set(testFile, flagTestName, 'updated', { replace: true });
|
|
55
55
|
const value = await fs.xattr.get(testFile, flagTestName, { encoding: 'utf8' });
|
|
56
56
|
assert.equal(value, 'updated');
|
|
57
57
|
|
|
58
|
-
assert.rejects(fs.xattr.set(testFile, 'user.nonexistent', 'value', { replace: true }), { code: 'ENODATA' });
|
|
58
|
+
await assert.rejects(fs.xattr.set(testFile, 'user.nonexistent', 'value', { replace: true }), { code: 'ENODATA' });
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
test('file must exist', () => {
|
|
62
|
-
assert.rejects(fs.xattr.set('nonexistent-file.txt', testName, 'value'), { code: 'ENOENT' });
|
|
61
|
+
test('file must exist', async () => {
|
|
62
|
+
await assert.rejects(fs.xattr.set('nonexistent-file.txt', testName, 'value'), { code: 'ENOENT' });
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
test('synchronous operations', () => {
|
package/tests/logs.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { log } from 'kerium';
|
|
2
2
|
|
|
3
3
|
export function setupLogs(prefix) {
|
|
4
4
|
const { ZENFS_LOG_LEVEL } = process.env;
|
|
5
5
|
|
|
6
|
-
let level = log.Level.
|
|
6
|
+
let level = log.Level.ERR;
|
|
7
7
|
|
|
8
8
|
if (ZENFS_LOG_LEVEL) {
|
|
9
9
|
const tmp = parseInt(ZENFS_LOG_LEVEL);
|
package/tests/setup/port.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { after } from 'node:test';
|
|
1
2
|
import { MessageChannel } from 'node:worker_threads';
|
|
2
3
|
import { InMemory, Port, configureSingle, fs, resolveMountConfig, resolveRemoteMount } from '../../dist/index.js';
|
|
3
4
|
import { copySync, data } from '../setup.js';
|
|
@@ -13,3 +14,8 @@ copySync(data, fs);
|
|
|
13
14
|
await resolveRemoteMount(remotePort, tmpfs);
|
|
14
15
|
|
|
15
16
|
await configureSingle({ backend: Port, port: localPort });
|
|
17
|
+
|
|
18
|
+
after(() => {
|
|
19
|
+
localPort.close();
|
|
20
|
+
remotePort.close();
|
|
21
|
+
});
|
package/dist/internal/log.d.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { List } from 'utilium';
|
|
2
|
-
import { ErrnoError } from './error.js';
|
|
3
|
-
import type { FileSystem } from './filesystem.js';
|
|
4
|
-
export declare const enum Level {
|
|
5
|
-
/** Emergency */
|
|
6
|
-
EMERG = 0,
|
|
7
|
-
/** Alert */
|
|
8
|
-
ALERT = 1,
|
|
9
|
-
/** Critical */
|
|
10
|
-
CRIT = 2,
|
|
11
|
-
/** Error */
|
|
12
|
-
ERR = 3,
|
|
13
|
-
/** Warning */
|
|
14
|
-
WARN = 4,
|
|
15
|
-
/** Notice */
|
|
16
|
-
NOTICE = 5,
|
|
17
|
-
/** Informational */
|
|
18
|
-
INFO = 6,
|
|
19
|
-
/** Debug */
|
|
20
|
-
DEBUG = 7
|
|
21
|
-
}
|
|
22
|
-
/** An object mapping log levels to a textual representation of them */
|
|
23
|
-
export declare const levels: {
|
|
24
|
-
readonly 0: "emergency";
|
|
25
|
-
readonly 1: "alert";
|
|
26
|
-
readonly 2: "critical";
|
|
27
|
-
readonly 3: "error";
|
|
28
|
-
readonly 4: "warning";
|
|
29
|
-
readonly 5: "notice";
|
|
30
|
-
readonly 6: "info";
|
|
31
|
-
readonly 7: "debug";
|
|
32
|
-
};
|
|
33
|
-
export declare function levelOf(value: (typeof levels)[Level]): Level;
|
|
34
|
-
/** A log entry */
|
|
35
|
-
export interface Entry {
|
|
36
|
-
level: Level;
|
|
37
|
-
timestamp: Date;
|
|
38
|
-
elapsedMs: number;
|
|
39
|
-
message: string;
|
|
40
|
-
}
|
|
41
|
-
/** The list of log entries */
|
|
42
|
-
export declare const entries: List<Entry>;
|
|
43
|
-
export declare function log(level: Level, message: string): void;
|
|
44
|
-
interface LogShortcutOptions {
|
|
45
|
-
fs?: FileSystem;
|
|
46
|
-
}
|
|
47
|
-
/** Shortcut for logging emergencies */
|
|
48
|
-
export declare const emerg: <T extends {
|
|
49
|
-
toString(): string;
|
|
50
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
51
|
-
/** Shortcut for logging alerts */
|
|
52
|
-
export declare const alert: <T extends {
|
|
53
|
-
toString(): string;
|
|
54
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
55
|
-
/** Shortcut for logging critical errors */
|
|
56
|
-
export declare const crit: <T extends {
|
|
57
|
-
toString(): string;
|
|
58
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
59
|
-
/** Shortcut for logging non-critical errors */
|
|
60
|
-
export declare const err: <T extends {
|
|
61
|
-
toString(): string;
|
|
62
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
63
|
-
/** Shortcut for logging warnings */
|
|
64
|
-
export declare const warn: <T extends {
|
|
65
|
-
toString(): string;
|
|
66
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
67
|
-
/** Shortcut for logging notices */
|
|
68
|
-
export declare const notice: <T extends {
|
|
69
|
-
toString(): string;
|
|
70
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
71
|
-
/** Shortcut for logging informational messages */
|
|
72
|
-
export declare const info: <T extends {
|
|
73
|
-
toString(): string;
|
|
74
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
75
|
-
/** Shortcut for logging debug messages */
|
|
76
|
-
export declare const debug: <T extends {
|
|
77
|
-
toString(): string;
|
|
78
|
-
} | ErrnoError>(message: T, options?: LogShortcutOptions) => T;
|
|
79
|
-
/**
|
|
80
|
-
* Shortcut for logging usage of deprecated functions at runtime
|
|
81
|
-
* @param symbol The thing that is deprecated
|
|
82
|
-
* @internal @hidden
|
|
83
|
-
*/
|
|
84
|
-
export declare function log_deprecated(symbol: string): void;
|
|
85
|
-
export interface FormatOptions {
|
|
86
|
-
/**
|
|
87
|
-
* Whether to use ANSI escape codes (e.g. for Xterm) or CSS (for browsers) to colorize the log
|
|
88
|
-
*/
|
|
89
|
-
style: 'ansi' | 'css';
|
|
90
|
-
/**
|
|
91
|
-
* How to colorize the message:
|
|
92
|
-
* - `level`: Colorize the level.
|
|
93
|
-
* - `message`: Colorize the message. For EMERG and ALERT, the level is also included.
|
|
94
|
-
*/
|
|
95
|
-
colorize: 'level' | 'message';
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Various format functions included to make using the logger easier.
|
|
99
|
-
* These are not the only formats you can use.
|
|
100
|
-
*/
|
|
101
|
-
export declare function fancy({ style, colorize }: FormatOptions): (entry: Entry) => Generator<string, void, unknown>;
|
|
102
|
-
export declare function format(entry: Entry): string[];
|
|
103
|
-
/** Whether log entries are being recorded */
|
|
104
|
-
export declare let isEnabled: boolean;
|
|
105
|
-
export interface LogConfiguration {
|
|
106
|
-
/**
|
|
107
|
-
* If false, log messages will not be recorded or outputted
|
|
108
|
-
* @default false
|
|
109
|
-
*/
|
|
110
|
-
enabled?: boolean;
|
|
111
|
-
/**
|
|
112
|
-
* The minimum level needed to output a message
|
|
113
|
-
* @default Level.ALERT
|
|
114
|
-
*/
|
|
115
|
-
level?: Level | (typeof levels)[Level];
|
|
116
|
-
/**
|
|
117
|
-
* Whether to include stack traces.
|
|
118
|
-
* @default false
|
|
119
|
-
*/
|
|
120
|
-
stack?: boolean;
|
|
121
|
-
/**
|
|
122
|
-
* Formats a log entry into a string
|
|
123
|
-
* @default `[${ms / 1000}] ${message}`
|
|
124
|
-
*/
|
|
125
|
-
format?(this: void, entry: Entry): string | Iterable<string>;
|
|
126
|
-
/**
|
|
127
|
-
* Outputs a log message
|
|
128
|
-
* @default console.error()
|
|
129
|
-
*/
|
|
130
|
-
output?(this: void, ...message: string[]): unknown;
|
|
131
|
-
/**
|
|
132
|
-
* If set, output() all current entries after `configure` is done
|
|
133
|
-
* @default false
|
|
134
|
-
*/
|
|
135
|
-
dumpBacklog?: boolean;
|
|
136
|
-
}
|
|
137
|
-
/** Configure logging behavior */
|
|
138
|
-
export declare function configure(options: LogConfiguration): void;
|
|
139
|
-
export {};
|
package/dist/internal/log.js
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/* Logging utilities. The things in this file are named to work nicely when you import as a namespace. */
|
|
2
|
-
import { List } from 'utilium';
|
|
3
|
-
import { join } from '../path.js';
|
|
4
|
-
import { ErrnoError } from './error.js';
|
|
5
|
-
export var Level;
|
|
6
|
-
(function (Level) {
|
|
7
|
-
/** Emergency */
|
|
8
|
-
Level[Level["EMERG"] = 0] = "EMERG";
|
|
9
|
-
/** Alert */
|
|
10
|
-
Level[Level["ALERT"] = 1] = "ALERT";
|
|
11
|
-
/** Critical */
|
|
12
|
-
Level[Level["CRIT"] = 2] = "CRIT";
|
|
13
|
-
/** Error */
|
|
14
|
-
Level[Level["ERR"] = 3] = "ERR";
|
|
15
|
-
/** Warning */
|
|
16
|
-
Level[Level["WARN"] = 4] = "WARN";
|
|
17
|
-
/** Notice */
|
|
18
|
-
Level[Level["NOTICE"] = 5] = "NOTICE";
|
|
19
|
-
/** Informational */
|
|
20
|
-
Level[Level["INFO"] = 6] = "INFO";
|
|
21
|
-
/** Debug */
|
|
22
|
-
Level[Level["DEBUG"] = 7] = "DEBUG";
|
|
23
|
-
})(Level || (Level = {}));
|
|
24
|
-
/** An object mapping log levels to a textual representation of them */
|
|
25
|
-
export const levels = {
|
|
26
|
-
[Level.EMERG]: 'emergency',
|
|
27
|
-
[Level.ALERT]: 'alert',
|
|
28
|
-
[Level.CRIT]: 'critical',
|
|
29
|
-
[Level.ERR]: 'error',
|
|
30
|
-
[Level.WARN]: 'warning',
|
|
31
|
-
[Level.NOTICE]: 'notice',
|
|
32
|
-
[Level.INFO]: 'info',
|
|
33
|
-
[Level.DEBUG]: 'debug',
|
|
34
|
-
};
|
|
35
|
-
export function levelOf(value) {
|
|
36
|
-
return Object.values(levels).indexOf(value);
|
|
37
|
-
}
|
|
38
|
-
/** The list of log entries */
|
|
39
|
-
export const entries = new List();
|
|
40
|
-
export function log(level, message) {
|
|
41
|
-
if (!isEnabled)
|
|
42
|
-
return;
|
|
43
|
-
const entry = {
|
|
44
|
-
level,
|
|
45
|
-
message,
|
|
46
|
-
timestamp: new Date(),
|
|
47
|
-
elapsedMs: performance.now(),
|
|
48
|
-
};
|
|
49
|
-
entries.add(entry);
|
|
50
|
-
output(entry);
|
|
51
|
-
}
|
|
52
|
-
function _messageString(msg, options) {
|
|
53
|
-
var _a, _b;
|
|
54
|
-
if (!(msg instanceof ErrnoError))
|
|
55
|
-
return msg.toString();
|
|
56
|
-
const beforePath = msg.code + ': ' + msg.message;
|
|
57
|
-
if (!msg.path)
|
|
58
|
-
return beforePath;
|
|
59
|
-
const mountPoint = typeof options.fs == 'string' ? options.fs : ((_b = (_a = options.fs) === null || _a === void 0 ? void 0 : _a._mountPoint) !== null && _b !== void 0 ? _b : '<unknown>');
|
|
60
|
-
return (beforePath
|
|
61
|
-
+ ': '
|
|
62
|
-
+ join(mountPoint, msg.path)
|
|
63
|
-
+ (includeStack
|
|
64
|
-
? '\n'
|
|
65
|
-
+ msg.stack
|
|
66
|
-
.split('\n')
|
|
67
|
-
.map(line => '\t' + line)
|
|
68
|
-
.slice(1)
|
|
69
|
-
.join('\n')
|
|
70
|
-
: ''));
|
|
71
|
-
}
|
|
72
|
-
function _shortcut(level) {
|
|
73
|
-
return function (message, options = {}) {
|
|
74
|
-
log(level, _messageString(message, options));
|
|
75
|
-
return message;
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
// Shortcuts
|
|
79
|
-
/** Shortcut for logging emergencies */
|
|
80
|
-
export const emerg = _shortcut(Level.EMERG);
|
|
81
|
-
/** Shortcut for logging alerts */
|
|
82
|
-
export const alert = _shortcut(Level.ALERT);
|
|
83
|
-
/** Shortcut for logging critical errors */
|
|
84
|
-
export const crit = _shortcut(Level.CRIT);
|
|
85
|
-
/** Shortcut for logging non-critical errors */
|
|
86
|
-
export const err = _shortcut(Level.ERR);
|
|
87
|
-
/** Shortcut for logging warnings */
|
|
88
|
-
export const warn = _shortcut(Level.WARN);
|
|
89
|
-
/** Shortcut for logging notices */
|
|
90
|
-
export const notice = _shortcut(Level.NOTICE);
|
|
91
|
-
/** Shortcut for logging informational messages */
|
|
92
|
-
export const info = _shortcut(Level.INFO);
|
|
93
|
-
/** Shortcut for logging debug messages */
|
|
94
|
-
export const debug = _shortcut(Level.DEBUG);
|
|
95
|
-
/**
|
|
96
|
-
* Shortcut for logging usage of deprecated functions at runtime
|
|
97
|
-
* @param symbol The thing that is deprecated
|
|
98
|
-
* @internal @hidden
|
|
99
|
-
*/
|
|
100
|
-
export function log_deprecated(symbol) {
|
|
101
|
-
log(Level.WARN, symbol + ' is deprecated and should not be used.');
|
|
102
|
-
}
|
|
103
|
-
// Formatting and output
|
|
104
|
-
/**
|
|
105
|
-
* @internal @hidden
|
|
106
|
-
*/
|
|
107
|
-
function ansi(text, format) {
|
|
108
|
-
return `\x1b[${format}m${text}\x1b[0m`;
|
|
109
|
-
}
|
|
110
|
-
function _prettyMs(entry, style) {
|
|
111
|
-
const text = '[' + (entry.elapsedMs / 1000).toFixed(3).padStart(10) + '] ';
|
|
112
|
-
switch (style) {
|
|
113
|
-
case 'ansi':
|
|
114
|
-
return [ansi(text, '2;37')];
|
|
115
|
-
case 'css':
|
|
116
|
-
return ['%c' + text, 'opacity: 0.8; color: white;'];
|
|
117
|
-
default:
|
|
118
|
-
return [text];
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
const levelColor = {
|
|
122
|
-
ansi: {
|
|
123
|
-
[Level.EMERG]: '1;4;37;41',
|
|
124
|
-
[Level.ALERT]: '1;37;41',
|
|
125
|
-
[Level.CRIT]: '1;35',
|
|
126
|
-
[Level.ERR]: '1;31',
|
|
127
|
-
[Level.WARN]: '1;33',
|
|
128
|
-
[Level.NOTICE]: '1;36',
|
|
129
|
-
[Level.INFO]: '1;37',
|
|
130
|
-
[Level.DEBUG]: '0;2;37',
|
|
131
|
-
},
|
|
132
|
-
css: {
|
|
133
|
-
[Level.EMERG]: 'font-weight: bold; text-decoration: underline; color: white; background-color: red;',
|
|
134
|
-
[Level.ALERT]: 'font-weight: bold; color: white; background-color: red;',
|
|
135
|
-
[Level.CRIT]: 'font-weight: bold; color: magenta;',
|
|
136
|
-
[Level.ERR]: 'font-weight: bold; color: red;',
|
|
137
|
-
[Level.WARN]: 'font-weight: bold; color: yellow;',
|
|
138
|
-
[Level.NOTICE]: 'font-weight: bold; color: cyan;',
|
|
139
|
-
[Level.INFO]: 'font-weight: bold; color: white;',
|
|
140
|
-
[Level.DEBUG]: 'opacity: 0.8; color: white;',
|
|
141
|
-
},
|
|
142
|
-
};
|
|
143
|
-
const messageColor = {
|
|
144
|
-
ansi: {
|
|
145
|
-
[Level.EMERG]: '1;31',
|
|
146
|
-
[Level.ALERT]: '1;31',
|
|
147
|
-
[Level.CRIT]: '1;31',
|
|
148
|
-
[Level.ERR]: '31',
|
|
149
|
-
[Level.WARN]: '33',
|
|
150
|
-
[Level.NOTICE]: '1;37',
|
|
151
|
-
[Level.INFO]: '37',
|
|
152
|
-
[Level.DEBUG]: '2;37',
|
|
153
|
-
},
|
|
154
|
-
css: {
|
|
155
|
-
[Level.EMERG]: 'font-weight: bold; color: red;',
|
|
156
|
-
[Level.ALERT]: 'font-weight: bold; color: red;',
|
|
157
|
-
[Level.CRIT]: 'font-weight: bold; color: red;',
|
|
158
|
-
[Level.ERR]: 'color: red;',
|
|
159
|
-
[Level.WARN]: 'color: yellow;',
|
|
160
|
-
[Level.NOTICE]: 'font-weight: bold; color: white;',
|
|
161
|
-
[Level.INFO]: 'color: white;',
|
|
162
|
-
[Level.DEBUG]: 'opacity: 0.8; color: white;',
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
/**
|
|
166
|
-
* Various format functions included to make using the logger easier.
|
|
167
|
-
* These are not the only formats you can use.
|
|
168
|
-
*/
|
|
169
|
-
export function fancy({ style, colorize }) {
|
|
170
|
-
return function* (entry) {
|
|
171
|
-
yield* _prettyMs(entry, style);
|
|
172
|
-
const levelText = style == 'ansi'
|
|
173
|
-
? [ansi(levels[entry.level].toUpperCase(), levelColor.ansi[entry.level])]
|
|
174
|
-
: ['%c' + levels[entry.level].toUpperCase(), levelColor.css[entry.level]];
|
|
175
|
-
if (colorize == 'level') {
|
|
176
|
-
yield* levelText;
|
|
177
|
-
yield entry.message;
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
if (entry.level < Level.CRIT) {
|
|
181
|
-
yield* levelText;
|
|
182
|
-
yield ': ';
|
|
183
|
-
}
|
|
184
|
-
if (colorize == 'message')
|
|
185
|
-
yield ansi(entry.message, messageColor.ansi[entry.level]);
|
|
186
|
-
else
|
|
187
|
-
yield* ['%c' + entry.message, messageColor.css[entry.level]];
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
let _format = (entry) => [..._prettyMs(entry), entry.message];
|
|
191
|
-
export function format(entry) {
|
|
192
|
-
const formatted = _format(entry);
|
|
193
|
-
return typeof formatted == 'string' ? [formatted] : Array.from(formatted);
|
|
194
|
-
}
|
|
195
|
-
let _output = console.error;
|
|
196
|
-
function output(entry) {
|
|
197
|
-
if (entry.level > minLevel)
|
|
198
|
-
return;
|
|
199
|
-
_output(...format(entry));
|
|
200
|
-
}
|
|
201
|
-
let minLevel = Level.ALERT;
|
|
202
|
-
let includeStack = false;
|
|
203
|
-
// Configuration
|
|
204
|
-
/** Whether log entries are being recorded */
|
|
205
|
-
export let isEnabled = true;
|
|
206
|
-
/** Configure logging behavior */
|
|
207
|
-
export function configure(options) {
|
|
208
|
-
var _a, _b, _c, _d, _e;
|
|
209
|
-
_format = (_a = options.format) !== null && _a !== void 0 ? _a : _format;
|
|
210
|
-
_output = (_b = options.output) !== null && _b !== void 0 ? _b : _output;
|
|
211
|
-
minLevel = typeof options.level == 'string' ? levelOf(options.level) : ((_c = options.level) !== null && _c !== void 0 ? _c : minLevel);
|
|
212
|
-
isEnabled = (_d = options.enabled) !== null && _d !== void 0 ? _d : isEnabled;
|
|
213
|
-
includeStack = (_e = options.stack) !== null && _e !== void 0 ? _e : includeStack;
|
|
214
|
-
if (!options.dumpBacklog)
|
|
215
|
-
return;
|
|
216
|
-
for (const entry of entries) {
|
|
217
|
-
output(entry);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { suite, test } from 'node:test';
|
|
3
|
-
import { readFileSync } from 'node:fs';
|
|
4
|
-
import { fs } from '../common.js';
|
|
5
|
-
import { join } from 'node:path/posix';
|
|
6
|
-
import { data as dataPath } from '../setup.js';
|
|
7
|
-
|
|
8
|
-
const utf8example = readFileSync(join(dataPath, 'utf8.txt'), 'utf8');
|
|
9
|
-
|
|
10
|
-
suite('writeFile', () => {
|
|
11
|
-
test('write and read file with specified content', async () => {
|
|
12
|
-
const filename = 'test.txt';
|
|
13
|
-
await fs.promises.writeFile(filename, utf8example);
|
|
14
|
-
const data = await fs.promises.readFile(filename);
|
|
15
|
-
assert.equal(data.length, Buffer.from(utf8example).length);
|
|
16
|
-
await fs.promises.unlink(filename);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test('write and read file using buffer', async () => {
|
|
20
|
-
const filename = 'test2.txt';
|
|
21
|
-
const expected = Buffer.from(utf8example, 'utf8');
|
|
22
|
-
|
|
23
|
-
await fs.promises.writeFile(filename, expected);
|
|
24
|
-
const actual = await fs.promises.readFile(filename);
|
|
25
|
-
assert.equal(actual.length, expected.length);
|
|
26
|
-
|
|
27
|
-
await fs.promises.unlink(filename);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('write base64 data to a file and read it back asynchronously', async () => {
|
|
31
|
-
const data = readFileSync(join(dataPath, 'image.jpg'), 'base64');
|
|
32
|
-
|
|
33
|
-
const buffer = Buffer.from(data, 'base64');
|
|
34
|
-
const filePath = 'test.jpg';
|
|
35
|
-
|
|
36
|
-
await fs.promises.writeFile(filePath, buffer);
|
|
37
|
-
|
|
38
|
-
const read = await fs.promises.readFile(filePath, 'base64');
|
|
39
|
-
assert.equal(read, data);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
suite('File Writing with Custom Mode', () => {
|
|
44
|
-
test('write file synchronously with custom mode', () => {
|
|
45
|
-
const file = 'testWriteFileSync.txt';
|
|
46
|
-
const mode = 0o755;
|
|
47
|
-
|
|
48
|
-
fs.writeFileSync(file, '123', { mode });
|
|
49
|
-
|
|
50
|
-
const content = fs.readFileSync(file, 'utf8');
|
|
51
|
-
assert.equal(content, '123');
|
|
52
|
-
assert((fs.statSync(file).mode & 0o777) === mode);
|
|
53
|
-
|
|
54
|
-
fs.unlinkSync(file);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('append to a file synchronously with custom mode', () => {
|
|
58
|
-
const file = 'testAppendFileSync.txt';
|
|
59
|
-
const mode = 0o755;
|
|
60
|
-
|
|
61
|
-
fs.appendFileSync(file, 'abc', { mode });
|
|
62
|
-
|
|
63
|
-
const content = fs.readFileSync(file, { encoding: 'utf8' });
|
|
64
|
-
assert.equal(content, 'abc');
|
|
65
|
-
|
|
66
|
-
assert((fs.statSync(file).mode & 0o777) === mode);
|
|
67
|
-
|
|
68
|
-
fs.unlinkSync(file);
|
|
69
|
-
});
|
|
70
|
-
});
|