@simplysm/core-node 13.0.76 → 13.0.77
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 +353 -44
- package/dist/features/fs-watcher.d.ts.map +1 -1
- package/dist/features/fs-watcher.js +2 -2
- package/dist/features/fs-watcher.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/utils/fs.d.ts +30 -30
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +101 -99
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/path.d.ts +19 -19
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/path.js +17 -17
- package/dist/utils/path.js.map +1 -1
- package/dist/worker/create-worker.d.ts +1 -1
- package/dist/worker/create-worker.d.ts.map +1 -1
- package/dist/worker/create-worker.js +8 -8
- package/dist/worker/create-worker.js.map +1 -1
- package/dist/worker/types.d.ts +2 -2
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker.js +4 -4
- package/dist/worker/worker.js.map +1 -1
- package/package.json +2 -2
- package/src/features/fs-watcher.ts +2 -2
- package/src/index.ts +2 -2
- package/src/utils/fs.ts +570 -562
- package/src/utils/path.ts +24 -24
- package/src/worker/create-worker.ts +9 -9
- package/src/worker/types.ts +6 -6
- package/src/worker/worker.ts +4 -4
- package/tests/utils/fs.spec.ts +123 -123
- package/tests/utils/path.spec.ts +55 -55
package/tests/utils/fs.spec.ts
CHANGED
|
@@ -3,35 +3,35 @@ import path from "path";
|
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import os from "os";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
6
|
+
existsSync,
|
|
7
|
+
exists,
|
|
8
|
+
mkdirSync,
|
|
9
|
+
mkdir,
|
|
10
|
+
rmSync,
|
|
11
|
+
rm,
|
|
12
|
+
copySync,
|
|
13
|
+
copy,
|
|
14
|
+
readSync,
|
|
15
|
+
read,
|
|
16
|
+
readBufferSync,
|
|
17
|
+
readBuffer,
|
|
18
|
+
readJsonSync,
|
|
19
|
+
readJson,
|
|
20
|
+
writeSync,
|
|
21
|
+
write,
|
|
22
|
+
writeJsonSync,
|
|
23
|
+
writeJson,
|
|
24
|
+
readdirSync,
|
|
25
|
+
readdir,
|
|
26
|
+
statSync,
|
|
27
|
+
stat,
|
|
28
|
+
lstatSync,
|
|
29
|
+
lstat,
|
|
30
|
+
globSync,
|
|
31
|
+
glob,
|
|
32
|
+
clearEmptyDirectory,
|
|
33
|
+
findAllParentChildPathsSync,
|
|
34
|
+
findAllParentChildPaths,
|
|
35
35
|
} from "../../src/utils/fs";
|
|
36
36
|
import { SdError } from "@simplysm/core-common";
|
|
37
37
|
|
|
@@ -48,32 +48,32 @@ describe("fs functions", () => {
|
|
|
48
48
|
|
|
49
49
|
//#region exists
|
|
50
50
|
|
|
51
|
-
describe("
|
|
51
|
+
describe("existsSync", () => {
|
|
52
52
|
it("returns true for existing file", () => {
|
|
53
53
|
const filePath = path.join(testDir, "test.txt");
|
|
54
54
|
fs.writeFileSync(filePath, "test");
|
|
55
55
|
|
|
56
|
-
expect(
|
|
56
|
+
expect(existsSync(filePath)).toBe(true);
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
it("returns false for nonexistent file", () => {
|
|
60
60
|
const filePath = path.join(testDir, "nonexistent.txt");
|
|
61
|
-
expect(
|
|
61
|
+
expect(existsSync(filePath)).toBe(false);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
describe("
|
|
66
|
+
describe("exists", () => {
|
|
67
67
|
it("returns true for existing file", async () => {
|
|
68
68
|
const filePath = path.join(testDir, "test.txt");
|
|
69
69
|
fs.writeFileSync(filePath, "test");
|
|
70
70
|
|
|
71
|
-
expect(await
|
|
71
|
+
expect(await exists(filePath)).toBe(true);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
it("returns false for nonexistent file", async () => {
|
|
75
75
|
const filePath = path.join(testDir, "nonexistent.txt");
|
|
76
|
-
expect(await
|
|
76
|
+
expect(await exists(filePath)).toBe(false);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
});
|
|
@@ -82,10 +82,10 @@ describe("fs functions", () => {
|
|
|
82
82
|
|
|
83
83
|
//#region mkdir
|
|
84
84
|
|
|
85
|
-
describe("
|
|
85
|
+
describe("mkdirSync", () => {
|
|
86
86
|
it("creates directory", () => {
|
|
87
87
|
const dirPath = path.join(testDir, "newdir");
|
|
88
|
-
|
|
88
|
+
mkdirSync(dirPath);
|
|
89
89
|
|
|
90
90
|
expect(fs.existsSync(dirPath)).toBe(true);
|
|
91
91
|
expect(fs.statSync(dirPath).isDirectory()).toBe(true);
|
|
@@ -93,20 +93,20 @@ describe("fs functions", () => {
|
|
|
93
93
|
|
|
94
94
|
it("creates nested directories (recursive)", () => {
|
|
95
95
|
const dirPath = path.join(testDir, "a/b/c");
|
|
96
|
-
|
|
96
|
+
mkdirSync(dirPath);
|
|
97
97
|
|
|
98
98
|
expect(fs.existsSync(dirPath)).toBe(true);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
it("passes without error for existing directory", () => {
|
|
102
|
-
expect(() =>
|
|
102
|
+
expect(() => mkdirSync(testDir)).not.toThrow();
|
|
103
103
|
});
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
describe("
|
|
106
|
+
describe("mkdir", () => {
|
|
107
107
|
it("creates directory asynchronously", async () => {
|
|
108
108
|
const dirPath = path.join(testDir, "asyncdir");
|
|
109
|
-
await
|
|
109
|
+
await mkdir(dirPath);
|
|
110
110
|
|
|
111
111
|
expect(fs.existsSync(dirPath)).toBe(true);
|
|
112
112
|
});
|
|
@@ -116,12 +116,12 @@ describe("fs functions", () => {
|
|
|
116
116
|
|
|
117
117
|
//#region rm
|
|
118
118
|
|
|
119
|
-
describe("
|
|
119
|
+
describe("rmSync", () => {
|
|
120
120
|
it("deletes file", () => {
|
|
121
121
|
const filePath = path.join(testDir, "todelete.txt");
|
|
122
122
|
fs.writeFileSync(filePath, "test");
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
rmSync(filePath);
|
|
125
125
|
|
|
126
126
|
expect(fs.existsSync(filePath)).toBe(false);
|
|
127
127
|
});
|
|
@@ -131,22 +131,22 @@ describe("fs functions", () => {
|
|
|
131
131
|
fs.mkdirSync(dirPath);
|
|
132
132
|
fs.writeFileSync(path.join(dirPath, "file.txt"), "test");
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
rmSync(dirPath);
|
|
135
135
|
|
|
136
136
|
expect(fs.existsSync(dirPath)).toBe(false);
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
it("passes without error for nonexistent path", () => {
|
|
140
|
-
expect(() =>
|
|
140
|
+
expect(() => rmSync(path.join(testDir, "nonexistent"))).not.toThrow();
|
|
141
141
|
});
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
-
describe("
|
|
144
|
+
describe("rm", () => {
|
|
145
145
|
it("deletes file asynchronously", async () => {
|
|
146
146
|
const filePath = path.join(testDir, "asyncdelete.txt");
|
|
147
147
|
fs.writeFileSync(filePath, "test");
|
|
148
148
|
|
|
149
|
-
await
|
|
149
|
+
await rm(filePath);
|
|
150
150
|
|
|
151
151
|
expect(fs.existsSync(filePath)).toBe(false);
|
|
152
152
|
});
|
|
@@ -156,58 +156,58 @@ describe("fs functions", () => {
|
|
|
156
156
|
|
|
157
157
|
//#region read/write
|
|
158
158
|
|
|
159
|
-
describe("
|
|
159
|
+
describe("readSync", () => {
|
|
160
160
|
it("reads file content as UTF-8 string", () => {
|
|
161
161
|
const filePath = path.join(testDir, "read.txt");
|
|
162
162
|
fs.writeFileSync(filePath, "Hello, World!");
|
|
163
163
|
|
|
164
|
-
const content =
|
|
164
|
+
const content = readSync(filePath);
|
|
165
165
|
|
|
166
166
|
expect(content).toBe("Hello, World!");
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
describe("
|
|
171
|
+
describe("read", () => {
|
|
172
172
|
it("reads file asynchronously", async () => {
|
|
173
173
|
const filePath = path.join(testDir, "asyncread.txt");
|
|
174
174
|
fs.writeFileSync(filePath, "async content");
|
|
175
175
|
|
|
176
|
-
const content = await
|
|
176
|
+
const content = await read(filePath);
|
|
177
177
|
|
|
178
178
|
expect(content).toBe("async content");
|
|
179
179
|
});
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
-
describe("
|
|
182
|
+
describe("readBufferSync", () => {
|
|
183
183
|
it("reads file as Buffer", () => {
|
|
184
184
|
const filePath = path.join(testDir, "buffer.txt");
|
|
185
185
|
fs.writeFileSync(filePath, "buffer content");
|
|
186
186
|
|
|
187
|
-
const buffer =
|
|
187
|
+
const buffer = readBufferSync(filePath);
|
|
188
188
|
|
|
189
189
|
expect(buffer instanceof Uint8Array).toBe(true);
|
|
190
190
|
expect(buffer.toString()).toBe("buffer content");
|
|
191
191
|
});
|
|
192
192
|
});
|
|
193
193
|
|
|
194
|
-
describe("
|
|
194
|
+
describe("readBuffer", () => {
|
|
195
195
|
it("reads file as Buffer asynchronously", async () => {
|
|
196
196
|
const filePath = path.join(testDir, "asyncbuffer.txt");
|
|
197
197
|
fs.writeFileSync(filePath, "async buffer content");
|
|
198
198
|
|
|
199
|
-
const buffer = await
|
|
199
|
+
const buffer = await readBuffer(filePath);
|
|
200
200
|
|
|
201
201
|
expect(buffer instanceof Uint8Array).toBe(true);
|
|
202
202
|
expect(buffer.toString()).toBe("async buffer content");
|
|
203
203
|
});
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
-
describe("
|
|
206
|
+
describe("writeSync", () => {
|
|
207
207
|
it("writes string to file", () => {
|
|
208
208
|
const filePath = path.join(testDir, "write.txt");
|
|
209
209
|
|
|
210
|
-
|
|
210
|
+
writeSync(filePath, "written content");
|
|
211
211
|
|
|
212
212
|
expect(fs.readFileSync(filePath, "utf-8")).toBe("written content");
|
|
213
213
|
});
|
|
@@ -216,7 +216,7 @@ describe("fs functions", () => {
|
|
|
216
216
|
const filePath = path.join(testDir, "buffer-write.bin");
|
|
217
217
|
const buffer = new Uint8Array([0x00, 0x01, 0x02, 0xff]);
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
writeSync(filePath, buffer);
|
|
220
220
|
|
|
221
221
|
expect(new Uint8Array(fs.readFileSync(filePath))).toEqual(buffer);
|
|
222
222
|
});
|
|
@@ -224,17 +224,17 @@ describe("fs functions", () => {
|
|
|
224
224
|
it("auto-creates parent directory if missing", () => {
|
|
225
225
|
const filePath = path.join(testDir, "sub/dir/write.txt");
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
writeSync(filePath, "nested content");
|
|
228
228
|
|
|
229
229
|
expect(fs.readFileSync(filePath, "utf-8")).toBe("nested content");
|
|
230
230
|
});
|
|
231
231
|
});
|
|
232
232
|
|
|
233
|
-
describe("
|
|
233
|
+
describe("write", () => {
|
|
234
234
|
it("writes file asynchronously", async () => {
|
|
235
235
|
const filePath = path.join(testDir, "asyncwrite.txt");
|
|
236
236
|
|
|
237
|
-
await
|
|
237
|
+
await write(filePath, "async written");
|
|
238
238
|
|
|
239
239
|
expect(fs.readFileSync(filePath, "utf-8")).toBe("async written");
|
|
240
240
|
});
|
|
@@ -244,12 +244,12 @@ describe("fs functions", () => {
|
|
|
244
244
|
|
|
245
245
|
//#region JSON
|
|
246
246
|
|
|
247
|
-
describe("
|
|
247
|
+
describe("readJsonSync", () => {
|
|
248
248
|
it("reads JSON file", () => {
|
|
249
249
|
const filePath = path.join(testDir, "data.json");
|
|
250
250
|
fs.writeFileSync(filePath, '{"name": "test", "value": 42}');
|
|
251
251
|
|
|
252
|
-
const data =
|
|
252
|
+
const data = readJsonSync<{ name: string; value: number }>(filePath);
|
|
253
253
|
|
|
254
254
|
expect(data).toEqual({ name: "test", value: 42 });
|
|
255
255
|
});
|
|
@@ -260,7 +260,7 @@ describe("fs functions", () => {
|
|
|
260
260
|
fs.writeFileSync(filePath, longContent);
|
|
261
261
|
|
|
262
262
|
try {
|
|
263
|
-
|
|
263
|
+
readJsonSync(filePath);
|
|
264
264
|
expect.fail("Should throw error");
|
|
265
265
|
} catch (err) {
|
|
266
266
|
expect((err as Error).message).toContain("...(truncated)");
|
|
@@ -268,12 +268,12 @@ describe("fs functions", () => {
|
|
|
268
268
|
});
|
|
269
269
|
});
|
|
270
270
|
|
|
271
|
-
describe("
|
|
271
|
+
describe("writeJsonSync", () => {
|
|
272
272
|
it("writes JSON file", () => {
|
|
273
273
|
const filePath = path.join(testDir, "output.json");
|
|
274
274
|
const data = { name: "test", value: 42 };
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
writeJsonSync(filePath, data);
|
|
277
277
|
|
|
278
278
|
const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) as unknown;
|
|
279
279
|
expect(content).toEqual(data);
|
|
@@ -283,7 +283,7 @@ describe("fs functions", () => {
|
|
|
283
283
|
const filePath = path.join(testDir, "formatted.json");
|
|
284
284
|
const data = { name: "test" };
|
|
285
285
|
|
|
286
|
-
|
|
286
|
+
writeJsonSync(filePath, data, { space: 2 });
|
|
287
287
|
|
|
288
288
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
289
289
|
expect(content).toContain("\n");
|
|
@@ -293,7 +293,7 @@ describe("fs functions", () => {
|
|
|
293
293
|
const filePath = path.join(testDir, "replaced.json");
|
|
294
294
|
const data = { name: "test", secret: "hidden" };
|
|
295
295
|
|
|
296
|
-
|
|
296
|
+
writeJsonSync(filePath, data, {
|
|
297
297
|
replacer: (_key, value) =>
|
|
298
298
|
typeof value === "string" && value === "hidden" ? undefined : value,
|
|
299
299
|
});
|
|
@@ -304,23 +304,23 @@ describe("fs functions", () => {
|
|
|
304
304
|
});
|
|
305
305
|
});
|
|
306
306
|
|
|
307
|
-
describe("
|
|
307
|
+
describe("readJson", () => {
|
|
308
308
|
it("reads JSON file asynchronously", async () => {
|
|
309
309
|
const filePath = path.join(testDir, "asyncdata.json");
|
|
310
310
|
fs.writeFileSync(filePath, '{"name": "async", "value": 100}');
|
|
311
311
|
|
|
312
|
-
const data = await
|
|
312
|
+
const data = await readJson<{ name: string; value: number }>(filePath);
|
|
313
313
|
|
|
314
314
|
expect(data).toEqual({ name: "async", value: 100 });
|
|
315
315
|
});
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
-
describe("
|
|
318
|
+
describe("writeJson", () => {
|
|
319
319
|
it("writes JSON file asynchronously", async () => {
|
|
320
320
|
const filePath = path.join(testDir, "asyncoutput.json");
|
|
321
321
|
const data = { name: "async", value: 100 };
|
|
322
322
|
|
|
323
|
-
await
|
|
323
|
+
await writeJson(filePath, data);
|
|
324
324
|
|
|
325
325
|
const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) as unknown;
|
|
326
326
|
expect(content).toEqual(data);
|
|
@@ -331,13 +331,13 @@ describe("fs functions", () => {
|
|
|
331
331
|
|
|
332
332
|
//#region copy
|
|
333
333
|
|
|
334
|
-
describe("
|
|
334
|
+
describe("copySync", () => {
|
|
335
335
|
it("copies file", () => {
|
|
336
336
|
const source = path.join(testDir, "source.txt");
|
|
337
337
|
const target = path.join(testDir, "target.txt");
|
|
338
338
|
fs.writeFileSync(source, "source content");
|
|
339
339
|
|
|
340
|
-
|
|
340
|
+
copySync(source, target);
|
|
341
341
|
|
|
342
342
|
expect(fs.readFileSync(target, "utf-8")).toBe("source content");
|
|
343
343
|
});
|
|
@@ -350,7 +350,7 @@ describe("fs functions", () => {
|
|
|
350
350
|
fs.mkdirSync(path.join(sourceDir, "sub"));
|
|
351
351
|
fs.writeFileSync(path.join(sourceDir, "sub/nested.txt"), "nested");
|
|
352
352
|
|
|
353
|
-
|
|
353
|
+
copySync(sourceDir, targetDir);
|
|
354
354
|
|
|
355
355
|
expect(fs.existsSync(path.join(targetDir, "file.txt"))).toBe(true);
|
|
356
356
|
expect(fs.existsSync(path.join(targetDir, "sub/nested.txt"))).toBe(true);
|
|
@@ -360,7 +360,7 @@ describe("fs functions", () => {
|
|
|
360
360
|
const source = path.join(testDir, "nonexistent");
|
|
361
361
|
const target = path.join(testDir, "target");
|
|
362
362
|
|
|
363
|
-
expect(() =>
|
|
363
|
+
expect(() => copySync(source, target)).not.toThrow();
|
|
364
364
|
});
|
|
365
365
|
|
|
366
366
|
it("selectively copies with filter option", () => {
|
|
@@ -370,7 +370,7 @@ describe("fs functions", () => {
|
|
|
370
370
|
fs.writeFileSync(path.join(sourceDir, "include.txt"), "include");
|
|
371
371
|
fs.writeFileSync(path.join(sourceDir, "exclude.log"), "exclude");
|
|
372
372
|
|
|
373
|
-
|
|
373
|
+
copySync(sourceDir, targetDir, (p) => !p.endsWith(".log"));
|
|
374
374
|
|
|
375
375
|
expect(fs.existsSync(path.join(targetDir, "include.txt"))).toBe(true);
|
|
376
376
|
expect(fs.existsSync(path.join(targetDir, "exclude.log"))).toBe(false);
|
|
@@ -385,7 +385,7 @@ describe("fs functions", () => {
|
|
|
385
385
|
fs.writeFileSync(path.join(sourceDir, "excluded", "nested.txt"), "nested");
|
|
386
386
|
fs.writeFileSync(path.join(sourceDir, "included", "nested.txt"), "nested");
|
|
387
387
|
|
|
388
|
-
|
|
388
|
+
copySync(sourceDir, targetDir, (p) => !p.includes("excluded"));
|
|
389
389
|
|
|
390
390
|
expect(fs.existsSync(path.join(targetDir, "excluded"))).toBe(false);
|
|
391
391
|
expect(fs.existsSync(path.join(targetDir, "excluded", "nested.txt"))).toBe(false);
|
|
@@ -394,13 +394,13 @@ describe("fs functions", () => {
|
|
|
394
394
|
});
|
|
395
395
|
});
|
|
396
396
|
|
|
397
|
-
describe("
|
|
397
|
+
describe("copy", () => {
|
|
398
398
|
it("copies file asynchronously", async () => {
|
|
399
399
|
const source = path.join(testDir, "asyncSource.txt");
|
|
400
400
|
const target = path.join(testDir, "asyncTarget.txt");
|
|
401
401
|
fs.writeFileSync(source, "async source content");
|
|
402
402
|
|
|
403
|
-
await
|
|
403
|
+
await copy(source, target);
|
|
404
404
|
|
|
405
405
|
expect(fs.readFileSync(target, "utf-8")).toBe("async source content");
|
|
406
406
|
});
|
|
@@ -412,7 +412,7 @@ describe("fs functions", () => {
|
|
|
412
412
|
fs.writeFileSync(path.join(sourceDir, "keep.ts"), "keep");
|
|
413
413
|
fs.writeFileSync(path.join(sourceDir, "skip.js"), "skip");
|
|
414
414
|
|
|
415
|
-
await
|
|
415
|
+
await copy(sourceDir, targetDir, (p) => p.endsWith(".ts"));
|
|
416
416
|
|
|
417
417
|
expect(fs.existsSync(path.join(targetDir, "keep.ts"))).toBe(true);
|
|
418
418
|
expect(fs.existsSync(path.join(targetDir, "skip.js"))).toBe(false);
|
|
@@ -423,13 +423,13 @@ describe("fs functions", () => {
|
|
|
423
423
|
|
|
424
424
|
//#region readdir
|
|
425
425
|
|
|
426
|
-
describe("
|
|
426
|
+
describe("readdirSync", () => {
|
|
427
427
|
it("reads directory contents", () => {
|
|
428
428
|
fs.writeFileSync(path.join(testDir, "file1.txt"), "");
|
|
429
429
|
fs.writeFileSync(path.join(testDir, "file2.txt"), "");
|
|
430
430
|
fs.mkdirSync(path.join(testDir, "subdir"));
|
|
431
431
|
|
|
432
|
-
const entries =
|
|
432
|
+
const entries = readdirSync(testDir);
|
|
433
433
|
|
|
434
434
|
expect(entries).toContain("file1.txt");
|
|
435
435
|
expect(entries).toContain("file2.txt");
|
|
@@ -437,12 +437,12 @@ describe("fs functions", () => {
|
|
|
437
437
|
});
|
|
438
438
|
});
|
|
439
439
|
|
|
440
|
-
describe("
|
|
440
|
+
describe("readdir", () => {
|
|
441
441
|
it("reads directory contents asynchronously", async () => {
|
|
442
442
|
fs.writeFileSync(path.join(testDir, "async1.txt"), "");
|
|
443
443
|
fs.writeFileSync(path.join(testDir, "async2.txt"), "");
|
|
444
444
|
|
|
445
|
-
const entries = await
|
|
445
|
+
const entries = await readdir(testDir);
|
|
446
446
|
|
|
447
447
|
expect(entries).toContain("async1.txt");
|
|
448
448
|
expect(entries).toContain("async2.txt");
|
|
@@ -453,12 +453,12 @@ describe("fs functions", () => {
|
|
|
453
453
|
|
|
454
454
|
//#region stat
|
|
455
455
|
|
|
456
|
-
describe("
|
|
456
|
+
describe("statSync", () => {
|
|
457
457
|
it("gets file information", () => {
|
|
458
458
|
const filePath = path.join(testDir, "statfile.txt");
|
|
459
459
|
fs.writeFileSync(filePath, "content");
|
|
460
460
|
|
|
461
|
-
const result =
|
|
461
|
+
const result = statSync(filePath);
|
|
462
462
|
|
|
463
463
|
expect(result.isFile()).toBe(true);
|
|
464
464
|
expect(result.size).toBeGreaterThan(0);
|
|
@@ -466,27 +466,27 @@ describe("fs functions", () => {
|
|
|
466
466
|
|
|
467
467
|
});
|
|
468
468
|
|
|
469
|
-
describe("
|
|
469
|
+
describe("stat", () => {
|
|
470
470
|
it("gets file information asynchronously", async () => {
|
|
471
471
|
const filePath = path.join(testDir, "asyncstatfile.txt");
|
|
472
472
|
fs.writeFileSync(filePath, "async content");
|
|
473
473
|
|
|
474
|
-
const
|
|
474
|
+
const result = await stat(filePath);
|
|
475
475
|
|
|
476
|
-
expect(
|
|
477
|
-
expect(
|
|
476
|
+
expect(result.isFile()).toBe(true);
|
|
477
|
+
expect(result.size).toBeGreaterThan(0);
|
|
478
478
|
});
|
|
479
479
|
});
|
|
480
480
|
|
|
481
|
-
describe("
|
|
481
|
+
describe("lstatSync", () => {
|
|
482
482
|
it("returns symbolic link information for symbolic links", () => {
|
|
483
483
|
const targetPath = path.join(testDir, "target.txt");
|
|
484
484
|
const linkPath = path.join(testDir, "link.txt");
|
|
485
485
|
fs.writeFileSync(targetPath, "target content");
|
|
486
486
|
fs.symlinkSync(targetPath, linkPath);
|
|
487
487
|
|
|
488
|
-
const lstatResult =
|
|
489
|
-
const statResult =
|
|
488
|
+
const lstatResult = lstatSync(linkPath);
|
|
489
|
+
const statResult = statSync(linkPath);
|
|
490
490
|
|
|
491
491
|
// lstat returns information about the symbolic link itself
|
|
492
492
|
expect(lstatResult.isSymbolicLink()).toBe(true);
|
|
@@ -498,15 +498,15 @@ describe("fs functions", () => {
|
|
|
498
498
|
});
|
|
499
499
|
});
|
|
500
500
|
|
|
501
|
-
describe("
|
|
501
|
+
describe("lstat", () => {
|
|
502
502
|
it("returns symbolic link information asynchronously", async () => {
|
|
503
503
|
const targetPath = path.join(testDir, "async-target.txt");
|
|
504
504
|
const linkPath = path.join(testDir, "async-link.txt");
|
|
505
505
|
fs.writeFileSync(targetPath, "target content");
|
|
506
506
|
fs.symlinkSync(targetPath, linkPath);
|
|
507
507
|
|
|
508
|
-
const lstatResult = await
|
|
509
|
-
const statResult = await
|
|
508
|
+
const lstatResult = await lstat(linkPath);
|
|
509
|
+
const statResult = await stat(linkPath);
|
|
510
510
|
|
|
511
511
|
// lstat returns information about the symbolic link itself
|
|
512
512
|
expect(lstatResult.isSymbolicLink()).toBe(true);
|
|
@@ -522,13 +522,13 @@ describe("fs functions", () => {
|
|
|
522
522
|
|
|
523
523
|
//#region glob
|
|
524
524
|
|
|
525
|
-
describe("
|
|
525
|
+
describe("globSync", () => {
|
|
526
526
|
it("searches files by glob pattern", () => {
|
|
527
527
|
fs.writeFileSync(path.join(testDir, "a.txt"), "");
|
|
528
528
|
fs.writeFileSync(path.join(testDir, "b.txt"), "");
|
|
529
529
|
fs.writeFileSync(path.join(testDir, "c.js"), "");
|
|
530
530
|
|
|
531
|
-
const txtFiles =
|
|
531
|
+
const txtFiles = globSync(path.join(testDir, "*.txt"));
|
|
532
532
|
|
|
533
533
|
expect(txtFiles.length).toBe(2);
|
|
534
534
|
expect(txtFiles.some((f) => f.endsWith("a.txt"))).toBe(true);
|
|
@@ -539,7 +539,7 @@ describe("fs functions", () => {
|
|
|
539
539
|
fs.mkdirSync(path.join(testDir, "nested"));
|
|
540
540
|
fs.writeFileSync(path.join(testDir, "nested/deep.txt"), "");
|
|
541
541
|
|
|
542
|
-
const files =
|
|
542
|
+
const files = globSync(path.join(testDir, "**/*.txt"));
|
|
543
543
|
|
|
544
544
|
expect(files.some((f) => f.endsWith("deep.txt"))).toBe(true);
|
|
545
545
|
});
|
|
@@ -548,19 +548,19 @@ describe("fs functions", () => {
|
|
|
548
548
|
fs.writeFileSync(path.join(testDir, ".hidden"), "");
|
|
549
549
|
fs.writeFileSync(path.join(testDir, "visible"), "");
|
|
550
550
|
|
|
551
|
-
const withoutDot =
|
|
552
|
-
const withDot =
|
|
551
|
+
const withoutDot = globSync(path.join(testDir, "*"));
|
|
552
|
+
const withDot = globSync(path.join(testDir, "*"), { dot: true });
|
|
553
553
|
|
|
554
554
|
expect(withoutDot.some((f) => f.endsWith(".hidden"))).toBe(false);
|
|
555
555
|
expect(withDot.some((f) => f.endsWith(".hidden"))).toBe(true);
|
|
556
556
|
});
|
|
557
557
|
});
|
|
558
558
|
|
|
559
|
-
describe("
|
|
559
|
+
describe("glob", () => {
|
|
560
560
|
it("searches files asynchronously by glob pattern", async () => {
|
|
561
561
|
fs.writeFileSync(path.join(testDir, "async.txt"), "");
|
|
562
562
|
|
|
563
|
-
const files = await
|
|
563
|
+
const files = await glob(path.join(testDir, "*.txt"));
|
|
564
564
|
|
|
565
565
|
expect(files.length).toBeGreaterThan(0);
|
|
566
566
|
});
|
|
@@ -570,12 +570,12 @@ describe("fs functions", () => {
|
|
|
570
570
|
|
|
571
571
|
//#region clearEmptyDirectoryAsync
|
|
572
572
|
|
|
573
|
-
describe("
|
|
573
|
+
describe("clearEmptyDirectory", () => {
|
|
574
574
|
it("recursively deletes empty directories", async () => {
|
|
575
575
|
const emptyDir = path.join(testDir, "empty/nested/deep");
|
|
576
576
|
fs.mkdirSync(emptyDir, { recursive: true });
|
|
577
577
|
|
|
578
|
-
await
|
|
578
|
+
await clearEmptyDirectory(path.join(testDir, "empty"));
|
|
579
579
|
|
|
580
580
|
expect(fs.existsSync(path.join(testDir, "empty"))).toBe(false);
|
|
581
581
|
});
|
|
@@ -585,7 +585,7 @@ describe("fs functions", () => {
|
|
|
585
585
|
fs.mkdirSync(dirWithFile);
|
|
586
586
|
fs.writeFileSync(path.join(dirWithFile, "file.txt"), "content");
|
|
587
587
|
|
|
588
|
-
await
|
|
588
|
+
await clearEmptyDirectory(dirWithFile);
|
|
589
589
|
|
|
590
590
|
expect(fs.existsSync(dirWithFile)).toBe(true);
|
|
591
591
|
});
|
|
@@ -595,14 +595,14 @@ describe("fs functions", () => {
|
|
|
595
595
|
|
|
596
596
|
//#region findAllParentChildPaths
|
|
597
597
|
|
|
598
|
-
describe("
|
|
598
|
+
describe("findAllParentChildPathsSync", () => {
|
|
599
599
|
it("finds specific file in parent directories", () => {
|
|
600
600
|
const deepDir = path.join(testDir, "a/b/c");
|
|
601
601
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
602
602
|
fs.writeFileSync(path.join(testDir, "marker.txt"), "");
|
|
603
603
|
fs.writeFileSync(path.join(testDir, "a/marker.txt"), "");
|
|
604
604
|
|
|
605
|
-
const results =
|
|
605
|
+
const results = findAllParentChildPathsSync("marker.txt", deepDir, testDir);
|
|
606
606
|
|
|
607
607
|
expect(results.length).toBe(2);
|
|
608
608
|
});
|
|
@@ -611,20 +611,20 @@ describe("fs functions", () => {
|
|
|
611
611
|
const deepDir = path.join(testDir, "a/b/c");
|
|
612
612
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
613
613
|
|
|
614
|
-
const results =
|
|
614
|
+
const results = findAllParentChildPathsSync("nonexistent-file.txt", deepDir, testDir);
|
|
615
615
|
|
|
616
616
|
expect(results).toEqual([]);
|
|
617
617
|
});
|
|
618
618
|
});
|
|
619
619
|
|
|
620
|
-
describe("
|
|
620
|
+
describe("findAllParentChildPaths", () => {
|
|
621
621
|
it("finds specific file in parent directories asynchronously", async () => {
|
|
622
622
|
const deepDir = path.join(testDir, "x/y/z");
|
|
623
623
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
624
624
|
fs.writeFileSync(path.join(testDir, "config.json"), "");
|
|
625
625
|
fs.writeFileSync(path.join(testDir, "x/config.json"), "");
|
|
626
626
|
|
|
627
|
-
const results = await
|
|
627
|
+
const results = await findAllParentChildPaths("config.json", deepDir, testDir);
|
|
628
628
|
|
|
629
629
|
expect(results.length).toBe(2);
|
|
630
630
|
});
|
|
@@ -633,7 +633,7 @@ describe("fs functions", () => {
|
|
|
633
633
|
const deepDir = path.join(testDir, "x/y/z");
|
|
634
634
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
635
635
|
|
|
636
|
-
const results = await
|
|
636
|
+
const results = await findAllParentChildPaths("nonexistent-file.txt", deepDir, testDir);
|
|
637
637
|
|
|
638
638
|
expect(results).toEqual([]);
|
|
639
639
|
});
|
|
@@ -646,9 +646,9 @@ describe("fs functions", () => {
|
|
|
646
646
|
describe("error cases", () => {
|
|
647
647
|
it("includes path information in SdError when reading nonexistent file", () => {
|
|
648
648
|
const filePath = path.join(testDir, "nonexistent.txt");
|
|
649
|
-
expect(() =>
|
|
649
|
+
expect(() => readSync(filePath)).toThrow(SdError);
|
|
650
650
|
try {
|
|
651
|
-
|
|
651
|
+
readSync(filePath);
|
|
652
652
|
} catch (err) {
|
|
653
653
|
expect((err as Error).message).toContain(filePath);
|
|
654
654
|
}
|
|
@@ -656,20 +656,20 @@ describe("fs functions", () => {
|
|
|
656
656
|
|
|
657
657
|
it("includes path information in SdError when reading nonexistent file asynchronously", async () => {
|
|
658
658
|
const filePath = path.join(testDir, "nonexistent.txt");
|
|
659
|
-
await expect(
|
|
659
|
+
await expect(read(filePath)).rejects.toThrow(SdError);
|
|
660
660
|
try {
|
|
661
|
-
await
|
|
661
|
+
await read(filePath);
|
|
662
662
|
} catch (err) {
|
|
663
663
|
expect((err as Error).message).toContain(filePath);
|
|
664
664
|
}
|
|
665
665
|
});
|
|
666
666
|
|
|
667
667
|
it("throws error when reading nonexistent directory", () => {
|
|
668
|
-
expect(() =>
|
|
668
|
+
expect(() => readdirSync(path.join(testDir, "nonexistent"))).toThrow();
|
|
669
669
|
});
|
|
670
670
|
|
|
671
671
|
it("throws error when stat nonexistent file", () => {
|
|
672
|
-
expect(() =>
|
|
672
|
+
expect(() => statSync(path.join(testDir, "nonexistent.txt"))).toThrow();
|
|
673
673
|
});
|
|
674
674
|
|
|
675
675
|
it("includes path and content information in SdError when reading invalid JSON", () => {
|
|
@@ -677,9 +677,9 @@ describe("fs functions", () => {
|
|
|
677
677
|
const content = "{ invalid json }";
|
|
678
678
|
fs.writeFileSync(filePath, content);
|
|
679
679
|
|
|
680
|
-
expect(() =>
|
|
680
|
+
expect(() => readJsonSync(filePath)).toThrow(SdError);
|
|
681
681
|
try {
|
|
682
|
-
|
|
682
|
+
readJsonSync(filePath);
|
|
683
683
|
} catch (err) {
|
|
684
684
|
expect((err as Error).message).toContain(filePath);
|
|
685
685
|
expect((err as Error).message).toContain(content);
|
|
@@ -691,9 +691,9 @@ describe("fs functions", () => {
|
|
|
691
691
|
const content = "{ invalid json }";
|
|
692
692
|
fs.writeFileSync(filePath, content);
|
|
693
693
|
|
|
694
|
-
await expect(
|
|
694
|
+
await expect(readJson(filePath)).rejects.toThrow(SdError);
|
|
695
695
|
try {
|
|
696
|
-
await
|
|
696
|
+
await readJson(filePath);
|
|
697
697
|
} catch (err) {
|
|
698
698
|
expect((err as Error).message).toContain(filePath);
|
|
699
699
|
expect((err as Error).message).toContain(content);
|