@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.
Files changed (87) hide show
  1. package/dist/backends/backend.js +6 -5
  2. package/dist/backends/cow.d.ts +2 -2
  3. package/dist/backends/cow.js +39 -58
  4. package/dist/backends/fetch.js +27 -29
  5. package/dist/backends/passthrough.d.ts +2 -3
  6. package/dist/backends/passthrough.js +84 -199
  7. package/dist/backends/port.d.ts +16 -3
  8. package/dist/backends/port.js +61 -30
  9. package/dist/backends/single_buffer.d.ts +52 -46
  10. package/dist/backends/single_buffer.js +462 -219
  11. package/dist/backends/store/fs.d.ts +16 -10
  12. package/dist/backends/store/fs.js +227 -242
  13. package/dist/backends/store/store.d.ts +3 -3
  14. package/dist/backends/store/store.js +11 -10
  15. package/dist/config.d.ts +2 -2
  16. package/dist/config.js +10 -11
  17. package/dist/internal/devices.d.ts +2 -2
  18. package/dist/internal/devices.js +39 -49
  19. package/dist/internal/error.d.ts +9 -204
  20. package/dist/internal/error.js +19 -288
  21. package/dist/internal/file_index.d.ts +1 -1
  22. package/dist/internal/file_index.js +9 -9
  23. package/dist/internal/filesystem.d.ts +23 -8
  24. package/dist/internal/index.d.ts +1 -1
  25. package/dist/internal/index.js +1 -1
  26. package/dist/internal/index_fs.d.ts +2 -2
  27. package/dist/internal/index_fs.js +19 -19
  28. package/dist/internal/inode.d.ts +81 -103
  29. package/dist/internal/inode.js +336 -195
  30. package/dist/mixins/async.js +32 -28
  31. package/dist/mixins/mutexed.d.ts +4 -4
  32. package/dist/mixins/mutexed.js +39 -39
  33. package/dist/mixins/readonly.d.ts +2 -2
  34. package/dist/mixins/readonly.js +20 -20
  35. package/dist/mixins/sync.js +2 -2
  36. package/dist/polyfills.js +1 -1
  37. package/dist/readline.js +1 -1
  38. package/dist/utils.d.ts +8 -5
  39. package/dist/utils.js +14 -17
  40. package/dist/vfs/acl.d.ts +8 -8
  41. package/dist/vfs/acl.js +66 -47
  42. package/dist/vfs/async.d.ts +2 -2
  43. package/dist/vfs/async.js +6 -8
  44. package/dist/vfs/dir.d.ts +1 -1
  45. package/dist/vfs/dir.js +3 -4
  46. package/dist/vfs/file.js +33 -24
  47. package/dist/vfs/flags.js +3 -3
  48. package/dist/vfs/ioctl.d.ts +8 -7
  49. package/dist/vfs/ioctl.js +132 -27
  50. package/dist/vfs/promises.d.ts +3 -3
  51. package/dist/vfs/promises.js +200 -235
  52. package/dist/vfs/shared.d.ts +1 -12
  53. package/dist/vfs/shared.js +7 -35
  54. package/dist/vfs/streams.js +9 -9
  55. package/dist/vfs/sync.d.ts +1 -2
  56. package/dist/vfs/sync.js +158 -170
  57. package/dist/vfs/watchers.js +8 -8
  58. package/dist/vfs/xattr.js +89 -106
  59. package/package.json +4 -2
  60. package/scripts/test.js +2 -2
  61. package/tests/assignment.ts +1 -1
  62. package/tests/backend/port.test.ts +4 -4
  63. package/tests/backend/single-buffer.test.ts +39 -10
  64. package/tests/backend/single-buffer.worker.js +30 -0
  65. package/tests/common/context.test.ts +2 -2
  66. package/tests/common/mutex.test.ts +9 -9
  67. package/tests/fetch/fetch.ts +1 -1
  68. package/tests/fs/append.test.ts +4 -4
  69. package/tests/fs/directory.test.ts +25 -25
  70. package/tests/fs/errors.test.ts +15 -19
  71. package/tests/fs/links.test.ts +3 -2
  72. package/tests/fs/open.test.ts +4 -21
  73. package/tests/fs/permissions.test.ts +8 -13
  74. package/tests/fs/read.test.ts +10 -9
  75. package/tests/fs/readFile.test.ts +8 -24
  76. package/tests/fs/rename.test.ts +4 -9
  77. package/tests/fs/stat.test.ts +2 -2
  78. package/tests/fs/times.test.ts +6 -6
  79. package/tests/fs/truncate.test.ts +8 -36
  80. package/tests/fs/watch.test.ts +10 -10
  81. package/tests/fs/write.test.ts +77 -13
  82. package/tests/fs/xattr.test.ts +7 -7
  83. package/tests/logs.js +2 -2
  84. package/tests/setup/port.ts +6 -0
  85. package/dist/internal/log.d.ts +0 -139
  86. package/dist/internal/log.js +0 -219
  87. package/tests/fs/writeFile.test.ts +0 -70
@@ -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
- const fn = 'write.txt';
5
- suite('write', () => {
6
- test('write file with specified content', async () => {
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(fn, 'w', 0o644);
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(fn, 'utf8');
21
+ const data = await fs.promises.readFile(fileName, 'utf8');
16
22
  assert.equal(data, expected);
17
23
 
18
- await fs.promises.unlink(fn);
24
+ await fs.promises.unlink(fileName);
19
25
  });
20
26
 
21
- test('write a buffer to a file', async () => {
27
+ test('Using FileHandle with buffer', async () => {
22
28
  const expected = Buffer.from('hello');
23
29
 
24
- const handle = await fs.promises.open(fn, 'w', 0o644);
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(fn), expected);
38
+ assert.deepEqual(await fs.promises.readFile(fileName), expected);
33
39
 
34
- await fs.promises.unlink(fn);
40
+ await fs.promises.unlink(fileName);
35
41
  });
36
42
 
37
- test('writeSync file with specified content', () => {
38
- const fd = fs.openSync(fn, 'w');
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(fn, 'utf8'), 'foobár');
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
  });
@@ -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: 'EPERM' });
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 * as log from '../dist/internal/log.js';
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.CRIT;
6
+ let level = log.Level.ERR;
7
7
 
8
8
  if (ZENFS_LOG_LEVEL) {
9
9
  const tmp = parseInt(ZENFS_LOG_LEVEL);
@@ -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
+ });
@@ -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 {};
@@ -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
- });