@simplysm/core-node 13.0.75 → 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-watcher.spec.ts +0 -53
- package/tests/utils/fs.spec.ts +123 -173
- package/tests/utils/path.spec.ts +55 -68
- package/tests/worker/sd-worker.spec.ts +0 -15
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,50 +48,44 @@ 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
|
-
it("returns true for existing directory", () => {
|
|
65
|
-
expect(fsExistsSync(testDir)).toBe(true);
|
|
66
|
-
});
|
|
67
64
|
});
|
|
68
65
|
|
|
69
|
-
describe("
|
|
66
|
+
describe("exists", () => {
|
|
70
67
|
it("returns true for existing file", async () => {
|
|
71
68
|
const filePath = path.join(testDir, "test.txt");
|
|
72
69
|
fs.writeFileSync(filePath, "test");
|
|
73
70
|
|
|
74
|
-
expect(await
|
|
71
|
+
expect(await exists(filePath)).toBe(true);
|
|
75
72
|
});
|
|
76
73
|
|
|
77
74
|
it("returns false for nonexistent file", async () => {
|
|
78
75
|
const filePath = path.join(testDir, "nonexistent.txt");
|
|
79
|
-
expect(await
|
|
76
|
+
expect(await exists(filePath)).toBe(false);
|
|
80
77
|
});
|
|
81
78
|
|
|
82
|
-
it("returns true for existing directory", async () => {
|
|
83
|
-
expect(await fsExists(testDir)).toBe(true);
|
|
84
|
-
});
|
|
85
79
|
});
|
|
86
80
|
|
|
87
81
|
//#endregion
|
|
88
82
|
|
|
89
83
|
//#region mkdir
|
|
90
84
|
|
|
91
|
-
describe("
|
|
85
|
+
describe("mkdirSync", () => {
|
|
92
86
|
it("creates directory", () => {
|
|
93
87
|
const dirPath = path.join(testDir, "newdir");
|
|
94
|
-
|
|
88
|
+
mkdirSync(dirPath);
|
|
95
89
|
|
|
96
90
|
expect(fs.existsSync(dirPath)).toBe(true);
|
|
97
91
|
expect(fs.statSync(dirPath).isDirectory()).toBe(true);
|
|
@@ -99,20 +93,20 @@ describe("fs functions", () => {
|
|
|
99
93
|
|
|
100
94
|
it("creates nested directories (recursive)", () => {
|
|
101
95
|
const dirPath = path.join(testDir, "a/b/c");
|
|
102
|
-
|
|
96
|
+
mkdirSync(dirPath);
|
|
103
97
|
|
|
104
98
|
expect(fs.existsSync(dirPath)).toBe(true);
|
|
105
99
|
});
|
|
106
100
|
|
|
107
101
|
it("passes without error for existing directory", () => {
|
|
108
|
-
expect(() =>
|
|
102
|
+
expect(() => mkdirSync(testDir)).not.toThrow();
|
|
109
103
|
});
|
|
110
104
|
});
|
|
111
105
|
|
|
112
|
-
describe("
|
|
106
|
+
describe("mkdir", () => {
|
|
113
107
|
it("creates directory asynchronously", async () => {
|
|
114
108
|
const dirPath = path.join(testDir, "asyncdir");
|
|
115
|
-
await
|
|
109
|
+
await mkdir(dirPath);
|
|
116
110
|
|
|
117
111
|
expect(fs.existsSync(dirPath)).toBe(true);
|
|
118
112
|
});
|
|
@@ -122,12 +116,12 @@ describe("fs functions", () => {
|
|
|
122
116
|
|
|
123
117
|
//#region rm
|
|
124
118
|
|
|
125
|
-
describe("
|
|
119
|
+
describe("rmSync", () => {
|
|
126
120
|
it("deletes file", () => {
|
|
127
121
|
const filePath = path.join(testDir, "todelete.txt");
|
|
128
122
|
fs.writeFileSync(filePath, "test");
|
|
129
123
|
|
|
130
|
-
|
|
124
|
+
rmSync(filePath);
|
|
131
125
|
|
|
132
126
|
expect(fs.existsSync(filePath)).toBe(false);
|
|
133
127
|
});
|
|
@@ -137,22 +131,22 @@ describe("fs functions", () => {
|
|
|
137
131
|
fs.mkdirSync(dirPath);
|
|
138
132
|
fs.writeFileSync(path.join(dirPath, "file.txt"), "test");
|
|
139
133
|
|
|
140
|
-
|
|
134
|
+
rmSync(dirPath);
|
|
141
135
|
|
|
142
136
|
expect(fs.existsSync(dirPath)).toBe(false);
|
|
143
137
|
});
|
|
144
138
|
|
|
145
139
|
it("passes without error for nonexistent path", () => {
|
|
146
|
-
expect(() =>
|
|
140
|
+
expect(() => rmSync(path.join(testDir, "nonexistent"))).not.toThrow();
|
|
147
141
|
});
|
|
148
142
|
});
|
|
149
143
|
|
|
150
|
-
describe("
|
|
144
|
+
describe("rm", () => {
|
|
151
145
|
it("deletes file asynchronously", async () => {
|
|
152
146
|
const filePath = path.join(testDir, "asyncdelete.txt");
|
|
153
147
|
fs.writeFileSync(filePath, "test");
|
|
154
148
|
|
|
155
|
-
await
|
|
149
|
+
await rm(filePath);
|
|
156
150
|
|
|
157
151
|
expect(fs.existsSync(filePath)).toBe(false);
|
|
158
152
|
});
|
|
@@ -162,66 +156,58 @@ describe("fs functions", () => {
|
|
|
162
156
|
|
|
163
157
|
//#region read/write
|
|
164
158
|
|
|
165
|
-
describe("
|
|
159
|
+
describe("readSync", () => {
|
|
166
160
|
it("reads file content as UTF-8 string", () => {
|
|
167
161
|
const filePath = path.join(testDir, "read.txt");
|
|
168
162
|
fs.writeFileSync(filePath, "Hello, World!");
|
|
169
163
|
|
|
170
|
-
const content =
|
|
164
|
+
const content = readSync(filePath);
|
|
171
165
|
|
|
172
166
|
expect(content).toBe("Hello, World!");
|
|
173
167
|
});
|
|
174
168
|
|
|
175
|
-
it("reads Korean content", () => {
|
|
176
|
-
const filePath = path.join(testDir, "korean.txt");
|
|
177
|
-
fs.writeFileSync(filePath, "안녕하세요");
|
|
178
|
-
|
|
179
|
-
const content = fsReadSync(filePath);
|
|
180
|
-
|
|
181
|
-
expect(content).toBe("안녕하세요");
|
|
182
|
-
});
|
|
183
169
|
});
|
|
184
170
|
|
|
185
|
-
describe("
|
|
171
|
+
describe("read", () => {
|
|
186
172
|
it("reads file asynchronously", async () => {
|
|
187
173
|
const filePath = path.join(testDir, "asyncread.txt");
|
|
188
174
|
fs.writeFileSync(filePath, "async content");
|
|
189
175
|
|
|
190
|
-
const content = await
|
|
176
|
+
const content = await read(filePath);
|
|
191
177
|
|
|
192
178
|
expect(content).toBe("async content");
|
|
193
179
|
});
|
|
194
180
|
});
|
|
195
181
|
|
|
196
|
-
describe("
|
|
182
|
+
describe("readBufferSync", () => {
|
|
197
183
|
it("reads file as Buffer", () => {
|
|
198
184
|
const filePath = path.join(testDir, "buffer.txt");
|
|
199
185
|
fs.writeFileSync(filePath, "buffer content");
|
|
200
186
|
|
|
201
|
-
const buffer =
|
|
187
|
+
const buffer = readBufferSync(filePath);
|
|
202
188
|
|
|
203
189
|
expect(buffer instanceof Uint8Array).toBe(true);
|
|
204
190
|
expect(buffer.toString()).toBe("buffer content");
|
|
205
191
|
});
|
|
206
192
|
});
|
|
207
193
|
|
|
208
|
-
describe("
|
|
194
|
+
describe("readBuffer", () => {
|
|
209
195
|
it("reads file as Buffer asynchronously", async () => {
|
|
210
196
|
const filePath = path.join(testDir, "asyncbuffer.txt");
|
|
211
197
|
fs.writeFileSync(filePath, "async buffer content");
|
|
212
198
|
|
|
213
|
-
const buffer = await
|
|
199
|
+
const buffer = await readBuffer(filePath);
|
|
214
200
|
|
|
215
201
|
expect(buffer instanceof Uint8Array).toBe(true);
|
|
216
202
|
expect(buffer.toString()).toBe("async buffer content");
|
|
217
203
|
});
|
|
218
204
|
});
|
|
219
205
|
|
|
220
|
-
describe("
|
|
206
|
+
describe("writeSync", () => {
|
|
221
207
|
it("writes string to file", () => {
|
|
222
208
|
const filePath = path.join(testDir, "write.txt");
|
|
223
209
|
|
|
224
|
-
|
|
210
|
+
writeSync(filePath, "written content");
|
|
225
211
|
|
|
226
212
|
expect(fs.readFileSync(filePath, "utf-8")).toBe("written content");
|
|
227
213
|
});
|
|
@@ -230,7 +216,7 @@ describe("fs functions", () => {
|
|
|
230
216
|
const filePath = path.join(testDir, "buffer-write.bin");
|
|
231
217
|
const buffer = new Uint8Array([0x00, 0x01, 0x02, 0xff]);
|
|
232
218
|
|
|
233
|
-
|
|
219
|
+
writeSync(filePath, buffer);
|
|
234
220
|
|
|
235
221
|
expect(new Uint8Array(fs.readFileSync(filePath))).toEqual(buffer);
|
|
236
222
|
});
|
|
@@ -238,17 +224,17 @@ describe("fs functions", () => {
|
|
|
238
224
|
it("auto-creates parent directory if missing", () => {
|
|
239
225
|
const filePath = path.join(testDir, "sub/dir/write.txt");
|
|
240
226
|
|
|
241
|
-
|
|
227
|
+
writeSync(filePath, "nested content");
|
|
242
228
|
|
|
243
229
|
expect(fs.readFileSync(filePath, "utf-8")).toBe("nested content");
|
|
244
230
|
});
|
|
245
231
|
});
|
|
246
232
|
|
|
247
|
-
describe("
|
|
233
|
+
describe("write", () => {
|
|
248
234
|
it("writes file asynchronously", async () => {
|
|
249
235
|
const filePath = path.join(testDir, "asyncwrite.txt");
|
|
250
236
|
|
|
251
|
-
await
|
|
237
|
+
await write(filePath, "async written");
|
|
252
238
|
|
|
253
239
|
expect(fs.readFileSync(filePath, "utf-8")).toBe("async written");
|
|
254
240
|
});
|
|
@@ -258,12 +244,12 @@ describe("fs functions", () => {
|
|
|
258
244
|
|
|
259
245
|
//#region JSON
|
|
260
246
|
|
|
261
|
-
describe("
|
|
247
|
+
describe("readJsonSync", () => {
|
|
262
248
|
it("reads JSON file", () => {
|
|
263
249
|
const filePath = path.join(testDir, "data.json");
|
|
264
250
|
fs.writeFileSync(filePath, '{"name": "test", "value": 42}');
|
|
265
251
|
|
|
266
|
-
const data =
|
|
252
|
+
const data = readJsonSync<{ name: string; value: number }>(filePath);
|
|
267
253
|
|
|
268
254
|
expect(data).toEqual({ name: "test", value: 42 });
|
|
269
255
|
});
|
|
@@ -274,7 +260,7 @@ describe("fs functions", () => {
|
|
|
274
260
|
fs.writeFileSync(filePath, longContent);
|
|
275
261
|
|
|
276
262
|
try {
|
|
277
|
-
|
|
263
|
+
readJsonSync(filePath);
|
|
278
264
|
expect.fail("Should throw error");
|
|
279
265
|
} catch (err) {
|
|
280
266
|
expect((err as Error).message).toContain("...(truncated)");
|
|
@@ -282,12 +268,12 @@ describe("fs functions", () => {
|
|
|
282
268
|
});
|
|
283
269
|
});
|
|
284
270
|
|
|
285
|
-
describe("
|
|
271
|
+
describe("writeJsonSync", () => {
|
|
286
272
|
it("writes JSON file", () => {
|
|
287
273
|
const filePath = path.join(testDir, "output.json");
|
|
288
274
|
const data = { name: "test", value: 42 };
|
|
289
275
|
|
|
290
|
-
|
|
276
|
+
writeJsonSync(filePath, data);
|
|
291
277
|
|
|
292
278
|
const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) as unknown;
|
|
293
279
|
expect(content).toEqual(data);
|
|
@@ -297,7 +283,7 @@ describe("fs functions", () => {
|
|
|
297
283
|
const filePath = path.join(testDir, "formatted.json");
|
|
298
284
|
const data = { name: "test" };
|
|
299
285
|
|
|
300
|
-
|
|
286
|
+
writeJsonSync(filePath, data, { space: 2 });
|
|
301
287
|
|
|
302
288
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
303
289
|
expect(content).toContain("\n");
|
|
@@ -307,7 +293,7 @@ describe("fs functions", () => {
|
|
|
307
293
|
const filePath = path.join(testDir, "replaced.json");
|
|
308
294
|
const data = { name: "test", secret: "hidden" };
|
|
309
295
|
|
|
310
|
-
|
|
296
|
+
writeJsonSync(filePath, data, {
|
|
311
297
|
replacer: (_key, value) =>
|
|
312
298
|
typeof value === "string" && value === "hidden" ? undefined : value,
|
|
313
299
|
});
|
|
@@ -318,23 +304,23 @@ describe("fs functions", () => {
|
|
|
318
304
|
});
|
|
319
305
|
});
|
|
320
306
|
|
|
321
|
-
describe("
|
|
307
|
+
describe("readJson", () => {
|
|
322
308
|
it("reads JSON file asynchronously", async () => {
|
|
323
309
|
const filePath = path.join(testDir, "asyncdata.json");
|
|
324
310
|
fs.writeFileSync(filePath, '{"name": "async", "value": 100}');
|
|
325
311
|
|
|
326
|
-
const data = await
|
|
312
|
+
const data = await readJson<{ name: string; value: number }>(filePath);
|
|
327
313
|
|
|
328
314
|
expect(data).toEqual({ name: "async", value: 100 });
|
|
329
315
|
});
|
|
330
316
|
});
|
|
331
317
|
|
|
332
|
-
describe("
|
|
318
|
+
describe("writeJson", () => {
|
|
333
319
|
it("writes JSON file asynchronously", async () => {
|
|
334
320
|
const filePath = path.join(testDir, "asyncoutput.json");
|
|
335
321
|
const data = { name: "async", value: 100 };
|
|
336
322
|
|
|
337
|
-
await
|
|
323
|
+
await writeJson(filePath, data);
|
|
338
324
|
|
|
339
325
|
const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) as unknown;
|
|
340
326
|
expect(content).toEqual(data);
|
|
@@ -345,13 +331,13 @@ describe("fs functions", () => {
|
|
|
345
331
|
|
|
346
332
|
//#region copy
|
|
347
333
|
|
|
348
|
-
describe("
|
|
334
|
+
describe("copySync", () => {
|
|
349
335
|
it("copies file", () => {
|
|
350
336
|
const source = path.join(testDir, "source.txt");
|
|
351
337
|
const target = path.join(testDir, "target.txt");
|
|
352
338
|
fs.writeFileSync(source, "source content");
|
|
353
339
|
|
|
354
|
-
|
|
340
|
+
copySync(source, target);
|
|
355
341
|
|
|
356
342
|
expect(fs.readFileSync(target, "utf-8")).toBe("source content");
|
|
357
343
|
});
|
|
@@ -364,7 +350,7 @@ describe("fs functions", () => {
|
|
|
364
350
|
fs.mkdirSync(path.join(sourceDir, "sub"));
|
|
365
351
|
fs.writeFileSync(path.join(sourceDir, "sub/nested.txt"), "nested");
|
|
366
352
|
|
|
367
|
-
|
|
353
|
+
copySync(sourceDir, targetDir);
|
|
368
354
|
|
|
369
355
|
expect(fs.existsSync(path.join(targetDir, "file.txt"))).toBe(true);
|
|
370
356
|
expect(fs.existsSync(path.join(targetDir, "sub/nested.txt"))).toBe(true);
|
|
@@ -374,7 +360,7 @@ describe("fs functions", () => {
|
|
|
374
360
|
const source = path.join(testDir, "nonexistent");
|
|
375
361
|
const target = path.join(testDir, "target");
|
|
376
362
|
|
|
377
|
-
expect(() =>
|
|
363
|
+
expect(() => copySync(source, target)).not.toThrow();
|
|
378
364
|
});
|
|
379
365
|
|
|
380
366
|
it("selectively copies with filter option", () => {
|
|
@@ -384,7 +370,7 @@ describe("fs functions", () => {
|
|
|
384
370
|
fs.writeFileSync(path.join(sourceDir, "include.txt"), "include");
|
|
385
371
|
fs.writeFileSync(path.join(sourceDir, "exclude.log"), "exclude");
|
|
386
372
|
|
|
387
|
-
|
|
373
|
+
copySync(sourceDir, targetDir, (p) => !p.endsWith(".log"));
|
|
388
374
|
|
|
389
375
|
expect(fs.existsSync(path.join(targetDir, "include.txt"))).toBe(true);
|
|
390
376
|
expect(fs.existsSync(path.join(targetDir, "exclude.log"))).toBe(false);
|
|
@@ -399,7 +385,7 @@ describe("fs functions", () => {
|
|
|
399
385
|
fs.writeFileSync(path.join(sourceDir, "excluded", "nested.txt"), "nested");
|
|
400
386
|
fs.writeFileSync(path.join(sourceDir, "included", "nested.txt"), "nested");
|
|
401
387
|
|
|
402
|
-
|
|
388
|
+
copySync(sourceDir, targetDir, (p) => !p.includes("excluded"));
|
|
403
389
|
|
|
404
390
|
expect(fs.existsSync(path.join(targetDir, "excluded"))).toBe(false);
|
|
405
391
|
expect(fs.existsSync(path.join(targetDir, "excluded", "nested.txt"))).toBe(false);
|
|
@@ -408,31 +394,17 @@ describe("fs functions", () => {
|
|
|
408
394
|
});
|
|
409
395
|
});
|
|
410
396
|
|
|
411
|
-
describe("
|
|
397
|
+
describe("copy", () => {
|
|
412
398
|
it("copies file asynchronously", async () => {
|
|
413
399
|
const source = path.join(testDir, "asyncSource.txt");
|
|
414
400
|
const target = path.join(testDir, "asyncTarget.txt");
|
|
415
401
|
fs.writeFileSync(source, "async source content");
|
|
416
402
|
|
|
417
|
-
await
|
|
403
|
+
await copy(source, target);
|
|
418
404
|
|
|
419
405
|
expect(fs.readFileSync(target, "utf-8")).toBe("async source content");
|
|
420
406
|
});
|
|
421
407
|
|
|
422
|
-
it("copies directory asynchronously (recursive)", async () => {
|
|
423
|
-
const sourceDir = path.join(testDir, "asyncSourceDir");
|
|
424
|
-
const targetDir = path.join(testDir, "asyncTargetDir");
|
|
425
|
-
fs.mkdirSync(sourceDir);
|
|
426
|
-
fs.writeFileSync(path.join(sourceDir, "file.txt"), "content");
|
|
427
|
-
fs.mkdirSync(path.join(sourceDir, "sub"));
|
|
428
|
-
fs.writeFileSync(path.join(sourceDir, "sub/nested.txt"), "nested");
|
|
429
|
-
|
|
430
|
-
await fsCopy(sourceDir, targetDir);
|
|
431
|
-
|
|
432
|
-
expect(fs.existsSync(path.join(targetDir, "file.txt"))).toBe(true);
|
|
433
|
-
expect(fs.existsSync(path.join(targetDir, "sub/nested.txt"))).toBe(true);
|
|
434
|
-
});
|
|
435
|
-
|
|
436
408
|
it("selectively copies with filter option asynchronously", async () => {
|
|
437
409
|
const sourceDir = path.join(testDir, "asyncFilterSource");
|
|
438
410
|
const targetDir = path.join(testDir, "asyncFilterTarget");
|
|
@@ -440,7 +412,7 @@ describe("fs functions", () => {
|
|
|
440
412
|
fs.writeFileSync(path.join(sourceDir, "keep.ts"), "keep");
|
|
441
413
|
fs.writeFileSync(path.join(sourceDir, "skip.js"), "skip");
|
|
442
414
|
|
|
443
|
-
await
|
|
415
|
+
await copy(sourceDir, targetDir, (p) => p.endsWith(".ts"));
|
|
444
416
|
|
|
445
417
|
expect(fs.existsSync(path.join(targetDir, "keep.ts"))).toBe(true);
|
|
446
418
|
expect(fs.existsSync(path.join(targetDir, "skip.js"))).toBe(false);
|
|
@@ -451,13 +423,13 @@ describe("fs functions", () => {
|
|
|
451
423
|
|
|
452
424
|
//#region readdir
|
|
453
425
|
|
|
454
|
-
describe("
|
|
426
|
+
describe("readdirSync", () => {
|
|
455
427
|
it("reads directory contents", () => {
|
|
456
428
|
fs.writeFileSync(path.join(testDir, "file1.txt"), "");
|
|
457
429
|
fs.writeFileSync(path.join(testDir, "file2.txt"), "");
|
|
458
430
|
fs.mkdirSync(path.join(testDir, "subdir"));
|
|
459
431
|
|
|
460
|
-
const entries =
|
|
432
|
+
const entries = readdirSync(testDir);
|
|
461
433
|
|
|
462
434
|
expect(entries).toContain("file1.txt");
|
|
463
435
|
expect(entries).toContain("file2.txt");
|
|
@@ -465,12 +437,12 @@ describe("fs functions", () => {
|
|
|
465
437
|
});
|
|
466
438
|
});
|
|
467
439
|
|
|
468
|
-
describe("
|
|
440
|
+
describe("readdir", () => {
|
|
469
441
|
it("reads directory contents asynchronously", async () => {
|
|
470
442
|
fs.writeFileSync(path.join(testDir, "async1.txt"), "");
|
|
471
443
|
fs.writeFileSync(path.join(testDir, "async2.txt"), "");
|
|
472
444
|
|
|
473
|
-
const entries = await
|
|
445
|
+
const entries = await readdir(testDir);
|
|
474
446
|
|
|
475
447
|
expect(entries).toContain("async1.txt");
|
|
476
448
|
expect(entries).toContain("async2.txt");
|
|
@@ -481,53 +453,40 @@ describe("fs functions", () => {
|
|
|
481
453
|
|
|
482
454
|
//#region stat
|
|
483
455
|
|
|
484
|
-
describe("
|
|
456
|
+
describe("statSync", () => {
|
|
485
457
|
it("gets file information", () => {
|
|
486
458
|
const filePath = path.join(testDir, "statfile.txt");
|
|
487
459
|
fs.writeFileSync(filePath, "content");
|
|
488
460
|
|
|
489
|
-
const result =
|
|
461
|
+
const result = statSync(filePath);
|
|
490
462
|
|
|
491
463
|
expect(result.isFile()).toBe(true);
|
|
492
464
|
expect(result.size).toBeGreaterThan(0);
|
|
493
465
|
});
|
|
494
466
|
|
|
495
|
-
it("gets directory information", () => {
|
|
496
|
-
const result = fsStatSync(testDir);
|
|
497
|
-
expect(result.isDirectory()).toBe(true);
|
|
498
|
-
});
|
|
499
467
|
});
|
|
500
468
|
|
|
501
|
-
describe("
|
|
469
|
+
describe("stat", () => {
|
|
502
470
|
it("gets file information asynchronously", async () => {
|
|
503
471
|
const filePath = path.join(testDir, "asyncstatfile.txt");
|
|
504
472
|
fs.writeFileSync(filePath, "async content");
|
|
505
473
|
|
|
506
|
-
const
|
|
474
|
+
const result = await stat(filePath);
|
|
507
475
|
|
|
508
|
-
expect(
|
|
509
|
-
expect(
|
|
476
|
+
expect(result.isFile()).toBe(true);
|
|
477
|
+
expect(result.size).toBeGreaterThan(0);
|
|
510
478
|
});
|
|
511
479
|
});
|
|
512
480
|
|
|
513
|
-
describe("
|
|
514
|
-
it("gets regular file information", () => {
|
|
515
|
-
const filePath = path.join(testDir, "lstatfile.txt");
|
|
516
|
-
fs.writeFileSync(filePath, "content");
|
|
517
|
-
|
|
518
|
-
const stat = fsLstatSync(filePath);
|
|
519
|
-
|
|
520
|
-
expect(stat.isFile()).toBe(true);
|
|
521
|
-
});
|
|
522
|
-
|
|
481
|
+
describe("lstatSync", () => {
|
|
523
482
|
it("returns symbolic link information for symbolic links", () => {
|
|
524
483
|
const targetPath = path.join(testDir, "target.txt");
|
|
525
484
|
const linkPath = path.join(testDir, "link.txt");
|
|
526
485
|
fs.writeFileSync(targetPath, "target content");
|
|
527
486
|
fs.symlinkSync(targetPath, linkPath);
|
|
528
487
|
|
|
529
|
-
const lstatResult =
|
|
530
|
-
const statResult =
|
|
488
|
+
const lstatResult = lstatSync(linkPath);
|
|
489
|
+
const statResult = statSync(linkPath);
|
|
531
490
|
|
|
532
491
|
// lstat returns information about the symbolic link itself
|
|
533
492
|
expect(lstatResult.isSymbolicLink()).toBe(true);
|
|
@@ -539,24 +498,15 @@ describe("fs functions", () => {
|
|
|
539
498
|
});
|
|
540
499
|
});
|
|
541
500
|
|
|
542
|
-
describe("
|
|
543
|
-
it("gets file information asynchronously", async () => {
|
|
544
|
-
const filePath = path.join(testDir, "asynclstatfile.txt");
|
|
545
|
-
fs.writeFileSync(filePath, "async content");
|
|
546
|
-
|
|
547
|
-
const stat = await fsLstat(filePath);
|
|
548
|
-
|
|
549
|
-
expect(stat.isFile()).toBe(true);
|
|
550
|
-
});
|
|
551
|
-
|
|
501
|
+
describe("lstat", () => {
|
|
552
502
|
it("returns symbolic link information asynchronously", async () => {
|
|
553
503
|
const targetPath = path.join(testDir, "async-target.txt");
|
|
554
504
|
const linkPath = path.join(testDir, "async-link.txt");
|
|
555
505
|
fs.writeFileSync(targetPath, "target content");
|
|
556
506
|
fs.symlinkSync(targetPath, linkPath);
|
|
557
507
|
|
|
558
|
-
const lstatResult = await
|
|
559
|
-
const statResult = await
|
|
508
|
+
const lstatResult = await lstat(linkPath);
|
|
509
|
+
const statResult = await stat(linkPath);
|
|
560
510
|
|
|
561
511
|
// lstat returns information about the symbolic link itself
|
|
562
512
|
expect(lstatResult.isSymbolicLink()).toBe(true);
|
|
@@ -572,13 +522,13 @@ describe("fs functions", () => {
|
|
|
572
522
|
|
|
573
523
|
//#region glob
|
|
574
524
|
|
|
575
|
-
describe("
|
|
525
|
+
describe("globSync", () => {
|
|
576
526
|
it("searches files by glob pattern", () => {
|
|
577
527
|
fs.writeFileSync(path.join(testDir, "a.txt"), "");
|
|
578
528
|
fs.writeFileSync(path.join(testDir, "b.txt"), "");
|
|
579
529
|
fs.writeFileSync(path.join(testDir, "c.js"), "");
|
|
580
530
|
|
|
581
|
-
const txtFiles =
|
|
531
|
+
const txtFiles = globSync(path.join(testDir, "*.txt"));
|
|
582
532
|
|
|
583
533
|
expect(txtFiles.length).toBe(2);
|
|
584
534
|
expect(txtFiles.some((f) => f.endsWith("a.txt"))).toBe(true);
|
|
@@ -589,7 +539,7 @@ describe("fs functions", () => {
|
|
|
589
539
|
fs.mkdirSync(path.join(testDir, "nested"));
|
|
590
540
|
fs.writeFileSync(path.join(testDir, "nested/deep.txt"), "");
|
|
591
541
|
|
|
592
|
-
const files =
|
|
542
|
+
const files = globSync(path.join(testDir, "**/*.txt"));
|
|
593
543
|
|
|
594
544
|
expect(files.some((f) => f.endsWith("deep.txt"))).toBe(true);
|
|
595
545
|
});
|
|
@@ -598,19 +548,19 @@ describe("fs functions", () => {
|
|
|
598
548
|
fs.writeFileSync(path.join(testDir, ".hidden"), "");
|
|
599
549
|
fs.writeFileSync(path.join(testDir, "visible"), "");
|
|
600
550
|
|
|
601
|
-
const withoutDot =
|
|
602
|
-
const withDot =
|
|
551
|
+
const withoutDot = globSync(path.join(testDir, "*"));
|
|
552
|
+
const withDot = globSync(path.join(testDir, "*"), { dot: true });
|
|
603
553
|
|
|
604
554
|
expect(withoutDot.some((f) => f.endsWith(".hidden"))).toBe(false);
|
|
605
555
|
expect(withDot.some((f) => f.endsWith(".hidden"))).toBe(true);
|
|
606
556
|
});
|
|
607
557
|
});
|
|
608
558
|
|
|
609
|
-
describe("
|
|
559
|
+
describe("glob", () => {
|
|
610
560
|
it("searches files asynchronously by glob pattern", async () => {
|
|
611
561
|
fs.writeFileSync(path.join(testDir, "async.txt"), "");
|
|
612
562
|
|
|
613
|
-
const files = await
|
|
563
|
+
const files = await glob(path.join(testDir, "*.txt"));
|
|
614
564
|
|
|
615
565
|
expect(files.length).toBeGreaterThan(0);
|
|
616
566
|
});
|
|
@@ -620,12 +570,12 @@ describe("fs functions", () => {
|
|
|
620
570
|
|
|
621
571
|
//#region clearEmptyDirectoryAsync
|
|
622
572
|
|
|
623
|
-
describe("
|
|
573
|
+
describe("clearEmptyDirectory", () => {
|
|
624
574
|
it("recursively deletes empty directories", async () => {
|
|
625
575
|
const emptyDir = path.join(testDir, "empty/nested/deep");
|
|
626
576
|
fs.mkdirSync(emptyDir, { recursive: true });
|
|
627
577
|
|
|
628
|
-
await
|
|
578
|
+
await clearEmptyDirectory(path.join(testDir, "empty"));
|
|
629
579
|
|
|
630
580
|
expect(fs.existsSync(path.join(testDir, "empty"))).toBe(false);
|
|
631
581
|
});
|
|
@@ -635,7 +585,7 @@ describe("fs functions", () => {
|
|
|
635
585
|
fs.mkdirSync(dirWithFile);
|
|
636
586
|
fs.writeFileSync(path.join(dirWithFile, "file.txt"), "content");
|
|
637
587
|
|
|
638
|
-
await
|
|
588
|
+
await clearEmptyDirectory(dirWithFile);
|
|
639
589
|
|
|
640
590
|
expect(fs.existsSync(dirWithFile)).toBe(true);
|
|
641
591
|
});
|
|
@@ -645,14 +595,14 @@ describe("fs functions", () => {
|
|
|
645
595
|
|
|
646
596
|
//#region findAllParentChildPaths
|
|
647
597
|
|
|
648
|
-
describe("
|
|
598
|
+
describe("findAllParentChildPathsSync", () => {
|
|
649
599
|
it("finds specific file in parent directories", () => {
|
|
650
600
|
const deepDir = path.join(testDir, "a/b/c");
|
|
651
601
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
652
602
|
fs.writeFileSync(path.join(testDir, "marker.txt"), "");
|
|
653
603
|
fs.writeFileSync(path.join(testDir, "a/marker.txt"), "");
|
|
654
604
|
|
|
655
|
-
const results =
|
|
605
|
+
const results = findAllParentChildPathsSync("marker.txt", deepDir, testDir);
|
|
656
606
|
|
|
657
607
|
expect(results.length).toBe(2);
|
|
658
608
|
});
|
|
@@ -661,20 +611,20 @@ describe("fs functions", () => {
|
|
|
661
611
|
const deepDir = path.join(testDir, "a/b/c");
|
|
662
612
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
663
613
|
|
|
664
|
-
const results =
|
|
614
|
+
const results = findAllParentChildPathsSync("nonexistent-file.txt", deepDir, testDir);
|
|
665
615
|
|
|
666
616
|
expect(results).toEqual([]);
|
|
667
617
|
});
|
|
668
618
|
});
|
|
669
619
|
|
|
670
|
-
describe("
|
|
620
|
+
describe("findAllParentChildPaths", () => {
|
|
671
621
|
it("finds specific file in parent directories asynchronously", async () => {
|
|
672
622
|
const deepDir = path.join(testDir, "x/y/z");
|
|
673
623
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
674
624
|
fs.writeFileSync(path.join(testDir, "config.json"), "");
|
|
675
625
|
fs.writeFileSync(path.join(testDir, "x/config.json"), "");
|
|
676
626
|
|
|
677
|
-
const results = await
|
|
627
|
+
const results = await findAllParentChildPaths("config.json", deepDir, testDir);
|
|
678
628
|
|
|
679
629
|
expect(results.length).toBe(2);
|
|
680
630
|
});
|
|
@@ -683,7 +633,7 @@ describe("fs functions", () => {
|
|
|
683
633
|
const deepDir = path.join(testDir, "x/y/z");
|
|
684
634
|
fs.mkdirSync(deepDir, { recursive: true });
|
|
685
635
|
|
|
686
|
-
const results = await
|
|
636
|
+
const results = await findAllParentChildPaths("nonexistent-file.txt", deepDir, testDir);
|
|
687
637
|
|
|
688
638
|
expect(results).toEqual([]);
|
|
689
639
|
});
|
|
@@ -696,9 +646,9 @@ describe("fs functions", () => {
|
|
|
696
646
|
describe("error cases", () => {
|
|
697
647
|
it("includes path information in SdError when reading nonexistent file", () => {
|
|
698
648
|
const filePath = path.join(testDir, "nonexistent.txt");
|
|
699
|
-
expect(() =>
|
|
649
|
+
expect(() => readSync(filePath)).toThrow(SdError);
|
|
700
650
|
try {
|
|
701
|
-
|
|
651
|
+
readSync(filePath);
|
|
702
652
|
} catch (err) {
|
|
703
653
|
expect((err as Error).message).toContain(filePath);
|
|
704
654
|
}
|
|
@@ -706,20 +656,20 @@ describe("fs functions", () => {
|
|
|
706
656
|
|
|
707
657
|
it("includes path information in SdError when reading nonexistent file asynchronously", async () => {
|
|
708
658
|
const filePath = path.join(testDir, "nonexistent.txt");
|
|
709
|
-
await expect(
|
|
659
|
+
await expect(read(filePath)).rejects.toThrow(SdError);
|
|
710
660
|
try {
|
|
711
|
-
await
|
|
661
|
+
await read(filePath);
|
|
712
662
|
} catch (err) {
|
|
713
663
|
expect((err as Error).message).toContain(filePath);
|
|
714
664
|
}
|
|
715
665
|
});
|
|
716
666
|
|
|
717
667
|
it("throws error when reading nonexistent directory", () => {
|
|
718
|
-
expect(() =>
|
|
668
|
+
expect(() => readdirSync(path.join(testDir, "nonexistent"))).toThrow();
|
|
719
669
|
});
|
|
720
670
|
|
|
721
671
|
it("throws error when stat nonexistent file", () => {
|
|
722
|
-
expect(() =>
|
|
672
|
+
expect(() => statSync(path.join(testDir, "nonexistent.txt"))).toThrow();
|
|
723
673
|
});
|
|
724
674
|
|
|
725
675
|
it("includes path and content information in SdError when reading invalid JSON", () => {
|
|
@@ -727,9 +677,9 @@ describe("fs functions", () => {
|
|
|
727
677
|
const content = "{ invalid json }";
|
|
728
678
|
fs.writeFileSync(filePath, content);
|
|
729
679
|
|
|
730
|
-
expect(() =>
|
|
680
|
+
expect(() => readJsonSync(filePath)).toThrow(SdError);
|
|
731
681
|
try {
|
|
732
|
-
|
|
682
|
+
readJsonSync(filePath);
|
|
733
683
|
} catch (err) {
|
|
734
684
|
expect((err as Error).message).toContain(filePath);
|
|
735
685
|
expect((err as Error).message).toContain(content);
|
|
@@ -741,9 +691,9 @@ describe("fs functions", () => {
|
|
|
741
691
|
const content = "{ invalid json }";
|
|
742
692
|
fs.writeFileSync(filePath, content);
|
|
743
693
|
|
|
744
|
-
await expect(
|
|
694
|
+
await expect(readJson(filePath)).rejects.toThrow(SdError);
|
|
745
695
|
try {
|
|
746
|
-
await
|
|
696
|
+
await readJson(filePath);
|
|
747
697
|
} catch (err) {
|
|
748
698
|
expect((err as Error).message).toContain(filePath);
|
|
749
699
|
expect((err as Error).message).toContain(content);
|