@wener/common 2.0.3 → 2.0.5

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 (168) hide show
  1. package/lib/ai/qwen3vl/utils.js.map +1 -1
  2. package/lib/cn/ChineseResidentIdNo.js +1 -1
  3. package/lib/cn/ChineseResidentIdNo.js.map +1 -1
  4. package/lib/cn/Mod11.js +1 -1
  5. package/lib/cn/Mod11.js.map +1 -1
  6. package/lib/consola/formatLogObject.js +5 -5
  7. package/lib/consola/formatLogObject.js.map +1 -1
  8. package/lib/data/maybeNumber.js +1 -1
  9. package/lib/data/maybeNumber.js.map +1 -1
  10. package/lib/data/types.d.js.map +1 -1
  11. package/lib/dayjs/formatDuration.js.map +1 -1
  12. package/lib/dayjs/resolveRelativeTime.js +9 -80
  13. package/lib/dayjs/resolveRelativeTime.js.map +1 -1
  14. package/lib/drain3/Drain.js +356 -0
  15. package/lib/drain3/Drain.js.map +1 -0
  16. package/lib/drain3/LogCluster.js +38 -0
  17. package/lib/drain3/LogCluster.js.map +1 -0
  18. package/lib/drain3/Node.js +39 -0
  19. package/lib/drain3/Node.js.map +1 -0
  20. package/lib/drain3/TemplateMiner.js +204 -0
  21. package/lib/drain3/TemplateMiner.js.map +1 -0
  22. package/lib/drain3/index.js +31 -0
  23. package/lib/drain3/index.js.map +1 -0
  24. package/lib/drain3/persistence/FilePersistence.js +24 -0
  25. package/lib/drain3/persistence/FilePersistence.js.map +1 -0
  26. package/lib/drain3/persistence/MemoryPersistence.js +18 -0
  27. package/lib/drain3/persistence/MemoryPersistence.js.map +1 -0
  28. package/lib/drain3/persistence/PersistenceHandler.js +5 -0
  29. package/lib/drain3/persistence/PersistenceHandler.js.map +1 -0
  30. package/lib/drain3/types.js +7 -0
  31. package/lib/drain3/types.js.map +1 -0
  32. package/lib/fs/IFileSystem.d.js.map +1 -1
  33. package/lib/fs/createBrowserFileSystem.js +4 -2
  34. package/lib/fs/createBrowserFileSystem.js.map +1 -1
  35. package/lib/fs/createMemoryFileSystem.js +7 -6
  36. package/lib/fs/createMemoryFileSystem.js.map +1 -1
  37. package/lib/fs/createSandboxFileSystem.js.map +1 -1
  38. package/lib/fs/createWebDavFileSystem.js +22 -5
  39. package/lib/fs/createWebDavFileSystem.js.map +1 -1
  40. package/lib/fs/createWebFileSystem.js +225 -0
  41. package/lib/fs/createWebFileSystem.js.map +1 -0
  42. package/lib/fs/findMimeType.js +1 -1
  43. package/lib/fs/findMimeType.js.map +1 -1
  44. package/lib/fs/index.js +1 -1
  45. package/lib/fs/index.js.map +1 -1
  46. package/lib/fs/minio/createMinioFileSystem.js +974 -0
  47. package/lib/fs/minio/createMinioFileSystem.js.map +1 -0
  48. package/lib/fs/minio/index.js +2 -0
  49. package/lib/fs/minio/index.js.map +1 -0
  50. package/lib/fs/orpc/createContractClientFileSystem.js +3 -3
  51. package/lib/fs/orpc/createContractClientFileSystem.js.map +1 -1
  52. package/lib/fs/orpc/server/createFileSystemContractImpl.js.map +1 -1
  53. package/lib/fs/s3/createS3MiniFileSystem.js +116 -68
  54. package/lib/fs/s3/createS3MiniFileSystem.js.map +1 -1
  55. package/lib/fs/server/createDatabaseFileSystem.js +7 -7
  56. package/lib/fs/server/createDatabaseFileSystem.js.map +1 -1
  57. package/lib/fs/server/createNodeFileSystem.js +30 -5
  58. package/lib/fs/server/createNodeFileSystem.js.map +1 -1
  59. package/lib/fs/tests/runFileSystemTest.js +27 -26
  60. package/lib/fs/tests/runFileSystemTest.js.map +1 -1
  61. package/lib/fs/utils.js.map +1 -1
  62. package/lib/fs/webdav/index.js +2 -0
  63. package/lib/fs/webdav/index.js.map +1 -0
  64. package/lib/jsonschema/JsonSchema.js +5 -5
  65. package/lib/jsonschema/JsonSchema.js.map +1 -1
  66. package/lib/jsonschema/forEachJsonSchema.js +1 -1
  67. package/lib/jsonschema/forEachJsonSchema.js.map +1 -1
  68. package/lib/jsonschema/types.d.js.map +1 -1
  69. package/lib/meta/defineMetadata.js.map +1 -1
  70. package/lib/orpc/createOpenApiContractClient.js.map +1 -1
  71. package/lib/password/PHC.js +2 -2
  72. package/lib/password/PHC.js.map +1 -1
  73. package/lib/password/createArgon2PasswordAlgorithm.js.map +1 -1
  74. package/lib/password/createBase64PasswordAlgorithm.js +1 -1
  75. package/lib/password/createBase64PasswordAlgorithm.js.map +1 -1
  76. package/lib/password/createBcryptPasswordAlgorithm.js.map +1 -1
  77. package/lib/password/createPBKDF2PasswordAlgorithm.js +1 -1
  78. package/lib/password/createPBKDF2PasswordAlgorithm.js.map +1 -1
  79. package/lib/password/createScryptPasswordAlgorithm.js +3 -3
  80. package/lib/password/createScryptPasswordAlgorithm.js.map +1 -1
  81. package/lib/resource/ListQuery.js.map +1 -1
  82. package/lib/resource/index.js.map +1 -1
  83. package/lib/s3/formatS3Url.js +2 -2
  84. package/lib/s3/formatS3Url.js.map +1 -1
  85. package/lib/s3/parseS3Url.js +1 -1
  86. package/lib/s3/parseS3Url.js.map +1 -1
  87. package/lib/schema/SchemaRegistry.js.map +1 -1
  88. package/lib/schema/TypeSchema.d.js.map +1 -1
  89. package/lib/schema/createSchemaData.js +4 -4
  90. package/lib/schema/createSchemaData.js.map +1 -1
  91. package/lib/schema/findJsonSchemaByPath.js.map +1 -1
  92. package/lib/schema/formatZodError.js +42 -44
  93. package/lib/schema/formatZodError.js.map +1 -1
  94. package/lib/schema/toJsonSchema.js +4 -4
  95. package/lib/schema/toJsonSchema.js.map +1 -1
  96. package/lib/schema/validate.js +1 -1
  97. package/lib/schema/validate.js.map +1 -1
  98. package/lib/utils/buildRedactorFormSchema.js +1 -1
  99. package/lib/utils/buildRedactorFormSchema.js.map +1 -1
  100. package/package.json +32 -13
  101. package/src/ai/qwen3vl/utils.ts +1 -1
  102. package/src/cn/ChineseResidentIdNo.ts +1 -1
  103. package/src/cn/Mod11.ts +1 -1
  104. package/src/cn/__snapshots__/ChineseResidentIdNo.test.ts.snap +1 -1
  105. package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +0 -23
  106. package/src/cn/parseChineseNumber.test.ts +4 -4
  107. package/src/consola/formatLogObject.ts +6 -6
  108. package/src/data/maybeNumber.ts +1 -1
  109. package/src/data/parseSort.test.ts +0 -1
  110. package/src/data/types.d.ts +2 -2
  111. package/src/dayjs/formatDuration.ts +2 -2
  112. package/src/dayjs/resolveRelativeTime.ts +11 -14
  113. package/src/drain3/Drain.test.ts +378 -0
  114. package/src/drain3/Drain.ts +394 -0
  115. package/src/drain3/LogCluster.ts +46 -0
  116. package/src/drain3/Node.ts +53 -0
  117. package/src/drain3/TemplateMiner.ts +246 -0
  118. package/src/drain3/index.ts +36 -0
  119. package/src/drain3/persistence/FilePersistence.ts +24 -0
  120. package/src/drain3/persistence/MemoryPersistence.ts +23 -0
  121. package/src/drain3/persistence/PersistenceHandler.ts +19 -0
  122. package/src/drain3/types.ts +75 -0
  123. package/src/fs/IFileSystem.d.ts +1 -2
  124. package/src/fs/createBrowserFileSystem.ts +7 -5
  125. package/src/fs/createMemoryFileSystem.ts +9 -13
  126. package/src/fs/createSandboxFileSystem.ts +1 -1
  127. package/src/fs/createWebDavFileSystem.ts +28 -10
  128. package/src/fs/createWebFileSystem.ts +242 -0
  129. package/src/fs/findMimeType.ts +1 -4
  130. package/src/fs/index.ts +1 -1
  131. package/src/fs/minio/createMinioFileSystem.ts +1148 -0
  132. package/src/fs/minio/index.ts +1 -0
  133. package/src/fs/orpc/createContractClientFileSystem.ts +5 -5
  134. package/src/fs/orpc/server/createFileSystemContractImpl.ts +1 -1
  135. package/src/fs/s3/createS3MiniFileSystem.ts +119 -78
  136. package/src/fs/s3/s3fs.test.ts +441 -0
  137. package/src/fs/s3/s3mini.test.ts +2 -2
  138. package/src/fs/server/createDatabaseFileSystem.ts +7 -7
  139. package/src/fs/server/createNodeFileSystem.ts +32 -13
  140. package/src/fs/server/dbfs.test.ts +2 -1
  141. package/src/fs/tests/runFileSystemTest.ts +29 -28
  142. package/src/fs/utils.ts +1 -1
  143. package/src/fs/webdav/index.ts +1 -0
  144. package/src/jsonschema/JsonSchema.ts +5 -5
  145. package/src/jsonschema/forEachJsonSchema.ts +1 -1
  146. package/src/jsonschema/types.d.ts +1 -1
  147. package/src/meta/defineMetadata.ts +1 -1
  148. package/src/orpc/createOpenApiContractClient.ts +2 -2
  149. package/src/password/PHC.ts +3 -3
  150. package/src/password/createArgon2PasswordAlgorithm.ts +1 -1
  151. package/src/password/createBase64PasswordAlgorithm.ts +2 -2
  152. package/src/password/createBcryptPasswordAlgorithm.ts +4 -2
  153. package/src/password/createPBKDF2PasswordAlgorithm.ts +2 -2
  154. package/src/password/createScryptPasswordAlgorithm.ts +4 -4
  155. package/src/resource/ListQuery.ts +4 -1
  156. package/src/resource/index.ts +2 -2
  157. package/src/s3/formatS3Url.test.ts +1 -1
  158. package/src/s3/formatS3Url.ts +2 -2
  159. package/src/s3/parseS3Url.ts +1 -1
  160. package/src/schema/SchemaRegistry.ts +1 -1
  161. package/src/schema/TypeSchema.d.ts +6 -6
  162. package/src/schema/createSchemaData.ts +4 -4
  163. package/src/schema/findJsonSchemaByPath.ts +4 -4
  164. package/src/schema/formatZodError.test.ts +2 -1
  165. package/src/schema/formatZodError.ts +50 -62
  166. package/src/schema/toJsonSchema.ts +6 -6
  167. package/src/schema/validate.ts +1 -1
  168. package/src/utils/buildRedactorFormSchema.ts +3 -3
