@wener/common 2.0.5 → 2.0.6

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 (206) hide show
  1. package/lib/ai/qwen3vl/index.js +1 -1
  2. package/lib/ai/qwen3vl/utils.js +15 -15
  3. package/lib/ai/vision/DocLayoutElementTypeSchema.js +22 -22
  4. package/lib/ai/vision/ImageAnnotationSchema.js +63 -47
  5. package/lib/ai/vision/index.js +2 -2
  6. package/lib/ai/vision/resolveImageAnnotation.js +81 -95
  7. package/lib/cn/ChineseResidentIdNo.js +55 -41
  8. package/lib/cn/ChineseResidentIdNo.mod.js +6 -1
  9. package/lib/cn/ChineseResidentIdNo.test.js +22 -21
  10. package/lib/cn/DivisionCode.js +220 -235
  11. package/lib/cn/DivisionCode.mod.js +6 -1
  12. package/lib/cn/DivisionCode.test.js +92 -121
  13. package/lib/cn/Mod11.js +18 -37
  14. package/lib/cn/Mod31.js +23 -41
  15. package/lib/cn/UnifiedSocialCreditCode.js +143 -137
  16. package/lib/cn/UnifiedSocialCreditCode.mod.js +6 -1
  17. package/lib/cn/UnifiedSocialCreditCode.test.js +21 -15
  18. package/lib/cn/formatChineseAmount.js +46 -71
  19. package/lib/cn/index.js +6 -6
  20. package/lib/cn/mod.js +5 -3
  21. package/lib/cn/parseChineseNumber.js +81 -85
  22. package/lib/cn/parseChineseNumber.test.js +183 -261
  23. package/lib/cn/pinyin/cartesianProduct.js +19 -19
  24. package/lib/cn/pinyin/cartesianProduct.test.js +78 -178
  25. package/lib/cn/pinyin/loader.js +13 -11
  26. package/lib/cn/pinyin/preload.js +2 -1
  27. package/lib/cn/pinyin/toPinyin.test.js +149 -161
  28. package/lib/cn/pinyin/toPinyinPure.js +28 -23
  29. package/lib/cn/pinyin/transform.js +11 -11
  30. package/lib/cn/types.d.js +2 -2
  31. package/lib/consola/createStandardConsolaReporter.js +14 -15
  32. package/lib/consola/formatLogObject.js +149 -133
  33. package/lib/consola/formatLogObject.test.js +167 -178
  34. package/lib/consola/index.js +2 -2
  35. package/lib/data/formatSort.js +14 -12
  36. package/lib/data/formatSort.test.js +33 -33
  37. package/lib/data/index.js +3 -3
  38. package/lib/data/maybeNumber.js +23 -23
  39. package/lib/data/parseSort.js +75 -68
  40. package/lib/data/parseSort.test.js +196 -187
  41. package/lib/data/resolvePagination.js +38 -39
  42. package/lib/data/resolvePagination.test.js +228 -218
  43. package/lib/data/types.d.js +2 -2
  44. package/lib/dayjs/dayjs.js +20 -20
  45. package/lib/dayjs/formatDuration.js +56 -56
  46. package/lib/dayjs/formatDuration.test.js +63 -77
  47. package/lib/dayjs/index.js +4 -4
  48. package/lib/dayjs/parseDuration.js +21 -26
  49. package/lib/dayjs/parseRelativeTime.js +65 -66
  50. package/lib/dayjs/parseRelativeTime.test.js +227 -243
  51. package/lib/dayjs/resolveRelativeTime.js +73 -72
  52. package/lib/dayjs/resolveRelativeTime.test.js +296 -307
  53. package/lib/decimal/index.js +1 -1
  54. package/lib/decimal/parseDecimal.js +12 -12
  55. package/lib/drain3/Drain.js +303 -338
  56. package/lib/drain3/LogCluster.js +25 -25
  57. package/lib/drain3/Node.js +24 -24
  58. package/lib/drain3/TemplateMiner.js +197 -196
  59. package/lib/drain3/index.js +5 -5
  60. package/lib/drain3/persistence/FilePersistence.js +19 -19
  61. package/lib/drain3/persistence/MemoryPersistence.js +8 -8
  62. package/lib/drain3/persistence/PersistenceHandler.js +2 -2
  63. package/lib/drain3/types.js +2 -2
  64. package/lib/emittery/emitter.js +7 -7
  65. package/lib/emittery/index.js +1 -1
  66. package/lib/foundation/schema/SexType.js +15 -12
  67. package/lib/foundation/schema/index.js +1 -1
  68. package/lib/foundation/schema/parseSexType.js +15 -16
  69. package/lib/foundation/schema/types.js +8 -6
  70. package/lib/fs/FileSystemError.js +18 -18
  71. package/lib/fs/IFileSystem.d.js +2 -2
  72. package/lib/fs/MemoryFileSystem.test.js +172 -181
  73. package/lib/fs/createBrowserFileSystem.js +222 -235
  74. package/lib/fs/createMemoryFileSystem.js +472 -510
  75. package/lib/fs/createSandboxFileSystem.js +102 -101
  76. package/lib/fs/createWebDavFileSystem.js +162 -149
  77. package/lib/fs/createWebFileSystem.js +197 -220
  78. package/lib/fs/findMimeType.js +14 -14
  79. package/lib/fs/index.js +7 -7
  80. package/lib/fs/minio/createMinioFileSystem.js +959 -956
  81. package/lib/fs/minio/index.js +1 -1
  82. package/lib/fs/orpc/FileSystemContract.js +57 -57
  83. package/lib/fs/orpc/createContractClientFileSystem.js +88 -88
  84. package/lib/fs/orpc/index.js +2 -2
  85. package/lib/fs/orpc/server/createFileSystemContractImpl.js +62 -60
  86. package/lib/fs/orpc/server/index.js +1 -1
  87. package/lib/fs/s3/createS3MiniFileSystem.js +756 -737
  88. package/lib/fs/s3/index.js +1 -1
  89. package/lib/fs/s3/s3mini.test.js +524 -553
  90. package/lib/fs/scandir.js +56 -56
  91. package/lib/fs/server/createDatabaseFileSystem.js +834 -741
  92. package/lib/fs/server/createNodeFileSystem.js +407 -405
  93. package/lib/fs/server/dbfs.test.js +201 -214
  94. package/lib/fs/server/index.js +1 -1
  95. package/lib/fs/server/loadTestDatabase.js +40 -43
  96. package/lib/fs/tests/runFileSystemTest.js +352 -316
  97. package/lib/fs/types.js +17 -20
  98. package/lib/fs/utils/getFileUrl.js +24 -30
  99. package/lib/fs/utils.js +17 -17
  100. package/lib/fs/webdav/index.js +1 -1
  101. package/lib/index.js +2 -2
  102. package/lib/jsonschema/JsonSchema.js +216 -155
  103. package/lib/jsonschema/JsonSchema.test.js +123 -124
  104. package/lib/jsonschema/forEachJsonSchema.js +41 -41
  105. package/lib/jsonschema/index.js +2 -2
  106. package/lib/jsonschema/types.d.js +2 -2
  107. package/lib/meta/defineFileType.js +32 -38
  108. package/lib/meta/defineInit.js +39 -35
  109. package/lib/meta/defineMetadata.js +37 -34
  110. package/lib/meta/defineMetadata.test.js +13 -12
  111. package/lib/meta/index.js +3 -3
  112. package/lib/orpc/createOpenApiContractClient.js +26 -24
  113. package/lib/orpc/createRpcContractClient.js +37 -31
  114. package/lib/orpc/index.js +2 -2
  115. package/lib/orpc/resolveLinkPlugins.js +25 -25
  116. package/lib/password/PHC.js +187 -189
  117. package/lib/password/PHC.test.js +517 -535
  118. package/lib/password/Password.js +85 -80
  119. package/lib/password/Password.test.js +330 -364
  120. package/lib/password/createArgon2PasswordAlgorithm.js +50 -51
  121. package/lib/password/createBase64PasswordAlgorithm.js +11 -11
  122. package/lib/password/createBcryptPasswordAlgorithm.js +20 -18
  123. package/lib/password/createPBKDF2PasswordAlgorithm.js +65 -52
  124. package/lib/password/createScryptPasswordAlgorithm.js +74 -63
  125. package/lib/password/index.js +5 -5
  126. package/lib/password/server/index.js +1 -1
  127. package/lib/resource/Identifiable.js +2 -2
  128. package/lib/resource/ListQuery.js +42 -42
  129. package/lib/resource/getTitleOfResource.js +5 -5
  130. package/lib/resource/index.js +2 -2
  131. package/lib/resource/schema/AnyResourceSchema.js +91 -89
  132. package/lib/resource/schema/BaseResourceSchema.js +26 -26
  133. package/lib/resource/schema/ResourceActionType.js +117 -115
  134. package/lib/resource/schema/ResourceStatus.js +94 -92
  135. package/lib/resource/schema/ResourceType.js +25 -23
  136. package/lib/resource/schema/index.js +5 -5
  137. package/lib/resource/schema/types.js +86 -55
  138. package/lib/resource/schema/types.test.js +16 -13
  139. package/lib/s3/formatS3Url.js +60 -60
  140. package/lib/s3/formatS3Url.test.js +238 -261
  141. package/lib/s3/index.js +2 -2
  142. package/lib/s3/parseS3Url.js +61 -60
  143. package/lib/s3/parseS3Url.test.js +270 -269
  144. package/lib/schema/SchemaRegistry.js +41 -42
  145. package/lib/schema/SchemaRegistry.mod.js +1 -1
  146. package/lib/schema/TypeSchema.d.js +2 -2
  147. package/lib/schema/createSchemaData.js +113 -67
  148. package/lib/schema/findJsonSchemaByPath.js +28 -23
  149. package/lib/schema/formatZodError.js +112 -131
  150. package/lib/schema/formatZodError.test.js +192 -195
  151. package/lib/schema/getSchemaCache.js +7 -7
  152. package/lib/schema/getSchemaOptions.js +17 -16
  153. package/lib/schema/index.js +6 -6
  154. package/lib/schema/toJsonSchema.js +195 -189
  155. package/lib/schema/toJsonSchema.test.js +34 -26
  156. package/lib/schema/validate.js +105 -96
  157. package/lib/tools/generateSchema.js +40 -40
  158. package/lib/tools/renderJsonSchemaToMarkdownDoc.js +74 -74
  159. package/lib/utils/buildBaseUrl.js +8 -8
  160. package/lib/utils/buildRedactorFormSchema.js +54 -53
  161. package/lib/utils/getEstimateProcessTime.js +24 -19
  162. package/lib/utils/index.js +3 -3
  163. package/lib/utils/resolveFeatureOptions.js +9 -9
  164. package/package.json +14 -14
  165. package/src/ai/vision/index.ts +2 -2
  166. package/src/cn/index.ts +1 -2
  167. package/src/consola/index.ts +1 -1
  168. package/src/data/index.ts +3 -4
  169. package/src/data/resolvePagination.ts +2 -2
  170. package/src/dayjs/formatDuration.ts +8 -9
  171. package/src/dayjs/index.ts +1 -1
  172. package/src/dayjs/parseRelativeTime.ts +1 -1
  173. package/src/dayjs/resolveRelativeTime.ts +1 -1
  174. package/src/drain3/Drain.test.ts +2 -2
  175. package/src/drain3/index.ts +2 -4
  176. package/src/fs/createWebDavFileSystem.ts +2 -7
  177. package/src/fs/createWebFileSystem.ts +1 -1
  178. package/src/fs/index.ts +4 -4
  179. package/src/fs/minio/createMinioFileSystem.ts +2 -2
  180. package/src/fs/minio/index.ts +1 -1
  181. package/src/fs/s3/createS3MiniFileSystem.ts +1 -1
  182. package/src/fs/server/createDatabaseFileSystem.ts +84 -120
  183. package/src/fs/server/dbfs.test.ts +14 -10
  184. package/src/fs/server/index.ts +1 -0
  185. package/src/fs/server/loadTestDatabase.ts +8 -119
  186. package/src/jsonschema/index.ts +1 -1
  187. package/src/meta/index.ts +2 -3
  188. package/src/orm/createSqliteDialect.ts +17 -0
  189. package/src/orm/index.ts +1 -0
  190. package/src/orpc/createOpenApiContractClient.ts +1 -1
  191. package/src/orpc/index.ts +1 -1
  192. package/src/password/createArgon2PasswordAlgorithm.ts +1 -1
  193. package/src/password/index.ts +2 -2
  194. package/src/resource/index.ts +3 -3
  195. package/src/resource/schema/index.ts +4 -4
  196. package/src/s3/index.ts +1 -1
  197. package/src/schema/SchemaRegistry.ts +1 -1
  198. package/src/schema/createSchemaData.ts +1 -1
  199. package/src/schema/findJsonSchemaByPath.ts +1 -1
  200. package/src/schema/index.ts +5 -5
  201. package/src/schema/validate.ts +1 -1
  202. package/src/utils/buildRedactorFormSchema.ts +1 -1
  203. package/src/utils/formatNumber.ts +18 -0
  204. package/src/utils/formatPercent.ts +17 -0
  205. package/src/utils/index.ts +3 -3
  206. package/src/utils/resolveFeatureOptions.ts +1 -1
