@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,34 +1,34 @@
1
- import { createReadStream as nodeCreateReadStream, createWriteStream as nodeCreateWriteStream } from "node:fs";
2
- import fsp from "node:fs/promises";
3
- import path from "node:path";
4
- import { Readable } from "node:stream";
5
- import { pathToFileURL } from "node:url";
1
+ import { createReadStream as nodeCreateReadStream, createWriteStream as nodeCreateWriteStream } from 'node:fs';
2
+ import fsp from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { Readable } from 'node:stream';
5
+ import { pathToFileURL } from 'node:url';
6
6
  /**
7
7
  * Creates a Node.js filesystem adapter that implements the IFileSystem interface
8
8
  * @param options Configuration options for the filesystem
9
9
  * @param options.root Optional root directory to restrict all operations within
10
10
  */ export function createNodeFileSystem(options = {}) {
11
- return new NodeFs(options);
11
+ return new NodeFs(options);
12
12
  }
13
13
  let NodeFs = class NodeFs {
14
- root;
15
- fs;
16
- constructor({ root, fs = fsp } = {}){
17
- // Normalize the root path if provided
18
- if (root) {
19
- this.root = path.resolve(root);
20
- } else {
21
- this.root = '';
22
- }
23
- this.fs = fs;
24
- }
25
- // Helper method to handle aborted signals consistently
26
- checkAborted(signal) {
27
- if (signal?.aborted) {
28
- throw new Error('The operation was aborted');
29
- }
30
- }
31
- /**
14
+ root;
15
+ fs;
16
+ constructor({ root, fs = fsp } = {}) {
17
+ // Normalize the root path if provided
18
+ if (root) {
19
+ this.root = path.resolve(root);
20
+ } else {
21
+ this.root = '';
22
+ }
23
+ this.fs = fs;
24
+ }
25
+ // Helper method to handle aborted signals consistently
26
+ checkAborted(signal) {
27
+ if (signal?.aborted) {
28
+ throw new Error('The operation was aborted');
29
+ }
30
+ }
31
+ /**
32
32
  * Resolves and secures a path by:
33
33
  * 1. Normalizing the path
34
34
  * 2. Prepending the root directory if one is set
@@ -36,391 +36,393 @@ let NodeFs = class NodeFs {
36
36
  *
37
37
  * This prevents path traversal attacks.
38
38
  */ resolvePath(filePath) {
39
- // Handle empty paths
40
- if (!filePath) {
41
- return this.root || '';
42
- }
43
- // Normalize to remove any '..' segments and handle slashes
44
- const normalizedPath = path.normalize(filePath);
45
- // If no root is set, just return the normalized path
46
- if (!this.root) {
47
- return normalizedPath;
48
- }
49
- // Join with root and resolve to absolute path
50
- const resolvedPath = path.resolve(path.join(this.root, normalizedPath));
51
- // Security check: ensure the path is within the root directory
52
- if (!resolvedPath.startsWith(this.root)) {
53
- throw new Error(`Security violation: Path ${filePath} attempts to access outside of the root directory`);
54
- }
55
- return resolvedPath;
56
- }
57
- /**
39
+ // Handle empty paths
40
+ if (!filePath) {
41
+ return this.root || '';
42
+ }
43
+ // Normalize to remove any '..' segments and handle slashes
44
+ const normalizedPath = path.normalize(filePath);
45
+ // If no root is set, just return the normalized path
46
+ if (!this.root) {
47
+ return normalizedPath;
48
+ }
49
+ // Join with root and resolve to absolute path
50
+ const resolvedPath = path.resolve(path.join(this.root, normalizedPath));
51
+ // Security check: ensure the path is within the root directory
52
+ if (!resolvedPath.startsWith(this.root)) {
53
+ throw new Error(`Security violation: Path ${filePath} attempts to access outside of the root directory`);
54
+ }
55
+ return resolvedPath;
56
+ }
57
+ /**
58
58
  * Removes the root prefix from a path for external representation
59
59
  */ stripRoot(fullPath) {
60
- if (!this.root || !fullPath.startsWith(this.root)) {
61
- return fullPath;
62
- }
63
- // Remove the root prefix and ensure there's a leading slash
64
- let relativePath = fullPath.substring(this.root.length);
65
- if (!relativePath) {
66
- return '/';
67
- }
68
- if (!relativePath.startsWith('/') && !relativePath.startsWith('\\')) {
69
- relativePath = `/${relativePath}`;
70
- }
71
- // Normalize to ensure consistent path separators
72
- return path.normalize(relativePath).replace(/\\/g, '/');
73
- }
74
- /**
60
+ if (!this.root || !fullPath.startsWith(this.root)) {
61
+ return fullPath;
62
+ }
63
+ // Remove the root prefix and ensure there's a leading slash
64
+ let relativePath = fullPath.substring(this.root.length);
65
+ if (!relativePath) {
66
+ return '/';
67
+ }
68
+ if (!relativePath.startsWith('/') && !relativePath.startsWith('\\')) {
69
+ relativePath = `/${relativePath}`;
70
+ }
71
+ // Normalize to ensure consistent path separators
72
+ return path.normalize(relativePath).replace(/\\/g, '/');
73
+ }
74
+ /**
75
75
  * Converts a system file stat to our IFileStat interface,
76
76
  * stripping the root prefix from paths
77
77
  */ toFileStat(fullPath, fsStats) {
78
- const normalizedPath = this.stripRoot(fullPath);
79
- const directoryPath = path.dirname(normalizedPath);
80
- const directory = directoryPath === '.' ? '/' : directoryPath.replace(/\\/g, '/');
81
- return {
82
- directory,
83
- path: normalizedPath,
84
- name: path.basename(fullPath),
85
- kind: fsStats.isDirectory() ? 'directory' : 'file',
86
- mtime: fsStats.mtimeMs,
87
- size: fsStats.size,
88
- meta: {}
89
- };
90
- }
91
- async readdir(dir, options = {}) {
92
- const { fs } = this;
93
- const { glob, recursive, depth = 1, kind, hidden = true, signal } = options;
94
- this.checkAborted(signal);
95
- // Resolve the directory path with security checks
96
- const resolvedDir = this.resolvePath(dir);
97
- // Basic file listing
98
- const entries = await fs.readdir(resolvedDir, {
99
- withFileTypes: true
100
- });
101
- let results = await Promise.all(entries.filter((entry)=>hidden || !entry.name.startsWith('.')).filter((entry)=>!kind || (kind === 'directory' ? entry.isDirectory() : entry.isFile())).map(async (entry)=>{
102
- this.checkAborted(signal);
103
- const entryFullPath = path.join(resolvedDir, entry.name);
104
- const stat = await fs.stat(entryFullPath);
105
- // Convert to external representation
106
- return {
107
- directory: this.stripRoot(resolvedDir),
108
- path: this.stripRoot(entryFullPath),
109
- name: entry.name,
110
- kind: entry.isDirectory() ? 'directory' : 'file',
111
- mtime: stat.mtimeMs,
112
- size: stat.size,
113
- meta: {}
114
- };
115
- }));
116
- // Handle recursive option
117
- if (recursive || depth > 1) {
118
- const subdirs = results.filter((entry)=>entry.kind === 'directory');
119
- for (const subdir of subdirs){
120
- this.checkAborted(signal);
121
- const maxDepth = recursive ? Infinity : depth - 1;
122
- if (maxDepth > 0) {
123
- // Need to convert the path back to a full path for the recursive call
124
- const _subdirFullPath = this.resolvePath(subdir.path);
125
- const subEntries = await this.readdir(subdir.path, {
126
- ...options,
127
- depth: maxDepth
128
- });
129
- results = [
130
- ...results,
131
- ...subEntries
132
- ];
133
- }
134
- }
135
- }
136
- // Handle glob filtering
137
- if (glob) {
138
- const { matcher } = await import("micromatch");
139
- const match = matcher(glob);
140
- results = results.filter((entry)=>match(entry.path));
141
- }
142
- return results;
143
- }
144
- async stat(filePath, options = {}) {
145
- const { fs } = this;
146
- const { signal } = options;
147
- this.checkAborted(signal);
148
- const resolvedPath = this.resolvePath(filePath);
149
- try {
150
- const stat = await fs.stat(resolvedPath);
151
- return this.toFileStat(resolvedPath, stat);
152
- } catch (err) {
153
- if (err.code === 'ENOENT') {
154
- throw new Error(`File not found: ${filePath}`);
155
- }
156
- throw err;
157
- }
158
- }
159
- async mkdir(dirPath, options = {}) {
160
- const { fs } = this;
161
- const { recursive = false, signal } = options;
162
- this.checkAborted(signal);
163
- const resolvedPath = this.resolvePath(dirPath);
164
- try {
165
- await fs.mkdir(resolvedPath, {
166
- recursive
167
- });
168
- } catch (err) {
169
- if (err.code === 'EEXIST' && recursive) {
170
- // Ignore if directory exists and recursive is true
171
- return;
172
- }
173
- throw err;
174
- }
175
- }
176
- async readFile(path, options = {}) {
177
- const { fs } = this;
178
- const { encoding = 'binary', signal, onDownloadProgress } = options;
179
- this.checkAborted(signal);
180
- const resolvedPath = this.resolvePath(path);
181
- try {
182
- // Handle progress reporting if needed
183
- if (onDownloadProgress) {
184
- const stat = await fs.stat(resolvedPath);
185
- const stream = this.createReadStream(path, {
186
- signal
187
- });
188
- return new Promise((resolve, reject)=>{
189
- const chunks = [];
190
- let loaded = 0;
191
- stream.on('data', (chunk)=>{
192
- chunks.push(Buffer.from(chunk));
193
- loaded += chunk.length;
194
- onDownloadProgress({
195
- loaded,
196
- total: stat.size
197
- });
198
- });
199
- stream.on('end', ()=>{
200
- const buffer = Buffer.concat(chunks);
201
- if (encoding === 'text') {
202
- resolve(buffer.toString('utf-8'));
203
- } else {
204
- resolve(buffer);
205
- }
206
- });
207
- stream.on('error', reject);
208
- });
209
- }
210
- // Standard file reading
211
- if (encoding === 'text') {
212
- return await fs.readFile(resolvedPath, {
213
- encoding: 'utf-8'
214
- });
215
- } else {
216
- return await fs.readFile(resolvedPath);
217
- }
218
- } catch (err) {
219
- if (err.code === 'ENOENT') {
220
- throw new Error(`File not found: ${path}`);
221
- }
222
- throw err;
223
- }
224
- }
225
- async writeFile(path, data, options = {}) {
226
- const { fs } = this;
227
- const { signal, overwrite = true, onUploadProgress } = options;
228
- this.checkAborted(signal);
229
- const resolvedPath = this.resolvePath(path);
230
- // Check if file exists and overwrite is false
231
- if (!overwrite) {
232
- const exists = await this.exists(path);
233
- if (exists) {
234
- throw new Error(`File already exists: ${path}`);
235
- }
236
- }
237
- // Create parent directories if they don't exist
238
- const directory = this.getDirectoryName(resolvedPath);
239
- if (directory !== resolvedPath) {
240
- try {
241
- await this.mkdir(this.stripRoot(directory), {
242
- recursive: true
243
- });
244
- } catch (err) {
245
- // Ignore directory exists error
246
- if (err?.code !== 'EEXIST') {
247
- throw err;
248
- }
249
- }
250
- }
251
- if (data instanceof Readable) {
252
- let _data = data;
253
- return new Promise((resolve, reject)=>{
254
- const writeStream = this.createWriteStream(path, options);
255
- let totalBytes = 0;
256
- if (onUploadProgress) {
257
- _data.on('data', (chunk)=>{
258
- totalBytes += chunk.length;
259
- onUploadProgress({
260
- loaded: totalBytes,
261
- total: -1
262
- });
263
- });
264
- }
265
- _data.pipe(writeStream);
266
- writeStream.on('finish', ()=>resolve());
267
- writeStream.on('error', reject);
268
- if (signal) {
269
- signal.addEventListener('abort', ()=>{
270
- _data.destroy();
271
- writeStream.destroy();
272
- reject(new Error('The operation was aborted'));
273
- });
274
- }
275
- });
276
- } else if (data instanceof ReadableStream) {
277
- // Handle web ReadableStream
278
- const reader = data.getReader();
279
- const chunks = [];
280
- let loaded = 0;
281
- while(true){
282
- const { done, value } = await reader.read();
283
- if (done) break;
284
- if (value) {
285
- chunks.push(value);
286
- loaded += value.length;
287
- if (onUploadProgress) {
288
- onUploadProgress({
289
- loaded,
290
- total: -1
291
- });
292
- }
293
- }
294
- }
295
- await fs.writeFile(resolvedPath, Buffer.concat(chunks));
296
- } else {
297
- // Convert ArrayBuffer/ArrayBufferView to Buffer if necessary
298
- let writeData;
299
- if (data instanceof ArrayBuffer) {
300
- writeData = Buffer.from(data);
301
- } else if (ArrayBuffer.isView(data)) {
302
- writeData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
303
- } else {
304
- writeData = data;
305
- }
306
- await fs.writeFile(resolvedPath, writeData);
307
- }
308
- }
309
- async rm(path, options = {}) {
310
- const { fs } = this;
311
- const { recursive = false, force = false, signal } = options;
312
- this.checkAborted(signal);
313
- const resolvedPath = this.resolvePath(path);
314
- try {
315
- await fs.rm(resolvedPath, {
316
- recursive,
317
- force
318
- });
319
- } catch (err) {
320
- if (force && err.code === 'ENOENT') {
321
- return;
322
- }
323
- throw err;
324
- }
325
- }
326
- async rename(oldPath, newPath, options = {}) {
327
- const { fs } = this;
328
- const { signal, overwrite = false } = options;
329
- this.checkAborted(signal);
330
- const resolvedOldPath = this.resolvePath(oldPath);
331
- const resolvedNewPath = this.resolvePath(newPath);
332
- // Check if target exists and overwrite is false
333
- if (!overwrite) {
334
- const exists = await this.exists(newPath);
335
- if (exists) {
336
- throw new Error(`Destination already exists: ${newPath}`);
337
- }
338
- }
339
- try {
340
- await fs.rename(resolvedOldPath, resolvedNewPath);
341
- } catch (err) {
342
- if (err.code === 'ENOENT') {
343
- throw new Error(`Source file not found: ${oldPath}`);
344
- }
345
- throw err;
346
- }
347
- }
348
- async exists(path) {
349
- const { fs } = this;
350
- try {
351
- await fs.access(this.resolvePath(path));
352
- return true;
353
- } catch {
354
- return false;
355
- }
356
- }
357
- async copy(src, dest, options = {}) {
358
- const { fs } = this;
359
- const { signal, overwrite = true, shallow = false } = options;
360
- this.checkAborted(signal);
361
- const resolvedSrc = this.resolvePath(src);
362
- const resolvedDest = this.resolvePath(dest);
363
- // Check if source exists
364
- try {
365
- const stat = await fs.stat(resolvedSrc);
366
- // Check if destination exists and overwrite is false
367
- if (!overwrite) {
368
- const exists = await this.exists(dest);
369
- if (exists) {
370
- throw new Error(`Destination already exists: ${dest}`);
371
- }
372
- }
373
- // Create parent directory if it doesn't exist
374
- const parentDir = this.getDirectoryName(resolvedDest);
375
- await this.mkdir(this.stripRoot(parentDir), {
376
- recursive: true
377
- });
378
- // Copy recursively or not based on shallow and if it's a directory
379
- await fs.cp(resolvedSrc, resolvedDest, {
380
- recursive: !shallow && stat.isDirectory(),
381
- force: overwrite
382
- });
383
- } catch (err) {
384
- if (err.code === 'ENOENT') {
385
- throw new Error(`Source file not found: ${src}`);
386
- }
387
- throw err;
388
- }
389
- }
390
- createReadStream(filePath, options = {}) {
391
- const resolvedPath = this.resolvePath(filePath);
392
- const { signal, range } = options;
393
- const stream = nodeCreateReadStream(resolvedPath, {
394
- start: range?.start,
395
- end: range?.end
396
- });
397
- signal?.addEventListener('abort', ()=>stream.destroy(new Error('The operation was aborted')));
398
- return stream;
399
- }
400
- createWriteStream(filePath, options = {}) {
401
- const resolvedPath = this.resolvePath(filePath);
402
- const { signal } = options;
403
- const stream = nodeCreateWriteStream(resolvedPath, {
404
- flags: options.overwrite === false ? 'wx' : 'w'
405
- });
406
- signal?.addEventListener('abort', ()=>stream.destroy(new Error('The operation was aborted')));
407
- return stream;
408
- }
409
- // Helper to extract directory name correctly
410
- getDirectoryName(filePath) {
411
- return path.dirname(filePath);
412
- }
413
- getUrl(needle) {
414
- if (typeof needle === 'object' && needle?.kind !== 'file') {
415
- return;
416
- }
417
- let path = typeof needle === 'string' ? needle : needle.path;
418
- if (!path) {
419
- return;
420
- }
421
- // file://
422
- return pathToFileURL(this.resolvePath(path)).toString();
423
- }
78
+ const normalizedPath = this.stripRoot(fullPath);
79
+ const directoryPath = path.dirname(normalizedPath);
80
+ const directory = directoryPath === '.' ? '/' : directoryPath.replace(/\\/g, '/');
81
+ return {
82
+ directory,
83
+ path: normalizedPath,
84
+ name: path.basename(fullPath),
85
+ kind: fsStats.isDirectory() ? 'directory' : 'file',
86
+ mtime: fsStats.mtimeMs,
87
+ size: fsStats.size,
88
+ meta: {},
89
+ };
90
+ }
91
+ async readdir(dir, options = {}) {
92
+ const { fs } = this;
93
+ const { glob, recursive, depth = 1, kind, hidden = true, signal } = options;
94
+ this.checkAborted(signal);
95
+ // Resolve the directory path with security checks
96
+ const resolvedDir = this.resolvePath(dir);
97
+ // Basic file listing
98
+ const entries = await fs.readdir(resolvedDir, {
99
+ withFileTypes: true,
100
+ });
101
+ let results = await Promise.all(
102
+ entries
103
+ .filter((entry) => hidden || !entry.name.startsWith('.'))
104
+ .filter((entry) => !kind || (kind === 'directory' ? entry.isDirectory() : entry.isFile()))
105
+ .map(async (entry) => {
106
+ this.checkAborted(signal);
107
+ const entryFullPath = path.join(resolvedDir, entry.name);
108
+ const stat = await fs.stat(entryFullPath);
109
+ // Convert to external representation
110
+ return {
111
+ directory: this.stripRoot(resolvedDir),
112
+ path: this.stripRoot(entryFullPath),
113
+ name: entry.name,
114
+ kind: entry.isDirectory() ? 'directory' : 'file',
115
+ mtime: stat.mtimeMs,
116
+ size: stat.size,
117
+ meta: {},
118
+ };
119
+ }),
120
+ );
121
+ // Handle recursive option
122
+ if (recursive || depth > 1) {
123
+ const subdirs = results.filter((entry) => entry.kind === 'directory');
124
+ for (const subdir of subdirs) {
125
+ this.checkAborted(signal);
126
+ const maxDepth = recursive ? Infinity : depth - 1;
127
+ if (maxDepth > 0) {
128
+ // Need to convert the path back to a full path for the recursive call
129
+ const _subdirFullPath = this.resolvePath(subdir.path);
130
+ const subEntries = await this.readdir(subdir.path, {
131
+ ...options,
132
+ depth: maxDepth,
133
+ });
134
+ results = [...results, ...subEntries];
135
+ }
136
+ }
137
+ }
138
+ // Handle glob filtering
139
+ if (glob) {
140
+ const { matcher } = await import('micromatch');
141
+ const match = matcher(glob);
142
+ results = results.filter((entry) => match(entry.path));
143
+ }
144
+ return results;
145
+ }
146
+ async stat(filePath, options = {}) {
147
+ const { fs } = this;
148
+ const { signal } = options;
149
+ this.checkAborted(signal);
150
+ const resolvedPath = this.resolvePath(filePath);
151
+ try {
152
+ const stat = await fs.stat(resolvedPath);
153
+ return this.toFileStat(resolvedPath, stat);
154
+ } catch (err) {
155
+ if (err.code === 'ENOENT') {
156
+ throw new Error(`File not found: ${filePath}`);
157
+ }
158
+ throw err;
159
+ }
160
+ }
161
+ async mkdir(dirPath, options = {}) {
162
+ const { fs } = this;
163
+ const { recursive = false, signal } = options;
164
+ this.checkAborted(signal);
165
+ const resolvedPath = this.resolvePath(dirPath);
166
+ try {
167
+ await fs.mkdir(resolvedPath, {
168
+ recursive,
169
+ });
170
+ } catch (err) {
171
+ if (err.code === 'EEXIST' && recursive) {
172
+ // Ignore if directory exists and recursive is true
173
+ return;
174
+ }
175
+ throw err;
176
+ }
177
+ }
178
+ async readFile(path, options = {}) {
179
+ const { fs } = this;
180
+ const { encoding = 'binary', signal, onDownloadProgress } = options;
181
+ this.checkAborted(signal);
182
+ const resolvedPath = this.resolvePath(path);
183
+ try {
184
+ // Handle progress reporting if needed
185
+ if (onDownloadProgress) {
186
+ const stat = await fs.stat(resolvedPath);
187
+ const stream = this.createReadStream(path, {
188
+ signal,
189
+ });
190
+ return new Promise((resolve, reject) => {
191
+ const chunks = [];
192
+ let loaded = 0;
193
+ stream.on('data', (chunk) => {
194
+ chunks.push(Buffer.from(chunk));
195
+ loaded += chunk.length;
196
+ onDownloadProgress({
197
+ loaded,
198
+ total: stat.size,
199
+ });
200
+ });
201
+ stream.on('end', () => {
202
+ const buffer = Buffer.concat(chunks);
203
+ if (encoding === 'text') {
204
+ resolve(buffer.toString('utf-8'));
205
+ } else {
206
+ resolve(buffer);
207
+ }
208
+ });
209
+ stream.on('error', reject);
210
+ });
211
+ }
212
+ // Standard file reading
213
+ if (encoding === 'text') {
214
+ return await fs.readFile(resolvedPath, {
215
+ encoding: 'utf-8',
216
+ });
217
+ } else {
218
+ return await fs.readFile(resolvedPath);
219
+ }
220
+ } catch (err) {
221
+ if (err.code === 'ENOENT') {
222
+ throw new Error(`File not found: ${path}`);
223
+ }
224
+ throw err;
225
+ }
226
+ }
227
+ async writeFile(path, data, options = {}) {
228
+ const { fs } = this;
229
+ const { signal, overwrite = true, onUploadProgress } = options;
230
+ this.checkAborted(signal);
231
+ const resolvedPath = this.resolvePath(path);
232
+ // Check if file exists and overwrite is false
233
+ if (!overwrite) {
234
+ const exists = await this.exists(path);
235
+ if (exists) {
236
+ throw new Error(`File already exists: ${path}`);
237
+ }
238
+ }
239
+ // Create parent directories if they don't exist
240
+ const directory = this.getDirectoryName(resolvedPath);
241
+ if (directory !== resolvedPath) {
242
+ try {
243
+ await this.mkdir(this.stripRoot(directory), {
244
+ recursive: true,
245
+ });
246
+ } catch (err) {
247
+ // Ignore directory exists error
248
+ if (err?.code !== 'EEXIST') {
249
+ throw err;
250
+ }
251
+ }
252
+ }
253
+ if (data instanceof Readable) {
254
+ let _data = data;
255
+ return new Promise((resolve, reject) => {
256
+ const writeStream = this.createWriteStream(path, options);
257
+ let totalBytes = 0;
258
+ if (onUploadProgress) {
259
+ _data.on('data', (chunk) => {
260
+ totalBytes += chunk.length;
261
+ onUploadProgress({
262
+ loaded: totalBytes,
263
+ total: -1,
264
+ });
265
+ });
266
+ }
267
+ _data.pipe(writeStream);
268
+ writeStream.on('finish', () => resolve());
269
+ writeStream.on('error', reject);
270
+ if (signal) {
271
+ signal.addEventListener('abort', () => {
272
+ _data.destroy();
273
+ writeStream.destroy();
274
+ reject(new Error('The operation was aborted'));
275
+ });
276
+ }
277
+ });
278
+ } else if (data instanceof ReadableStream) {
279
+ // Handle web ReadableStream
280
+ const reader = data.getReader();
281
+ const chunks = [];
282
+ let loaded = 0;
283
+ while (true) {
284
+ const { done, value } = await reader.read();
285
+ if (done) break;
286
+ if (value) {
287
+ chunks.push(value);
288
+ loaded += value.length;
289
+ if (onUploadProgress) {
290
+ onUploadProgress({
291
+ loaded,
292
+ total: -1,
293
+ });
294
+ }
295
+ }
296
+ }
297
+ await fs.writeFile(resolvedPath, Buffer.concat(chunks));
298
+ } else {
299
+ // Convert ArrayBuffer/ArrayBufferView to Buffer if necessary
300
+ let writeData;
301
+ if (data instanceof ArrayBuffer) {
302
+ writeData = Buffer.from(data);
303
+ } else if (ArrayBuffer.isView(data)) {
304
+ writeData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
305
+ } else {
306
+ writeData = data;
307
+ }
308
+ await fs.writeFile(resolvedPath, writeData);
309
+ }
310
+ }
311
+ async rm(path, options = {}) {
312
+ const { fs } = this;
313
+ const { recursive = false, force = false, signal } = options;
314
+ this.checkAborted(signal);
315
+ const resolvedPath = this.resolvePath(path);
316
+ try {
317
+ await fs.rm(resolvedPath, {
318
+ recursive,
319
+ force,
320
+ });
321
+ } catch (err) {
322
+ if (force && err.code === 'ENOENT') {
323
+ return;
324
+ }
325
+ throw err;
326
+ }
327
+ }
328
+ async rename(oldPath, newPath, options = {}) {
329
+ const { fs } = this;
330
+ const { signal, overwrite = false } = options;
331
+ this.checkAborted(signal);
332
+ const resolvedOldPath = this.resolvePath(oldPath);
333
+ const resolvedNewPath = this.resolvePath(newPath);
334
+ // Check if target exists and overwrite is false
335
+ if (!overwrite) {
336
+ const exists = await this.exists(newPath);
337
+ if (exists) {
338
+ throw new Error(`Destination already exists: ${newPath}`);
339
+ }
340
+ }
341
+ try {
342
+ await fs.rename(resolvedOldPath, resolvedNewPath);
343
+ } catch (err) {
344
+ if (err.code === 'ENOENT') {
345
+ throw new Error(`Source file not found: ${oldPath}`);
346
+ }
347
+ throw err;
348
+ }
349
+ }
350
+ async exists(path) {
351
+ const { fs } = this;
352
+ try {
353
+ await fs.access(this.resolvePath(path));
354
+ return true;
355
+ } catch {
356
+ return false;
357
+ }
358
+ }
359
+ async copy(src, dest, options = {}) {
360
+ const { fs } = this;
361
+ const { signal, overwrite = true, shallow = false } = options;
362
+ this.checkAborted(signal);
363
+ const resolvedSrc = this.resolvePath(src);
364
+ const resolvedDest = this.resolvePath(dest);
365
+ // Check if source exists
366
+ try {
367
+ const stat = await fs.stat(resolvedSrc);
368
+ // Check if destination exists and overwrite is false
369
+ if (!overwrite) {
370
+ const exists = await this.exists(dest);
371
+ if (exists) {
372
+ throw new Error(`Destination already exists: ${dest}`);
373
+ }
374
+ }
375
+ // Create parent directory if it doesn't exist
376
+ const parentDir = this.getDirectoryName(resolvedDest);
377
+ await this.mkdir(this.stripRoot(parentDir), {
378
+ recursive: true,
379
+ });
380
+ // Copy recursively or not based on shallow and if it's a directory
381
+ await fs.cp(resolvedSrc, resolvedDest, {
382
+ recursive: !shallow && stat.isDirectory(),
383
+ force: overwrite,
384
+ });
385
+ } catch (err) {
386
+ if (err.code === 'ENOENT') {
387
+ throw new Error(`Source file not found: ${src}`);
388
+ }
389
+ throw err;
390
+ }
391
+ }
392
+ createReadStream(filePath, options = {}) {
393
+ const resolvedPath = this.resolvePath(filePath);
394
+ const { signal, range } = options;
395
+ const stream = nodeCreateReadStream(resolvedPath, {
396
+ start: range?.start,
397
+ end: range?.end,
398
+ });
399
+ signal?.addEventListener('abort', () => stream.destroy(new Error('The operation was aborted')));
400
+ return stream;
401
+ }
402
+ createWriteStream(filePath, options = {}) {
403
+ const resolvedPath = this.resolvePath(filePath);
404
+ const { signal } = options;
405
+ const stream = nodeCreateWriteStream(resolvedPath, {
406
+ flags: options.overwrite === false ? 'wx' : 'w',
407
+ });
408
+ signal?.addEventListener('abort', () => stream.destroy(new Error('The operation was aborted')));
409
+ return stream;
410
+ }
411
+ // Helper to extract directory name correctly
412
+ getDirectoryName(filePath) {
413
+ return path.dirname(filePath);
414
+ }
415
+ getUrl(needle) {
416
+ if (typeof needle === 'object' && needle?.kind !== 'file') {
417
+ return;
418
+ }
419
+ let path = typeof needle === 'string' ? needle : needle.path;
420
+ if (!path) {
421
+ return;
422
+ }
423
+ // file://
424
+ return pathToFileURL(this.resolvePath(path)).toString();
425
+ }
424
426
  };
425
427
 
426
- //# sourceMappingURL=createNodeFileSystem.js.map
428
+ //# sourceMappingURL=createNodeFileSystem.js.map