@@ -0,0 +1 @@
1
+ export { createMinioFileSystem, type CreateMinioFileSystemOptions } from './createMinioFileSystem';
@@ -16,7 +16,7 @@ import type {
16
16
  WriteFileOptions,
17
17
  } from '../IFileSystem';
18
18
  import { resolveData } from '../utils';
19
- import { FileSystemContract } from './FileSystemContract';
19
+ import type { FileSystemContract } from './FileSystemContract';
20
20
 
21
21
  type FileSystemContractClient = ContractRouterClient<typeof FileSystemContract>;
22
22
 
@@ -41,7 +41,7 @@ class ContractFS implements IFileSystem {
41
41
  }));
42
42
  }
43
43
 
44
- async stat(entry: string, options?: StatOptions) {
44
+ async stat(entry: string, _options?: StatOptions) {
45
45
  const { data } = await this.client.stat({ path: entry });
46
46
  return {
47
47
  ...data,
@@ -72,7 +72,7 @@ class ContractFS implements IFileSystem {
72
72
 
73
73
  async writeFile(path: string, data: WritableData, options?: WriteFileOptions) {
74
74
  let buf = resolveData(data);
75
- await this.client.writeFile({ path, base64: ArrayBuffers.toBase64(buf), ...options });
75
+ await this.client.writeFile({ path, base64: ArrayBuffers.toBase64(buf as BufferSource), ...options });
76
76
  }
77
77
 
78
78
  async rename(oldPath: string, newPath: string, options?: RenameOptions) {
@@ -105,11 +105,11 @@ class ContractFS implements IFileSystem {
105
105
  });
106
106
  }
107
107
 
108
- createReadStream(path: string, options?: CreateReadStreamOptions): Readable {
108
+ createReadStream(_path: string, _options?: CreateReadStreamOptions): Readable {
109
109
  throw new Error('createReadStream is not implemented in ContractFS');
110
110
  }
111
111
 
112
- createWriteStream(path: string, options?: CreateWriteStreamOptions): Writable {
112
+ createWriteStream(_path: string, _options?: CreateWriteStreamOptions): Writable {
113
113
  throw new Error('createWriteStream is not implemented in ContractFS');
114
114
  }
115
115
  }
@@ -43,7 +43,7 @@ export function createFileSystemContractImpl(ifs: IFileSystem) {
43
43
  }),
44
44
  readFile: os.readFile.handler(async ({ input }) => {
45
45
  return {
46
- base64: ArrayBuffers.toBase64(await ifs.readFile(input.path, { encoding: 'binary' })),
46
+ base64: ArrayBuffers.toBase64((await ifs.readFile(input.path, { encoding: 'binary' })) as BufferSource),
47
47
  };
48
48
  }),
49
49
  writeFile: os.writeFile.handler(async ({ input }) => {
@@ -14,6 +14,7 @@ import type {
14
14
  RenameOptions,
15
15
  RmOptions,
16
16
  StatOptions,
17
+ WritableData,
17
18
  WriteFileOptions,
18
19
  } from '../IFileSystem';
19
20
 
@@ -71,7 +72,7 @@ export function createS3MiniFileSystem(options: CreateS3MiniFileSystemOptions =
71
72
  class S3FS implements IFileSystem {
72
73
  constructor(
73
74
  readonly client: S3mini,
74
- private readonly bucket: string,
75
+ readonly _bucket: string,
75
76
  private readonly prefix: string = '',
76
77
  ) {}
77
78
 
@@ -87,7 +88,7 @@ class S3FS implements IFileSystem {
87
88
 
88
89
  // Prepend prefix if set
89
90
  if (this.prefix) {
90
- return this.prefix + '/' + normalized;
91
+ return `${this.prefix}/${normalized}`;
91
92
  }
92
93
  return normalized;
93
94
  }
@@ -96,9 +97,9 @@ class S3FS implements IFileSystem {
96
97
  * Remove prefix from S3 key to get the file system path
97
98
  */
98
99
  private stripPrefix(key: string): string {
99
- if (!this.prefix || !key.startsWith(this.prefix + '/')) {
100
+ if (!this.prefix || !key.startsWith(`${this.prefix}/`)) {
100
101
  // If key doesn't start with prefix, return as-is (shouldn't happen normally)
101
- return key.startsWith('/') ? key : '/' + key;
102
+ return key.startsWith('/') ? key : `/${key}`;
102
103
  }
103
104
  const withoutPrefix = key.slice(this.prefix.length);
104
105
  return withoutPrefix || '/';
@@ -122,7 +123,7 @@ class S3FS implements IFileSystem {
122
123
  return '/';
123
124
  }
124
125
  const dir = dirname(key).replace(/\\/g, '/');
125
- return dir === '.' ? '/' : '/' + dir;
126
+ return dir === '.' ? '/' : `/${dir}`;
126
127
  }
127
128
 
128
129
  /**
@@ -164,66 +165,105 @@ class S3FS implements IFileSystem {
164
165
  this.checkAborted(signal);
165
166
 
166
167
  const dirPrefix = this.normalizeKey(dir);
167
- const prefixWithSlash = dirPrefix ? (dirPrefix.endsWith('/') ? dirPrefix : dirPrefix + '/') : '';
168
+ const prefixWithSlash = dirPrefix ? (dirPrefix.endsWith('/') ? dirPrefix : `${dirPrefix}/`) : '';
168
169
 
169
170
  try {
170
- // When delimiter is '/', S3 returns:
171
- // - Files: Key without trailing /, Size > 0
172
- // - Directories: Key with trailing /, Size: 0
173
- const delimiter = recursive ? undefined : '/';
174
-
175
- const objects = await this.client.listObjects(delimiter ?? '', prefixWithSlash, undefined, {
176
- delimiter,
177
- signal,
178
- });
171
+ const delimiter = recursive ? '' : '/';
172
+
173
+ // S3mini doesn't expose CommonPrefixes from delimiter-based listing.
174
+ // For non-recursive listing, we do two calls:
175
+ // 1. With delimiter to get direct files
176
+ // 2. Without delimiter to infer directory prefixes
177
+ let objects: Array<{ Key: string; Size: number | string; LastModified?: Date | string; ETag?: string }> = [];
178
+ let commonPrefixes: string[] = [];
179
+
180
+ if (delimiter && !recursive) {
181
+ const directObjects = await this.client.listObjects(delimiter, prefixWithSlash, undefined, {
182
+ delimiter,
183
+ signal,
184
+ });
185
+ if (directObjects) {
186
+ objects = directObjects;
187
+ }
188
+
189
+ // Infer CommonPrefixes by listing all objects recursively
190
+ const allObjectsRecursive = await this.client.listObjects('', prefixWithSlash, 1000, { signal });
191
+ if (allObjectsRecursive) {
192
+ const prefixSet = new Set<string>();
193
+ for (const obj of allObjectsRecursive) {
194
+ const key = obj.Key || '';
195
+ if (!key || !key.startsWith(prefixWithSlash)) continue;
196
+
197
+ const relativeKey = key.slice(prefixWithSlash.length);
198
+ const firstSlash = relativeKey.indexOf('/');
199
+ if (firstSlash > 0) {
200
+ prefixSet.add(prefixWithSlash + relativeKey.slice(0, firstSlash + 1));
201
+ }
202
+ }
203
+ commonPrefixes = Array.from(prefixSet).sort();
204
+ }
205
+ } else {
206
+ const listResult = await this.client.listObjects(delimiter, prefixWithSlash, undefined, { signal });
207
+ if (listResult) {
208
+ objects = listResult;
209
+ }
210
+ }
179
211
 
180
- if (!objects || objects.length === 0) {
212
+ if (!objects.length && !commonPrefixes.length) {
181
213
  return [];
182
214
  }
183
215
 
184
216
  let results: IFileStat[] = [];
185
- const seenPaths = new Set<string>();
186
217
 
187
- for (const obj of objects) {
218
+ // Process inferred CommonPrefixes (directories)
219
+ for (const prefix of commonPrefixes) {
188
220
  this.checkAborted(signal);
221
+ if (prefixWithSlash && !prefix.startsWith(prefixWithSlash)) continue;
189
222
 
190
- const key = obj.Key || '';
191
- if (!key) continue;
223
+ const relativePrefix = prefixWithSlash ? prefix.slice(prefixWithSlash.length) : prefix;
224
+ const dirName = relativePrefix.replace(/\/$/, '');
225
+ if (!dirName) continue;
192
226
 
193
- // Skip if not under our prefix
194
- if (prefixWithSlash && !key.startsWith(prefixWithSlash)) {
195
- continue;
227
+ if (!recursive && depth === 1) {
228
+ if (dirName.indexOf('/') >= 0) continue;
196
229
  }
197
230
 
198
- // Strip the prefix from the key for relative path calculation
199
- const relativeKey = prefixWithSlash ? key.slice(prefixWithSlash.length) : key;
231
+ const dirKey = prefix.endsWith('/') ? prefix : `${prefix}/`;
232
+ const stat = this.toFileStat(dirKey, {
233
+ Key: dirKey,
234
+ Size: 0,
235
+ LastModified: new Date(),
236
+ });
200
237
 
201
- // Skip empty relative keys (the directory itself)
202
- if (!relativeKey || relativeKey === '/') {
203
- continue;
204
- }
238
+ if (!hidden && stat.name.startsWith('.')) continue;
239
+ if (kind && stat.kind !== kind) continue;
205
240
 
206
- // Directory: Key ends with '/' (from CommonPrefixes or explicit marker)
207
- const isDir = key.endsWith('/');
241
+ results.push(stat);
242
+ }
243
+
244
+ // Process objects (files and explicit directory markers)
245
+ const seenDirs = new Set<string>();
246
+ for (const obj of objects) {
247
+ this.checkAborted(signal);
248
+
249
+ const key = obj.Key || '';
250
+ if (!key) continue;
251
+ if (prefixWithSlash && !key.startsWith(prefixWithSlash)) continue;
252
+
253
+ const relativeKey = prefixWithSlash ? key.slice(prefixWithSlash.length) : key;
254
+ if (!relativeKey || relativeKey === '/') continue;
208
255
 
209
- // For non-recursive, only show immediate children
210
256
  if (!recursive && depth === 1) {
211
- // For directories, the relative key looks like "dirname/"
212
- // For files, the relative key looks like "filename"
213
- // We only want immediate children, so no more slashes in the middle
214
- const keyWithoutTrailingSlash = relativeKey.replace(/\/$/, '');
215
- if (keyWithoutTrailingSlash.includes('/')) {
216
- // This is deeper than one level, skip
217
- continue;
218
- }
257
+ const firstSlash = relativeKey.indexOf('/');
258
+ if (firstSlash >= 0) continue;
219
259
  }
220
260
 
221
- // Deduplicate by path
222
- const pathKey = key.replace(/\/$/, ''); // Normalize for deduplication
223
- if (seenPaths.has(pathKey)) {
224
- continue;
261
+ const isDir = this.isDirectoryKey(key);
262
+ if (isDir) {
263
+ const dk = key.slice(0, -1);
264
+ if (seenDirs.has(dk)) continue;
265
+ seenDirs.add(dk);
225
266
  }
226
- seenPaths.add(pathKey);
227
267
 
228
268
  const stat = this.toFileStat(key, {
229
269
  Key: key,
@@ -232,15 +272,8 @@ class S3FS implements IFileSystem {
232
272
  ETag: obj.ETag,
233
273
  });
234
274
 
235
- // Filter by hidden
236
- if (!hidden && stat.name.startsWith('.')) {
237
- continue;
238
- }
239
-
240
- // Filter by kind
241
- if (kind && stat.kind !== kind) {
242
- continue;
243
- }
275
+ if (!hidden && stat.name.startsWith('.')) continue;
276
+ if (kind && stat.kind !== kind) continue;
244
277
 
245
278
  results.push(stat);
246
279
  }
@@ -316,7 +349,7 @@ class S3FS implements IFileSystem {
316
349
  }
317
350
 
318
351
  // If object not found, try checking if it's a directory (prefix listing)
319
- const dirKey = key.endsWith('/') ? key : key + '/';
352
+ const dirKey = key.endsWith('/') ? key : `${key}/`;
320
353
  const objects = await this.client.listObjects('/', dirKey, 1, { delimiter: '/', signal });
321
354
 
322
355
  if (objects && objects.length > 0) {
@@ -342,7 +375,7 @@ class S3FS implements IFileSystem {
342
375
  }
343
376
 
344
377
  async mkdir(path: string, options: MkdirOptions = {}): Promise<void> {
345
- const { recursive = false, signal } = options;
378
+ const { recursive: _recursive = false, signal } = options;
346
379
  this.checkAborted(signal);
347
380
 
348
381
  // In S3, directories don't actually exist - they're just prefixes
@@ -353,7 +386,7 @@ class S3FS implements IFileSystem {
353
386
  }
354
387
 
355
388
  // Ensure it ends with / to indicate directory
356
- const dirKey = key.endsWith('/') ? key : key + '/';
389
+ const dirKey = key.endsWith('/') ? key : `${key}/`;
357
390
 
358
391
  // Try to create a marker object (0-byte object)
359
392
  try {
@@ -403,11 +436,7 @@ class S3FS implements IFileSystem {
403
436
  }
404
437
  }
405
438
 
406
- async writeFile(
407
- path: string,
408
- data: string | Buffer | ArrayBuffer | Readable | ArrayBufferView,
409
- options: WriteFileOptions = {},
410
- ): Promise<void> {
439
+ async writeFile(path: string, data: WritableData, options: WriteFileOptions = {}): Promise<void> {
411
440
  const { signal, overwrite = true, onUploadProgress } = options;
412
441
  this.checkAborted(signal);
413
442
 
@@ -426,7 +455,24 @@ class S3FS implements IFileSystem {
426
455
 
427
456
  // Convert data to buffer or string
428
457
  let body: string | Buffer;
429
- if (data instanceof Readable) {
458
+ if (data instanceof ReadableStream) {
459
+ // Handle web ReadableStream
460
+ const reader = data.getReader();
461
+ const chunks: Uint8Array[] = [];
462
+ let loaded = 0;
463
+ while (true) {
464
+ const { done, value } = await reader.read();
465
+ if (done) break;
466
+ if (value) {
467
+ chunks.push(value);
468
+ loaded += value.length;
469
+ if (onUploadProgress) {
470
+ onUploadProgress({ loaded, total: -1 });
471
+ }
472
+ }
473
+ }
474
+ body = Buffer.concat(chunks);
475
+ } else if (data instanceof Readable) {
430
476
  // For streams, we need to read them into a buffer
431
477
  const chunks: Buffer[] = [];
432
478
  let loaded = 0;
@@ -466,12 +512,7 @@ class S3FS implements IFileSystem {
466
512
  // ArrayBufferView
467
513
  body = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
468
514
  }
469
-
470
- try {
471
- await this.client.putObject(key, body, undefined, undefined, undefined);
472
- } catch (error: any) {
473
- throw error;
474
- }
515
+ await this.client.putObject(key, body, undefined, undefined, undefined);
475
516
  }
476
517
 
477
518
  async rm(path: string, options: RmOptions = {}): Promise<void> {
@@ -486,7 +527,7 @@ class S3FS implements IFileSystem {
486
527
  try {
487
528
  if (recursive) {
488
529
  // List all objects with this prefix (no delimiter = recursive)
489
- const prefix = key.endsWith('/') ? key : key + '/';
530
+ const prefix = key.endsWith('/') ? key : `${key}/`;
490
531
  const objects = await this.client.listObjects('', prefix, undefined, { signal });
491
532
 
492
533
  if (objects) {
@@ -538,13 +579,13 @@ class S3FS implements IFileSystem {
538
579
  try {
539
580
  // Check if it's a directory (has objects with prefix)
540
581
  const isDir = oldKey.endsWith('/');
541
- const prefix = isDir ? oldKey : oldKey + '/';
582
+ const prefix = isDir ? oldKey : `${oldKey}/`;
542
583
 
543
584
  const objects = await this.client.listObjects('', prefix, undefined, { signal });
544
585
 
545
586
  if (objects && objects.length > 0) {
546
587
  // It's a directory or has multiple objects, move all
547
- const newPrefix = newKey.endsWith('/') ? newKey : newKey + '/';
588
+ const newPrefix = newKey.endsWith('/') ? newKey : `${newKey}/`;
548
589
 
549
590
  // Move all objects
550
591
  await Promise.all(
@@ -591,7 +632,7 @@ class S3FS implements IFileSystem {
591
632
  }
592
633
 
593
634
  // Check if it's a directory
594
- const dirKey = key.endsWith('/') ? key : key + '/';
635
+ const dirKey = key.endsWith('/') ? key : `${key}/`;
595
636
  const objects = await this.client.listObjects('/', dirKey, 1, { delimiter: '/' });
596
637
  return objects !== null && objects.length > 0;
597
638
  } catch {
@@ -624,8 +665,8 @@ class S3FS implements IFileSystem {
624
665
 
625
666
  if (srcStat.kind === 'directory') {
626
667
  // Copy directory recursively
627
- const srcPrefix = srcKey.endsWith('/') ? srcKey : srcKey + '/';
628
- const destPrefix = destKey.endsWith('/') ? destKey : destKey + '/';
668
+ const srcPrefix = srcKey.endsWith('/') ? srcKey : `${srcKey}/`;
669
+ const destPrefix = destKey.endsWith('/') ? destKey : `${destKey}/`;
629
670
 
630
671
  const objects = await this.client.listObjects(shallow ? '/' : '', srcPrefix, undefined, {
631
672
  ...(shallow ? { delimiter: '/' } : {}),
@@ -691,7 +732,7 @@ class S3FS implements IFileSystem {
691
732
 
692
733
  // Convert ReadableStream to Node Readable
693
734
  const reader = response.body.getReader();
694
- const decoder = new TextDecoder();
735
+ const _decoder = new TextDecoder();
695
736
 
696
737
  nodeStream = new Readable({
697
738
  async read() {
@@ -781,7 +822,7 @@ class S3FS implements IFileSystem {
781
822
  throw new Error('Cannot write to root directory');
782
823
  }
783
824
 
784
- const { signal, overwrite = true } = options;
825
+ const { signal, overwrite: _overwrite = true } = options;
785
826
  this.checkAborted(signal);
786
827
 
787
828
  // Create a WritableStream that buffers data and uploads when done
@@ -814,7 +855,7 @@ class S3FS implements IFileSystem {
814
855
  });
815
856
  }
816
857
 
817
- getUrl(path: IFileStat | string, options?: any): string | undefined {
858
+ getUrl(path: IFileStat | string, _options?: any): string | undefined {
818
859
  if (typeof path === 'object' && path?.kind !== 'file') {
819
860
  return;
820
861
  }