@@ -1,319 +1,355 @@
1
- import { expect } from "vitest";
2
- import { FileSystemError, FileSystemErrorCode } from "../FileSystemError.js";
1
+ import { expect } from 'vitest';
2
+ import { FileSystemError, FileSystemErrorCode } from '../FileSystemError.js';
3
3
  export async function runFileSystemTest(fs, options = {}) {
4
- const { writableStream = true, readableStream = true, readStream = true, writeStream = true, abort = true } = options;
5
- // should be implemented
6
- const stat = await fs.stat("/README.txt");
7
- expect(stat).toMatchObject({
8
- path: "/README.txt",
9
- directory: "/",
10
- name: "README.txt",
11
- kind: "file",
12
- size: 5
13
- });
14
- await fs.mkdir("/");
15
- const entries = await fs.readdir("/");
16
- expect(entries.some((e) => e.name === "README.txt")).toBe(true);
17
- await fs.mkdir("/test");
18
- if (fs.getUrl) {
19
- expect(fs.getUrl(await fs.stat("/README.txt"))).toBeTypeOf("string");
20
- }
21
- // should handle AbortSignal
22
- if (abort) {
23
- const controller = new AbortController();
24
- controller.abort();
25
- await expect(fs.stat("/README.txt", {
26
- signal: controller.signal
27
- })).rejects.toThrow(Error);
28
- await expect(fs.readdir("/", {
29
- signal: controller.signal
30
- })).rejects.toThrow(Error);
31
- await expect(fs.mkdir("/test", {
32
- signal: controller.signal
33
- })).rejects.toThrow(Error);
34
- await expect(fs.readFile("/README.txt", {
35
- signal: controller.signal
36
- })).rejects.toThrow(Error);
37
- await expect(fs.writeFile("/test.txt", "test", {
38
- signal: controller.signal
39
- })).rejects.toThrow(Error);
40
- await expect(fs.rm("/README.txt", {
41
- signal: controller.signal
42
- })).rejects.toThrow(Error);
43
- await expect(fs.rename("/README.txt", "/new.txt", {
44
- signal: controller.signal
45
- })).rejects.toThrow(Error);
46
- await expect(fs.copy("/README.txt", "/copy.txt", {
47
- signal: controller.signal
48
- })).rejects.toThrow(Error);
49
- }
50
- // should validate input parameters
51
- await expect(fs.stat("")).rejects.toThrow(FileSystemError);
52
- await expect(fs.stat("")).rejects.toMatchObject({
53
- code: FileSystemErrorCode.EINVAL
54
- });
55
- await expect(fs.stat(null)).rejects.toThrow(FileSystemError);
56
- await expect(fs.stat(null)).rejects.toMatchObject({
57
- code: FileSystemErrorCode.EINVAL
58
- });
59
- await expect(fs.stat(undefined)).rejects.toThrow(FileSystemError);
60
- await expect(fs.stat(undefined)).rejects.toMatchObject({
61
- code: FileSystemErrorCode.EINVAL
62
- });
63
- await expect(fs.stat(123)).rejects.toThrow(FileSystemError);
64
- await expect(fs.stat(123)).rejects.toMatchObject({
65
- code: FileSystemErrorCode.EINVAL
66
- });
67
- await expect(fs.writeFile("", "test")).rejects.toThrow(FileSystemError);
68
- await expect(fs.writeFile("", "test")).rejects.toMatchObject({
69
- code: FileSystemErrorCode.EINVAL
70
- });
71
- await expect(fs.writeFile("/test", null)).rejects.toThrow(FileSystemError);
72
- await expect(fs.writeFile("/test", null)).rejects.toMatchObject({
73
- code: FileSystemErrorCode.EINVAL
74
- });
75
- await expect(fs.writeFile("/test", undefined)).rejects.toThrow(FileSystemError);
76
- await expect(fs.writeFile("/test", undefined)).rejects.toMatchObject({
77
- code: FileSystemErrorCode.EINVAL
78
- });
79
- await expect(fs.writeFile("/", "test")).rejects.toThrow(FileSystemError);
80
- await expect(fs.writeFile("/", "test")).rejects.toMatchObject({
81
- code: FileSystemErrorCode.EINVAL
82
- });
83
- // should support streaming operations
84
- const serverFs = fs;
85
- if (readStream && "createReadStream" in fs) {
86
- await fs.writeFile("/stream.txt", "Hello, World!");
87
- // Test createReadStream
88
- const readStreamObj = serverFs.createReadStream("/stream.txt");
89
- expect(readStreamObj).toBeDefined();
90
- const chunks = [];
91
- for await (const chunk of readStreamObj) {
92
- chunks.push(chunk);
93
- }
94
- expect(Buffer.concat(chunks).toString()).toBe("Hello, World!");
95
- // Test createReadStream with range
96
- const rangeStream = serverFs.createReadStream("/stream.txt", {
97
- range: {
98
- start: 0,
99
- end: 4
100
- }
101
- });
102
- const rangeChunks = [];
103
- for await (const chunk of rangeStream) {
104
- rangeChunks.push(chunk);
105
- }
106
- expect(Buffer.concat(rangeChunks).toString()).toBe("Hello");
107
- }
108
- if (writeStream && "createWriteStream" in fs) {
109
- // Test createWriteStream
110
- const writeStreamObj = serverFs.createWriteStream("/write-test.txt");
111
- expect(writeStreamObj).toBeDefined();
112
- writeStreamObj.write("Test content");
113
- writeStreamObj.end();
114
- await new Promise((resolve) => writeStreamObj.on("finish", resolve));
115
- expect(await fs.readFile("/write-test.txt", {
116
- encoding: "text"
117
- })).toBe("Test content");
118
- }
119
- // should support Web Streams API
120
- if (readableStream && fs.createReadableStream) {
121
- await fs.writeFile("/webstream.txt", "Web Stream Test");
122
- // Test createReadableStream
123
- const readableStreamObj = fs.createReadableStream("/webstream.txt");
124
- expect(readableStreamObj).toBeDefined();
125
- const reader = readableStreamObj.getReader();
126
- const { value } = await reader.read();
127
- expect(value?.toString()).toBe("Web Stream Test");
128
- }
129
- if (writableStream && fs.createWritableStream) {
130
- // Test createWritableStream
131
- const writableStreamObj = fs.createWritableStream("/web-write-test.txt");
132
- expect(writableStreamObj).toBeDefined();
133
- const writer = writableStreamObj.getWriter();
134
- await writer.write(Buffer.from("Web Stream Write Test"));
135
- await writer.close();
136
- expect(await fs.readFile("/web-write-test.txt", {
137
- encoding: "text"
138
- })).toBe("Web Stream Write Test");
139
- }
140
- // should handle streaming errors
141
- if (abort && readStream && "createReadStream" in fs) {
142
- const controller2 = new AbortController();
143
- // Test read stream with abort
144
- const readStreamObj = serverFs.createReadStream("/README.txt", {
145
- signal: controller2.signal
146
- });
147
- controller2.abort();
148
- await expect(new Promise((_, reject) => {
149
- readStreamObj.on("error", reject);
150
- })).rejects.toThrow(Error);
151
- }
152
- if (abort && writeStream && "createWriteStream" in fs) {
153
- // Test write stream with abort
154
- const controller3 = new AbortController();
155
- const writeStreamObj = serverFs.createWriteStream("/abort-test.txt", {
156
- signal: controller3.signal
157
- });
158
- controller3.abort();
159
- await expect(new Promise((_, reject) => {
160
- writeStreamObj.on("error", reject);
161
- writeStreamObj.write("test");
162
- })).rejects.toThrow(Error);
163
- }
164
- // should handle file operations correctly
165
- // Test file creation
166
- await fs.writeFile("/newfile.txt", "New content");
167
- expect(await fs.exists("/newfile.txt")).toBe(true);
168
- const stat2 = await fs.stat("/newfile.txt");
169
- expect(stat2.kind).toBe("file");
170
- expect(stat2.size).toBe(11); // "New content" is 11 bytes
171
- // Test file reading
172
- const content = await fs.readFile("/newfile.txt", {
173
- encoding: "text"
174
- });
175
- expect(content).toBe("New content");
176
- // Test file reading as binary
177
- const binary = await fs.readFile("/newfile.txt");
178
- expect(Buffer.from(binary).toString()).toBe("New content");
179
- // Test file overwrite
180
- await fs.writeFile("/newfile.txt", "Updated content");
181
- expect(await fs.readFile("/newfile.txt", {
182
- encoding: "text"
183
- })).toBe("Updated content");
184
- // Test file overwrite protection
185
- await expect(fs.writeFile("/newfile.txt", "Should fail", {
186
- overwrite: false
187
- })).rejects.toThrow(FileSystemError);
188
- await expect(fs.writeFile("/newfile.txt", "Should fail", {
189
- overwrite: false
190
- })).rejects.toMatchObject({
191
- code: FileSystemErrorCode.EEXIST
192
- });
193
- // Test large file write (should use file_node_content table)
194
- // Create ~1KB data to test large file handling
195
- const largeData = "x".repeat(1024); // 1KB of data
196
- await fs.writeFile("/largefile.txt", largeData);
197
- const largeFileStat = await fs.stat("/largefile.txt");
198
- expect(largeFileStat.size).toBe(1024);
199
- const largeFileContent = await fs.readFile("/largefile.txt", {
200
- encoding: "text"
201
- });
202
- expect(largeFileContent).toBe(largeData);
203
- expect(largeFileContent.length).toBe(1024);
204
- // should handle directory operations correctly
205
- // Test directory creation
206
- await fs.mkdir("/newdir");
207
- expect(await fs.exists("/newdir")).toBe(true);
208
- const stat3 = await fs.stat("/newdir");
209
- expect(stat3.kind).toBe("directory");
210
- // Test recursive directory creation
211
- await fs.mkdir("/deep/nested/dir", {
212
- recursive: true
213
- });
214
- expect(await fs.exists("/deep/nested/dir")).toBe(true);
215
- // Test non-recursive directory creation failure
216
- await expect(fs.mkdir("/another/deep/dir")).rejects.toThrow(FileSystemError);
217
- await expect(fs.mkdir("/another/deep/dir")).rejects.toMatchObject({
218
- code: FileSystemErrorCode.ENOENT
219
- });
220
- // Test directory listing
221
- await fs.writeFile("/newdir/file1.txt", "File 1");
222
- await fs.writeFile("/newdir/file2.txt", "File 2");
223
- const contents = await fs.readdir("/newdir");
224
- expect(contents).toHaveLength(2);
225
- expect(contents.map((f) => f.name)).toContain("file1.txt");
226
- expect(contents.map((f) => f.name)).toContain("file2.txt");
227
- // should handle file removal correctly
228
- await fs.writeFile("/toremove.txt", "Remove me");
229
- expect(await fs.exists("/toremove.txt")).toBe(true);
230
- await fs.rm("/toremove.txt");
231
- expect(await fs.exists("/toremove.txt")).toBe(false);
232
- // Test force removal
233
- await expect(fs.rm("/nonexistent.txt")).rejects.toThrow(FileSystemError);
234
- await expect(fs.rm("/nonexistent.txt")).rejects.toMatchObject({
235
- code: FileSystemErrorCode.ENOENT
236
- });
237
- await fs.rm("/nonexistent.txt", {
238
- force: true
239
- }); // Should not throw
240
- // Test recursive removal
241
- await fs.mkdir("/dirwithfiles", {
242
- recursive: true
243
- });
244
- await fs.writeFile("/dirwithfiles/file.txt", "content");
245
- await expect(fs.rm("/dirwithfiles")).rejects.toThrow(FileSystemError);
246
- await expect(fs.rm("/dirwithfiles")).rejects.toMatchObject({
247
- code: FileSystemErrorCode.ENOTEMPTY
248
- });
249
- await fs.rm("/dirwithfiles", {
250
- recursive: true
251
- });
252
- expect(await fs.exists("/dirwithfiles")).toBe(false);
253
- // should handle file rename correctly
254
- await fs.writeFile("/rename.txt", "Original content");
255
- expect(await fs.exists("/rename.txt")).toBe(true);
256
- await fs.rename("/rename.txt", "/renamed.txt");
257
- expect(await fs.exists("/rename.txt")).toBe(false);
258
- expect(await fs.exists("/renamed.txt")).toBe(true);
259
- expect(await fs.readFile("/renamed.txt", {
260
- encoding: "text"
261
- })).toBe("Original content");
262
- // should handle file copy correctly
263
- await fs.writeFile("/copy.txt", "Copy me");
264
- expect(await fs.exists("/copy.txt")).toBe(true);
265
- await fs.copy("/copy.txt", "/copied.txt");
266
- expect(await fs.exists("/copy.txt")).toBe(true);
267
- expect(await fs.exists("/copied.txt")).toBe(true);
268
- expect(await fs.readFile("/copied.txt", {
269
- encoding: "text"
270
- })).toBe("Copy me");
271
- // Test copy overwrite
272
- await fs.writeFile("/target2.txt", "Target content");
273
- await expect(fs.copy("/copy.txt", "/target2.txt")).rejects.toThrow(FileSystemError);
274
- await expect(fs.copy("/copy.txt", "/target2.txt")).rejects.toMatchObject({
275
- code: FileSystemErrorCode.EEXIST
276
- });
277
- await fs.copy("/copy.txt", "/target2.txt", {
278
- overwrite: true
279
- });
280
- expect(await fs.readFile("/target2.txt", {
281
- encoding: "text"
282
- })).toBe("Copy me");
283
- // should handle edge cases correctly
284
- // Test root directory operations
285
- await expect(fs.stat("/")).resolves.toBeDefined();
286
- await expect(fs.readdir("/")).resolves.toBeDefined();
287
- await fs.mkdir("/"); // Should not throw
288
- // Test path normalization
289
- await fs.writeFile("/normalize.txt", "test");
290
- expect(await fs.exists("/normalize.txt")).toBe(true);
291
- expect(await fs.exists("/./normalize.txt")).toBe(true);
292
- // Note: the exists method may return true for files with trailing slashes due to normalization
293
- // Test error cases
294
- await expect(fs.stat("/nonexistent")).rejects.toThrow(FileSystemError);
295
- await expect(fs.stat("/nonexistent")).rejects.toMatchObject({
296
- code: FileSystemErrorCode.ENOENT
297
- });
298
- await expect(fs.readdir("/nonexistent")).rejects.toThrow(FileSystemError);
299
- await expect(fs.readdir("/nonexistent")).rejects.toMatchObject({
300
- code: FileSystemErrorCode.ENOENT
301
- });
302
- await expect(fs.readFile("/nonexistent")).rejects.toThrow(FileSystemError);
303
- await expect(fs.readFile("/nonexistent")).rejects.toMatchObject({
304
- code: FileSystemErrorCode.ENOENT
305
- });
306
- await expect(fs.rm("/nonexistent")).rejects.toThrow(FileSystemError);
307
- await expect(fs.rm("/nonexistent")).rejects.toMatchObject({
308
- code: FileSystemErrorCode.ENOENT
309
- });
310
- await expect(fs.rename("/nonexistent", "/new")).rejects.toThrow(FileSystemError);
311
- await expect(fs.rename("/nonexistent", "/new")).rejects.toMatchObject({
312
- code: FileSystemErrorCode.ENOENT
313
- });
314
- await expect(fs.copy("/nonexistent", "/new")).rejects.toThrow(FileSystemError);
315
- await expect(fs.copy("/nonexistent", "/new")).rejects.toMatchObject({
316
- code: FileSystemErrorCode.ENOENT
317
- });
4
+ const { writableStream = true, readableStream = true, readStream = true, writeStream = true, abort = true } = options;
5
+ // should be implemented
6
+ const stat = await fs.stat('/README.txt');
7
+ expect(stat).toMatchObject({
8
+ path: '/README.txt',
9
+ directory: '/',
10
+ name: 'README.txt',
11
+ kind: 'file',
12
+ size: 5,
13
+ });
14
+ await fs.mkdir('/');
15
+ const entries = await fs.readdir('/');
16
+ expect(entries.some((e) => e.name === 'README.txt')).toBe(true);
17
+ await fs.mkdir('/test');
18
+ if (fs.getUrl) {
19
+ expect(fs.getUrl(await fs.stat('/README.txt'))).toBeTypeOf('string');
20
+ }
21
+ // should handle AbortSignal
22
+ if (abort) {
23
+ const controller = new AbortController();
24
+ controller.abort();
25
+ await expect(
26
+ fs.stat('/README.txt', {
27
+ signal: controller.signal,
28
+ }),
29
+ ).rejects.toThrow(Error);
30
+ await expect(
31
+ fs.readdir('/', {
32
+ signal: controller.signal,
33
+ }),
34
+ ).rejects.toThrow(Error);
35
+ await expect(
36
+ fs.mkdir('/test', {
37
+ signal: controller.signal,
38
+ }),
39
+ ).rejects.toThrow(Error);
40
+ await expect(
41
+ fs.readFile('/README.txt', {
42
+ signal: controller.signal,
43
+ }),
44
+ ).rejects.toThrow(Error);
45
+ await expect(
46
+ fs.writeFile('/test.txt', 'test', {
47
+ signal: controller.signal,
48
+ }),
49
+ ).rejects.toThrow(Error);
50
+ await expect(
51
+ fs.rm('/README.txt', {
52
+ signal: controller.signal,
53
+ }),
54
+ ).rejects.toThrow(Error);
55
+ await expect(
56
+ fs.rename('/README.txt', '/new.txt', {
57
+ signal: controller.signal,
58
+ }),
59
+ ).rejects.toThrow(Error);
60
+ await expect(
61
+ fs.copy('/README.txt', '/copy.txt', {
62
+ signal: controller.signal,
63
+ }),
64
+ ).rejects.toThrow(Error);
65
+ }
66
+ // should validate input parameters
67
+ await expect(fs.stat('')).rejects.toThrow(FileSystemError);
68
+ await expect(fs.stat('')).rejects.toMatchObject({
69
+ code: FileSystemErrorCode.EINVAL,
70
+ });
71
+ await expect(fs.stat(null)).rejects.toThrow(FileSystemError);
72
+ await expect(fs.stat(null)).rejects.toMatchObject({
73
+ code: FileSystemErrorCode.EINVAL,
74
+ });
75
+ await expect(fs.stat(undefined)).rejects.toThrow(FileSystemError);
76
+ await expect(fs.stat(undefined)).rejects.toMatchObject({
77
+ code: FileSystemErrorCode.EINVAL,
78
+ });
79
+ await expect(fs.stat(123)).rejects.toThrow(FileSystemError);
80
+ await expect(fs.stat(123)).rejects.toMatchObject({
81
+ code: FileSystemErrorCode.EINVAL,
82
+ });
83
+ await expect(fs.writeFile('', 'test')).rejects.toThrow(FileSystemError);
84
+ await expect(fs.writeFile('', 'test')).rejects.toMatchObject({
85
+ code: FileSystemErrorCode.EINVAL,
86
+ });
87
+ await expect(fs.writeFile('/test', null)).rejects.toThrow(FileSystemError);
88
+ await expect(fs.writeFile('/test', null)).rejects.toMatchObject({
89
+ code: FileSystemErrorCode.EINVAL,
90
+ });
91
+ await expect(fs.writeFile('/test', undefined)).rejects.toThrow(FileSystemError);
92
+ await expect(fs.writeFile('/test', undefined)).rejects.toMatchObject({
93
+ code: FileSystemErrorCode.EINVAL,
94
+ });
95
+ await expect(fs.writeFile('/', 'test')).rejects.toThrow(FileSystemError);
96
+ await expect(fs.writeFile('/', 'test')).rejects.toMatchObject({
97
+ code: FileSystemErrorCode.EINVAL,
98
+ });
99
+ // should support streaming operations
100
+ const serverFs = fs;
101
+ if (readStream && 'createReadStream' in fs) {
102
+ await fs.writeFile('/stream.txt', 'Hello, World!');
103
+ // Test createReadStream
104
+ const readStreamObj = serverFs.createReadStream('/stream.txt');
105
+ expect(readStreamObj).toBeDefined();
106
+ const chunks = [];
107
+ for await (const chunk of readStreamObj) {
108
+ chunks.push(chunk);
109
+ }
110
+ expect(Buffer.concat(chunks).toString()).toBe('Hello, World!');
111
+ // Test createReadStream with range
112
+ const rangeStream = serverFs.createReadStream('/stream.txt', {
113
+ range: {
114
+ start: 0,
115
+ end: 4,
116
+ },
117
+ });
118
+ const rangeChunks = [];
119
+ for await (const chunk of rangeStream) {
120
+ rangeChunks.push(chunk);
121
+ }
122
+ expect(Buffer.concat(rangeChunks).toString()).toBe('Hello');
123
+ }
124
+ if (writeStream && 'createWriteStream' in fs) {
125
+ // Test createWriteStream
126
+ const writeStreamObj = serverFs.createWriteStream('/write-test.txt');
127
+ expect(writeStreamObj).toBeDefined();
128
+ writeStreamObj.write('Test content');
129
+ writeStreamObj.end();
130
+ await new Promise((resolve) => writeStreamObj.on('finish', resolve));
131
+ expect(
132
+ await fs.readFile('/write-test.txt', {
133
+ encoding: 'text',
134
+ }),
135
+ ).toBe('Test content');
136
+ }
137
+ // should support Web Streams API
138
+ if (readableStream && fs.createReadableStream) {
139
+ await fs.writeFile('/webstream.txt', 'Web Stream Test');
140
+ // Test createReadableStream
141
+ const readableStreamObj = fs.createReadableStream('/webstream.txt');
142
+ expect(readableStreamObj).toBeDefined();
143
+ const reader = readableStreamObj.getReader();
144
+ const { value } = await reader.read();
145
+ expect(value?.toString()).toBe('Web Stream Test');
146
+ }
147
+ if (writableStream && fs.createWritableStream) {
148
+ // Test createWritableStream
149
+ const writableStreamObj = fs.createWritableStream('/web-write-test.txt');
150
+ expect(writableStreamObj).toBeDefined();
151
+ const writer = writableStreamObj.getWriter();
152
+ await writer.write(Buffer.from('Web Stream Write Test'));
153
+ await writer.close();
154
+ expect(
155
+ await fs.readFile('/web-write-test.txt', {
156
+ encoding: 'text',
157
+ }),
158
+ ).toBe('Web Stream Write Test');
159
+ }
160
+ // should handle streaming errors
161
+ if (abort && readStream && 'createReadStream' in fs) {
162
+ const controller2 = new AbortController();
163
+ // Test read stream with abort
164
+ const readStreamObj = serverFs.createReadStream('/README.txt', {
165
+ signal: controller2.signal,
166
+ });
167
+ controller2.abort();
168
+ await expect(
169
+ new Promise((_, reject) => {
170
+ readStreamObj.on('error', reject);
171
+ }),
172
+ ).rejects.toThrow(Error);
173
+ }
174
+ if (abort && writeStream && 'createWriteStream' in fs) {
175
+ // Test write stream with abort
176
+ const controller3 = new AbortController();
177
+ const writeStreamObj = serverFs.createWriteStream('/abort-test.txt', {
178
+ signal: controller3.signal,
179
+ });
180
+ controller3.abort();
181
+ await expect(
182
+ new Promise((_, reject) => {
183
+ writeStreamObj.on('error', reject);
184
+ writeStreamObj.write('test');
185
+ }),
186
+ ).rejects.toThrow(Error);
187
+ }
188
+ // should handle file operations correctly
189
+ // Test file creation
190
+ await fs.writeFile('/newfile.txt', 'New content');
191
+ expect(await fs.exists('/newfile.txt')).toBe(true);
192
+ const stat2 = await fs.stat('/newfile.txt');
193
+ expect(stat2.kind).toBe('file');
194
+ expect(stat2.size).toBe(11); // "New content" is 11 bytes
195
+ // Test file reading
196
+ const content = await fs.readFile('/newfile.txt', {
197
+ encoding: 'text',
198
+ });
199
+ expect(content).toBe('New content');
200
+ // Test file reading as binary
201
+ const binary = await fs.readFile('/newfile.txt');
202
+ expect(Buffer.from(binary).toString()).toBe('New content');
203
+ // Test file overwrite
204
+ await fs.writeFile('/newfile.txt', 'Updated content');
205
+ expect(
206
+ await fs.readFile('/newfile.txt', {
207
+ encoding: 'text',
208
+ }),
209
+ ).toBe('Updated content');
210
+ // Test file overwrite protection
211
+ await expect(
212
+ fs.writeFile('/newfile.txt', 'Should fail', {
213
+ overwrite: false,
214
+ }),
215
+ ).rejects.toThrow(FileSystemError);
216
+ await expect(
217
+ fs.writeFile('/newfile.txt', 'Should fail', {
218
+ overwrite: false,
219
+ }),
220
+ ).rejects.toMatchObject({
221
+ code: FileSystemErrorCode.EEXIST,
222
+ });
223
+ // Test large file write (should use file_node_content table)
224
+ // Create ~1KB data to test large file handling
225
+ const largeData = 'x'.repeat(1024); // 1KB of data
226
+ await fs.writeFile('/largefile.txt', largeData);
227
+ const largeFileStat = await fs.stat('/largefile.txt');
228
+ expect(largeFileStat.size).toBe(1024);
229
+ const largeFileContent = await fs.readFile('/largefile.txt', {
230
+ encoding: 'text',
231
+ });
232
+ expect(largeFileContent).toBe(largeData);
233
+ expect(largeFileContent.length).toBe(1024);
234
+ // should handle directory operations correctly
235
+ // Test directory creation
236
+ await fs.mkdir('/newdir');
237
+ expect(await fs.exists('/newdir')).toBe(true);
238
+ const stat3 = await fs.stat('/newdir');
239
+ expect(stat3.kind).toBe('directory');
240
+ // Test recursive directory creation
241
+ await fs.mkdir('/deep/nested/dir', {
242
+ recursive: true,
243
+ });
244
+ expect(await fs.exists('/deep/nested/dir')).toBe(true);
245
+ // Test non-recursive directory creation failure
246
+ await expect(fs.mkdir('/another/deep/dir')).rejects.toThrow(FileSystemError);
247
+ await expect(fs.mkdir('/another/deep/dir')).rejects.toMatchObject({
248
+ code: FileSystemErrorCode.ENOENT,
249
+ });
250
+ // Test directory listing
251
+ await fs.writeFile('/newdir/file1.txt', 'File 1');
252
+ await fs.writeFile('/newdir/file2.txt', 'File 2');
253
+ const contents = await fs.readdir('/newdir');
254
+ expect(contents).toHaveLength(2);
255
+ expect(contents.map((f) => f.name)).toContain('file1.txt');
256
+ expect(contents.map((f) => f.name)).toContain('file2.txt');
257
+ // should handle file removal correctly
258
+ await fs.writeFile('/toremove.txt', 'Remove me');
259
+ expect(await fs.exists('/toremove.txt')).toBe(true);
260
+ await fs.rm('/toremove.txt');
261
+ expect(await fs.exists('/toremove.txt')).toBe(false);
262
+ // Test force removal
263
+ await expect(fs.rm('/nonexistent.txt')).rejects.toThrow(FileSystemError);
264
+ await expect(fs.rm('/nonexistent.txt')).rejects.toMatchObject({
265
+ code: FileSystemErrorCode.ENOENT,
266
+ });
267
+ await fs.rm('/nonexistent.txt', {
268
+ force: true,
269
+ }); // Should not throw
270
+ // Test recursive removal
271
+ await fs.mkdir('/dirwithfiles', {
272
+ recursive: true,
273
+ });
274
+ await fs.writeFile('/dirwithfiles/file.txt', 'content');
275
+ await expect(fs.rm('/dirwithfiles')).rejects.toThrow(FileSystemError);
276
+ await expect(fs.rm('/dirwithfiles')).rejects.toMatchObject({
277
+ code: FileSystemErrorCode.ENOTEMPTY,
278
+ });
279
+ await fs.rm('/dirwithfiles', {
280
+ recursive: true,
281
+ });
282
+ expect(await fs.exists('/dirwithfiles')).toBe(false);
283
+ // should handle file rename correctly
284
+ await fs.writeFile('/rename.txt', 'Original content');
285
+ expect(await fs.exists('/rename.txt')).toBe(true);
286
+ await fs.rename('/rename.txt', '/renamed.txt');
287
+ expect(await fs.exists('/rename.txt')).toBe(false);
288
+ expect(await fs.exists('/renamed.txt')).toBe(true);
289
+ expect(
290
+ await fs.readFile('/renamed.txt', {
291
+ encoding: 'text',
292
+ }),
293
+ ).toBe('Original content');
294
+ // should handle file copy correctly
295
+ await fs.writeFile('/copy.txt', 'Copy me');
296
+ expect(await fs.exists('/copy.txt')).toBe(true);
297
+ await fs.copy('/copy.txt', '/copied.txt');
298
+ expect(await fs.exists('/copy.txt')).toBe(true);
299
+ expect(await fs.exists('/copied.txt')).toBe(true);
300
+ expect(
301
+ await fs.readFile('/copied.txt', {
302
+ encoding: 'text',
303
+ }),
304
+ ).toBe('Copy me');
305
+ // Test copy overwrite
306
+ await fs.writeFile('/target2.txt', 'Target content');
307
+ await expect(fs.copy('/copy.txt', '/target2.txt')).rejects.toThrow(FileSystemError);
308
+ await expect(fs.copy('/copy.txt', '/target2.txt')).rejects.toMatchObject({
309
+ code: FileSystemErrorCode.EEXIST,
310
+ });
311
+ await fs.copy('/copy.txt', '/target2.txt', {
312
+ overwrite: true,
313
+ });
314
+ expect(
315
+ await fs.readFile('/target2.txt', {
316
+ encoding: 'text',
317
+ }),
318
+ ).toBe('Copy me');
319
+ // should handle edge cases correctly
320
+ // Test root directory operations
321
+ await expect(fs.stat('/')).resolves.toBeDefined();
322
+ await expect(fs.readdir('/')).resolves.toBeDefined();
323
+ await fs.mkdir('/'); // Should not throw
324
+ // Test path normalization
325
+ await fs.writeFile('/normalize.txt', 'test');
326
+ expect(await fs.exists('/normalize.txt')).toBe(true);
327
+ expect(await fs.exists('/./normalize.txt')).toBe(true);
328
+ // Note: the exists method may return true for files with trailing slashes due to normalization
329
+ // Test error cases
330
+ await expect(fs.stat('/nonexistent')).rejects.toThrow(FileSystemError);
331
+ await expect(fs.stat('/nonexistent')).rejects.toMatchObject({
332
+ code: FileSystemErrorCode.ENOENT,
333
+ });
334
+ await expect(fs.readdir('/nonexistent')).rejects.toThrow(FileSystemError);
335
+ await expect(fs.readdir('/nonexistent')).rejects.toMatchObject({
336
+ code: FileSystemErrorCode.ENOENT,
337
+ });
338
+ await expect(fs.readFile('/nonexistent')).rejects.toThrow(FileSystemError);
339
+ await expect(fs.readFile('/nonexistent')).rejects.toMatchObject({
340
+ code: FileSystemErrorCode.ENOENT,
341
+ });
342
+ await expect(fs.rm('/nonexistent')).rejects.toThrow(FileSystemError);
343
+ await expect(fs.rm('/nonexistent')).rejects.toMatchObject({
344
+ code: FileSystemErrorCode.ENOENT,
345
+ });
346
+ await expect(fs.rename('/nonexistent', '/new')).rejects.toThrow(FileSystemError);
347
+ await expect(fs.rename('/nonexistent', '/new')).rejects.toMatchObject({
348
+ code: FileSystemErrorCode.ENOENT,
349
+ });
350
+ await expect(fs.copy('/nonexistent', '/new')).rejects.toThrow(FileSystemError);
351
+ await expect(fs.copy('/nonexistent', '/new')).rejects.toMatchObject({
352
+ code: FileSystemErrorCode.ENOENT,
353
+ });
318
354
  }
319
355
  //# sourceMappingURL=runFileSystemTest.js.map