@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,133 +1,141 @@
1
1
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
- try {
3
- var info = gen[key](arg);
4
- var value = info.value;
5
- } catch (error) {
6
- reject(error);
7
- return;
8
- }
9
- if (info.done) {
10
- resolve(value);
11
- } else {
12
- Promise.resolve(value).then(_next, _throw);
13
- }
2
+ try {
3
+ var info = gen[key](arg);
4
+ var value = info.value;
5
+ } catch (error) {
6
+ reject(error);
7
+ return;
8
+ }
9
+ if (info.done) {
10
+ resolve(value);
11
+ } else {
12
+ Promise.resolve(value).then(_next, _throw);
13
+ }
14
14
  }
15
15
  function _async_to_generator(fn) {
16
- return function() {
17
- var self = this, args = arguments;
18
- return new Promise(function(resolve, reject) {
19
- var gen = fn.apply(self, args);
20
- function _next(value) {
21
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
- }
23
- function _throw(err) {
24
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
- }
26
- _next(undefined);
27
- });
28
- };
16
+ return function () {
17
+ var args = arguments;
18
+ return new Promise((resolve, reject) => {
19
+ var gen = fn.apply(this, args);
20
+ function _next(value) {
21
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
22
+ }
23
+ function _throw(err) {
24
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
25
+ }
26
+ _next(undefined);
27
+ });
28
+ };
29
29
  }
30
30
  function _ts_generator(thisArg, body) {
31
- var f, y, t, _ = {
32
- label: 0,
33
- sent: function() {
34
- if (t[0] & 1) throw t[1];
35
- return t[1];
36
- },
37
- trys: [],
38
- ops: []
39
- }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
40
- return d(g, "next", {
41
- value: verb(0)
42
- }), d(g, "throw", {
43
- value: verb(1)
44
- }), d(g, "return", {
45
- value: verb(2)
46
- }), typeof Symbol === "function" && d(g, Symbol.iterator, {
47
- value: function() {
48
- return this;
49
- }
50
- }), g;
51
- function verb(n) {
52
- return function(v) {
53
- return step([
54
- n,
55
- v
56
- ]);
57
- };
58
- }
59
- function step(op) {
60
- if (f) throw new TypeError("Generator is already executing.");
61
- while(g && (g = 0, op[0] && (_ = 0)), _)try {
62
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
63
- if (y = 0, t) op = [
64
- op[0] & 2,
65
- t.value
66
- ];
67
- switch(op[0]){
68
- case 0:
69
- case 1:
70
- t = op;
71
- break;
72
- case 4:
73
- _.label++;
74
- return {
75
- value: op[1],
76
- done: false
77
- };
78
- case 5:
79
- _.label++;
80
- y = op[1];
81
- op = [
82
- 0
83
- ];
84
- continue;
85
- case 7:
86
- op = _.ops.pop();
87
- _.trys.pop();
88
- continue;
89
- default:
90
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
91
- _ = 0;
92
- continue;
93
- }
94
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
95
- _.label = op[1];
96
- break;
97
- }
98
- if (op[0] === 6 && _.label < t[1]) {
99
- _.label = t[1];
100
- t = op;
101
- break;
102
- }
103
- if (t && _.label < t[2]) {
104
- _.label = t[2];
105
- _.ops.push(op);
106
- break;
107
- }
108
- if (t[2]) _.ops.pop();
109
- _.trys.pop();
110
- continue;
111
- }
112
- op = body.call(thisArg, _);
113
- } catch (e) {
114
- op = [
115
- 6,
116
- e
117
- ];
118
- y = 0;
119
- } finally{
120
- f = t = 0;
121
- }
122
- if (op[0] & 5) throw op[1];
123
- return {
124
- value: op[0] ? op[1] : void 0,
125
- done: true
126
- };
127
- }
31
+ var f,
32
+ y,
33
+ t,
34
+ _ = {
35
+ label: 0,
36
+ sent: () => {
37
+ if (t[0] & 1) throw t[1];
38
+ return t[1];
39
+ },
40
+ trys: [],
41
+ ops: [],
42
+ },
43
+ g = Object.create((typeof Iterator === 'function' ? Iterator : Object).prototype),
44
+ d = Object.defineProperty;
45
+ return (
46
+ d(g, 'next', {
47
+ value: verb(0),
48
+ }),
49
+ d(g, 'throw', {
50
+ value: verb(1),
51
+ }),
52
+ d(g, 'return', {
53
+ value: verb(2),
54
+ }),
55
+ typeof Symbol === 'function' &&
56
+ d(g, Symbol.iterator, {
57
+ value: function () {
58
+ return this;
59
+ },
60
+ }),
61
+ g
62
+ );
63
+ function verb(n) {
64
+ return (v) => step([n, v]);
65
+ }
66
+ function step(op) {
67
+ if (f) throw new TypeError('Generator is already executing.');
68
+ while ((g && ((g = 0), op[0] && (_ = 0)), _))
69
+ try {
70
+ if (
71
+ ((f = 1),
72
+ y &&
73
+ (t = op[0] & 2 ? y['return'] : op[0] ? y['throw'] || ((t = y['return']) && t.call(y), 0) : y.next) &&
74
+ !(t = t.call(y, op[1])).done)
75
+ )
76
+ return t;
77
+ if (((y = 0), t)) op = [op[0] & 2, t.value];
78
+ switch (op[0]) {
79
+ case 0:
80
+ case 1:
81
+ t = op;
82
+ break;
83
+ case 4:
84
+ _.label++;
85
+ return {
86
+ value: op[1],
87
+ done: false,
88
+ };
89
+ case 5:
90
+ _.label++;
91
+ y = op[1];
92
+ op = [0];
93
+ continue;
94
+ case 7:
95
+ op = _.ops.pop();
96
+ _.trys.pop();
97
+ continue;
98
+ default:
99
+ if (!((t = _.trys), (t = t.length > 0 && t[t.length - 1])) && (op[0] === 6 || op[0] === 2)) {
100
+ _ = 0;
101
+ continue;
102
+ }
103
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
104
+ _.label = op[1];
105
+ break;
106
+ }
107
+ if (op[0] === 6 && _.label < t[1]) {
108
+ _.label = t[1];
109
+ t = op;
110
+ break;
111
+ }
112
+ if (t && _.label < t[2]) {
113
+ _.label = t[2];
114
+ _.ops.push(op);
115
+ break;
116
+ }
117
+ if (t[2]) _.ops.pop();
118
+ _.trys.pop();
119
+ continue;
120
+ }
121
+ op = body.call(thisArg, _);
122
+ } catch (e) {
123
+ op = [6, e];
124
+ y = 0;
125
+ } finally {
126
+ f = t = 0;
127
+ }
128
+ if (op[0] & 5) throw op[1];
129
+ return {
130
+ value: op[0] ? op[1] : void 0,
131
+ done: true,
132
+ };
133
+ }
128
134
  }
135
+
129
136
  import { S3mini } from 's3mini';
130
137
  import { afterAll, beforeAll, describe, expect, test } from 'vitest';
138
+
131
139
  /**
132
140
  * Tests for s3mini and S3 filesystem behavior
133
141
  *
@@ -143,272 +151,233 @@ import { afterAll, beforeAll, describe, expect, test } from 'vitest';
143
151
  */ // Set to true to run network tests
144
152
  var RUN_NETWORK_TESTS = process.env.RUN_S3_NETWORK_TESTS === 'true';
145
153
  // Generate unique bucket name for this test run
146
- var TEST_BUCKET = "s3mini-test-".concat(Date.now());
147
- describe('s3mini with MinIO Play', function() {
148
- var client;
149
- beforeAll(function() {
150
- return _async_to_generator(function() {
151
- var e;
152
- return _ts_generator(this, function(_state) {
153
- switch(_state.label){
154
- case 0:
155
- if (!RUN_NETWORK_TESTS) return [
156
- 2
157
- ];
158
- // s3mini expects bucket name in the endpoint URL
159
- client = new S3mini({
160
- endpoint: "https://play.min.io/".concat(TEST_BUCKET),
161
- accessKeyId: 'Q3AM3UQ867SPQQA43P2F',
162
- secretAccessKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG',
163
- region: 'us-east-1'
164
- });
165
- _state.label = 1;
166
- case 1:
167
- _state.trys.push([
168
- 1,
169
- 3,
170
- ,
171
- 4
172
- ]);
173
- return [
174
- 4,
175
- client.createBucket()
176
- ];
177
- case 2:
178
- _state.sent();
179
- console.log("Created bucket: ".concat(TEST_BUCKET));
180
- return [
181
- 3,
182
- 4
183
- ];
184
- case 3:
185
- e = _state.sent();
186
- console.log('Bucket creation error:', e);
187
- return [
188
- 3,
189
- 4
190
- ];
191
- case 4:
192
- return [
193
- 2
194
- ];
195
- }
196
- });
197
- })();
198
- });
199
- afterAll(function() {
200
- return _async_to_generator(function() {
201
- var objects, keys, e;
202
- return _ts_generator(this, function(_state) {
203
- switch(_state.label){
204
- case 0:
205
- if (!RUN_NETWORK_TESTS || !client) return [
206
- 2
207
- ];
208
- _state.label = 1;
209
- case 1:
210
- _state.trys.push([
211
- 1,
212
- 5,
213
- ,
214
- 6
215
- ]);
216
- return [
217
- 4,
218
- client.listObjects('/', '', 1000)
219
- ];
220
- case 2:
221
- objects = _state.sent();
222
- if (!(objects && objects.length > 0)) return [
223
- 3,
224
- 4
225
- ];
226
- keys = objects.map(function(o) {
227
- return o.Key;
228
- }).filter(Boolean);
229
- if (!(keys.length > 0)) return [
230
- 3,
231
- 4
232
- ];
233
- return [
234
- 4,
235
- client.deleteObjects(keys)
236
- ];
237
- case 3:
238
- _state.sent();
239
- _state.label = 4;
240
- case 4:
241
- return [
242
- 3,
243
- 6
244
- ];
245
- case 5:
246
- e = _state.sent();
247
- console.log('Cleanup error:', e);
248
- return [
249
- 3,
250
- 6
251
- ];
252
- case 6:
253
- return [
254
- 2
255
- ];
256
- }
257
- });
258
- })();
259
- });
260
- describe.skipIf(!RUN_NETWORK_TESTS)('listObjects with delimiter', function() {
261
- test('should list objects and detect directories', function() {
262
- return _async_to_generator(function() {
263
- var objects, dirs, files, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, dir, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, file;
264
- return _ts_generator(this, function(_state) {
265
- switch(_state.label){
266
- case 0:
267
- // Create test structure
268
- return [
269
- 4,
270
- client.putObject('file1.txt', 'content1')
271
- ];
272
- case 1:
273
- _state.sent();
274
- return [
275
- 4,
276
- client.putObject('file2.txt', 'content2')
277
- ];
278
- case 2:
279
- _state.sent();
280
- return [
281
- 4,
282
- client.putObject('dir1/', '')
283
- ];
284
- case 3:
285
- _state.sent(); // Directory marker
286
- return [
287
- 4,
288
- client.putObject('dir1/nested.txt', 'nested content')
289
- ];
290
- case 4:
291
- _state.sent();
292
- return [
293
- 4,
294
- client.putObject('dir2/', '')
295
- ];
296
- case 5:
297
- _state.sent(); // Another directory marker
298
- return [
299
- 4,
300
- client.listObjects('/', '', 100, {
301
- delimiter: '/'
302
- })
303
- ];
304
- case 6:
305
- objects = _state.sent();
306
- console.log('MinIO Play listing with delimiter:', JSON.stringify(objects, null, 2));
307
- expect(objects).toBeDefined();
308
- expect(Array.isArray(objects)).toBe(true);
309
- if (objects && objects.length > 0) {
310
- // Check for files and directories
311
- dirs = objects.filter(function(o) {
312
- var _o_Key;
313
- return (_o_Key = o.Key) === null || _o_Key === void 0 ? void 0 : _o_Key.endsWith('/');
314
- });
315
- files = objects.filter(function(o) {
316
- var _o_Key;
317
- return !((_o_Key = o.Key) === null || _o_Key === void 0 ? void 0 : _o_Key.endsWith('/'));
318
- });
319
- console.log("Found ".concat(dirs.length, " directories and ").concat(files.length, " files"));
320
- console.log('Directories:', dirs.map(function(d) {
321
- return d.Key;
322
- }));
323
- console.log('Files:', files.map(function(f) {
324
- return f.Key;
325
- }));
326
- _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
327
- try {
328
- // Directories should have Size: 0
329
- for(_iterator = dirs[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
330
- dir = _step.value;
331
- expect(Number(dir.Size)).toBe(0);
332
- expect(dir.Key).toMatch(/\/$/);
333
- }
334
- } catch (err) {
335
- _didIteratorError = true;
336
- _iteratorError = err;
337
- } finally{
338
- try {
339
- if (!_iteratorNormalCompletion && _iterator.return != null) {
340
- _iterator.return();
341
- }
342
- } finally{
343
- if (_didIteratorError) {
344
- throw _iteratorError;
345
- }
346
- }
347
- }
348
- _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
349
- try {
350
- // Files should have Size > 0
351
- for(_iterator1 = files[Symbol.iterator](); !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
352
- file = _step1.value;
353
- expect(Number(file.Size)).toBeGreaterThan(0);
354
- expect(file.Key).not.toMatch(/\/$/);
355
- }
356
- } catch (err) {
357
- _didIteratorError1 = true;
358
- _iteratorError1 = err;
359
- } finally{
360
- try {
361
- if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
362
- _iterator1.return();
363
- }
364
- } finally{
365
- if (_didIteratorError1) {
366
- throw _iteratorError1;
367
- }
368
- }
369
- }
370
- }
371
- return [
372
- 2
373
- ];
374
- }
375
- });
376
- })();
377
- });
378
- test('should list nested directory contents', function() {
379
- return _async_to_generator(function() {
380
- var objects, files;
381
- return _ts_generator(this, function(_state) {
382
- switch(_state.label){
383
- case 0:
384
- return [
385
- 4,
386
- client.listObjects('/', 'dir1/', 100, {
387
- delimiter: '/'
388
- })
389
- ];
390
- case 1:
391
- objects = _state.sent();
392
- console.log('MinIO Play dir1/ listing:', JSON.stringify(objects, null, 2));
393
- expect(objects).toBeDefined();
394
- expect(Array.isArray(objects)).toBe(true);
395
- // Should find nested.txt
396
- files = (objects === null || objects === void 0 ? void 0 : objects.filter(function(o) {
397
- var _o_Key;
398
- return !((_o_Key = o.Key) === null || _o_Key === void 0 ? void 0 : _o_Key.endsWith('/'));
399
- })) || [];
400
- expect(files.some(function(f) {
401
- var _f_Key;
402
- return (_f_Key = f.Key) === null || _f_Key === void 0 ? void 0 : _f_Key.includes('nested.txt');
403
- })).toBe(true);
404
- return [
405
- 2
406
- ];
407
- }
408
- });
409
- })();
410
- });
411
- });
154
+ var TEST_BUCKET = 's3mini-test-'.concat(Date.now());
155
+ describe('s3mini with MinIO Play', () => {
156
+ var client;
157
+ beforeAll(() =>
158
+ _async_to_generator(function () {
159
+ var e;
160
+ return _ts_generator(this, (_state) => {
161
+ switch (_state.label) {
162
+ case 0:
163
+ if (!RUN_NETWORK_TESTS) return [2];
164
+ // s3mini expects bucket name in the endpoint URL
165
+ client = new S3mini({
166
+ endpoint: 'https://play.min.io/'.concat(TEST_BUCKET),
167
+ accessKeyId: 'Q3AM3UQ867SPQQA43P2F',
168
+ secretAccessKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG',
169
+ region: 'us-east-1',
170
+ });
171
+ _state.label = 1;
172
+ case 1:
173
+ _state.trys.push([1, 3, , 4]);
174
+ return [4, client.createBucket()];
175
+ case 2:
176
+ _state.sent();
177
+ console.log('Created bucket: '.concat(TEST_BUCKET));
178
+ return [3, 4];
179
+ case 3:
180
+ e = _state.sent();
181
+ console.log('Bucket creation error:', e);
182
+ return [3, 4];
183
+ case 4:
184
+ return [2];
185
+ }
186
+ });
187
+ })(),
188
+ );
189
+ afterAll(() =>
190
+ _async_to_generator(function () {
191
+ var objects, keys, e;
192
+ return _ts_generator(this, (_state) => {
193
+ switch (_state.label) {
194
+ case 0:
195
+ if (!RUN_NETWORK_TESTS || !client) return [2];
196
+ _state.label = 1;
197
+ case 1:
198
+ _state.trys.push([1, 5, , 6]);
199
+ return [4, client.listObjects('/', '', 1000)];
200
+ case 2:
201
+ objects = _state.sent();
202
+ if (!(objects && objects.length > 0)) return [3, 4];
203
+ keys = objects.map((o) => o.Key).filter(Boolean);
204
+ if (!(keys.length > 0)) return [3, 4];
205
+ return [4, client.deleteObjects(keys)];
206
+ case 3:
207
+ _state.sent();
208
+ _state.label = 4;
209
+ case 4:
210
+ return [3, 6];
211
+ case 5:
212
+ e = _state.sent();
213
+ console.log('Cleanup error:', e);
214
+ return [3, 6];
215
+ case 6:
216
+ return [2];
217
+ }
218
+ });
219
+ })(),
220
+ );
221
+ describe.skipIf(!RUN_NETWORK_TESTS)('listObjects with delimiter', () => {
222
+ test('should list objects and detect directories', () =>
223
+ _async_to_generator(function () {
224
+ var objects,
225
+ dirs,
226
+ files,
227
+ _iteratorNormalCompletion,
228
+ _didIteratorError,
229
+ _iteratorError,
230
+ _iterator,
231
+ _step,
232
+ dir,
233
+ _iteratorNormalCompletion1,
234
+ _didIteratorError1,
235
+ _iteratorError1,
236
+ _iterator1,
237
+ _step1,
238
+ file;
239
+ return _ts_generator(this, (_state) => {
240
+ switch (_state.label) {
241
+ case 0:
242
+ // Create test structure
243
+ return [4, client.putObject('file1.txt', 'content1')];
244
+ case 1:
245
+ _state.sent();
246
+ return [4, client.putObject('file2.txt', 'content2')];
247
+ case 2:
248
+ _state.sent();
249
+ return [4, client.putObject('dir1/', '')];
250
+ case 3:
251
+ _state.sent(); // Directory marker
252
+ return [4, client.putObject('dir1/nested.txt', 'nested content')];
253
+ case 4:
254
+ _state.sent();
255
+ return [4, client.putObject('dir2/', '')];
256
+ case 5:
257
+ _state.sent(); // Another directory marker
258
+ return [
259
+ 4,
260
+ client.listObjects('/', '', 100, {
261
+ delimiter: '/',
262
+ }),
263
+ ];
264
+ case 6:
265
+ objects = _state.sent();
266
+ console.log('MinIO Play listing with delimiter:', JSON.stringify(objects, null, 2));
267
+ expect(objects).toBeDefined();
268
+ expect(Array.isArray(objects)).toBe(true);
269
+ if (objects && objects.length > 0) {
270
+ // Check for files and directories
271
+ dirs = objects.filter((o) => {
272
+ var _o_Key;
273
+ return (_o_Key = o.Key) === null || _o_Key === void 0 ? void 0 : _o_Key.endsWith('/');
274
+ });
275
+ files = objects.filter((o) => {
276
+ var _o_Key;
277
+ return !((_o_Key = o.Key) === null || _o_Key === void 0 ? void 0 : _o_Key.endsWith('/'));
278
+ });
279
+ console.log('Found '.concat(dirs.length, ' directories and ').concat(files.length, ' files'));
280
+ console.log(
281
+ 'Directories:',
282
+ dirs.map((d) => d.Key),
283
+ );
284
+ console.log(
285
+ 'Files:',
286
+ files.map((f) => f.Key),
287
+ );
288
+ (_iteratorNormalCompletion = true), (_didIteratorError = false), (_iteratorError = undefined);
289
+ try {
290
+ // Directories should have Size: 0
291
+ for (
292
+ _iterator = dirs[Symbol.iterator]();
293
+ !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
294
+ _iteratorNormalCompletion = true
295
+ ) {
296
+ dir = _step.value;
297
+ expect(Number(dir.Size)).toBe(0);
298
+ expect(dir.Key).toMatch(/\/$/);
299
+ }
300
+ } catch (err) {
301
+ _didIteratorError = true;
302
+ _iteratorError = err;
303
+ } finally {
304
+ try {
305
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
306
+ _iterator.return();
307
+ }
308
+ } finally {
309
+ if (_didIteratorError) {
310
+ throw _iteratorError;
311
+ }
312
+ }
313
+ }
314
+ (_iteratorNormalCompletion1 = true), (_didIteratorError1 = false), (_iteratorError1 = undefined);
315
+ try {
316
+ // Files should have Size > 0
317
+ for (
318
+ _iterator1 = files[Symbol.iterator]();
319
+ !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done);
320
+ _iteratorNormalCompletion1 = true
321
+ ) {
322
+ file = _step1.value;
323
+ expect(Number(file.Size)).toBeGreaterThan(0);
324
+ expect(file.Key).not.toMatch(/\/$/);
325
+ }
326
+ } catch (err) {
327
+ _didIteratorError1 = true;
328
+ _iteratorError1 = err;
329
+ } finally {
330
+ try {
331
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
332
+ _iterator1.return();
333
+ }
334
+ } finally {
335
+ if (_didIteratorError1) {
336
+ throw _iteratorError1;
337
+ }
338
+ }
339
+ }
340
+ }
341
+ return [2];
342
+ }
343
+ });
344
+ })());
345
+ test('should list nested directory contents', () =>
346
+ _async_to_generator(function () {
347
+ var objects, files;
348
+ return _ts_generator(this, (_state) => {
349
+ switch (_state.label) {
350
+ case 0:
351
+ return [
352
+ 4,
353
+ client.listObjects('/', 'dir1/', 100, {
354
+ delimiter: '/',
355
+ }),
356
+ ];
357
+ case 1:
358
+ objects = _state.sent();
359
+ console.log('MinIO Play dir1/ listing:', JSON.stringify(objects, null, 2));
360
+ expect(objects).toBeDefined();
361
+ expect(Array.isArray(objects)).toBe(true);
362
+ // Should find nested.txt
363
+ files =
364
+ (objects === null || objects === void 0
365
+ ? void 0
366
+ : objects.filter((o) => {
367
+ var _o_Key;
368
+ return !((_o_Key = o.Key) === null || _o_Key === void 0 ? void 0 : _o_Key.endsWith('/'));
369
+ })) || [];
370
+ expect(
371
+ files.some((f) => {
372
+ var _f_Key;
373
+ return (_f_Key = f.Key) === null || _f_Key === void 0 ? void 0 : _f_Key.includes('nested.txt');
374
+ }),
375
+ ).toBe(true);
376
+ return [2];
377
+ }
378
+ });
379
+ })());
380
+ });
412
381
  });
413
382
  /**
414
383
  * Unit tests for S3 directory detection logic (no network required)
@@ -416,169 +385,171 @@ describe('s3mini with MinIO Play', function() {
416
385
  * When using delimiter: '/' with listObjects, S3 returns:
417
386
  * - Files: Key without trailing /, Size > 0
418
387
  * - Directories: Key with trailing /, Size: 0
419
- */ describe('s3mini listObjects behavior', function() {
420
- test('directory detection logic - directories end with / and have Size: 0', function() {
421
- // Mock response similar to user's example
422
- var mockResponse = [
423
- {
424
- Key: 'fusion/README.md',
425
- LastModified: '2025-12-18T01:51:09.000Z',
426
- ETag: '"adc69293e8fd256b2609664f1e11cb53"',
427
- Size: 6,
428
- StorageClass: 'STANDARD'
429
- },
430
- {
431
- Key: 'fusion/home/',
432
- Size: 0,
433
- LastModified: new Date('1970-01-01T00:00:00.000Z'),
434
- ETag: '',
435
- StorageClass: ''
436
- },
437
- {
438
- Key: 'fusion/mcp/',
439
- Size: 0,
440
- LastModified: new Date('1970-01-01T00:00:00.000Z'),
441
- ETag: '',
442
- StorageClass: ''
443
- }
444
- ];
445
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
446
- try {
447
- // Test directory detection logic
448
- for(var _iterator = mockResponse[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
449
- var obj = _step.value;
450
- var isDir = obj.Key.endsWith('/');
451
- if (isDir) {
452
- expect(obj.Size).toBe(0);
453
- expect(obj.Key).toMatch(/\/$/);
454
- } else {
455
- expect(obj.Size).toBeGreaterThan(0);
456
- expect(obj.Key).not.toMatch(/\/$/);
457
- }
458
- }
459
- } catch (err) {
460
- _didIteratorError = true;
461
- _iteratorError = err;
462
- } finally{
463
- try {
464
- if (!_iteratorNormalCompletion && _iterator.return != null) {
465
- _iterator.return();
466
- }
467
- } finally{
468
- if (_didIteratorError) {
469
- throw _iteratorError;
470
- }
471
- }
472
- }
473
- // Count directories and files
474
- var dirs = mockResponse.filter(function(o) {
475
- return o.Key.endsWith('/');
476
- });
477
- var files = mockResponse.filter(function(o) {
478
- return !o.Key.endsWith('/');
479
- });
480
- expect(dirs).toHaveLength(2);
481
- expect(files).toHaveLength(1);
482
- });
483
- test('readdir should properly identify directories from S3 response', function() {
484
- var s3Response = [
485
- {
486
- Key: 'fusion/README.md',
487
- Size: 6,
488
- LastModified: new Date(),
489
- ETag: '"abc"'
490
- },
491
- {
492
- Key: 'fusion/home/',
493
- Size: 0,
494
- LastModified: new Date(0),
495
- ETag: ''
496
- },
497
- {
498
- Key: 'fusion/mcp/',
499
- Size: 0,
500
- LastModified: new Date(0),
501
- ETag: ''
502
- }
503
- ];
504
- var results = s3Response.map(function(obj) {
505
- var key = obj.Key;
506
- var isDir = key.endsWith('/');
507
- var name = isDir ? key.slice(0, -1).split('/').pop() : key.split('/').pop();
508
- return {
509
- name: name,
510
- kind: isDir ? 'directory' : 'file',
511
- size: obj.Size
512
- };
513
- });
514
- expect(results).toEqual([
515
- {
516
- name: 'README.md',
517
- kind: 'file',
518
- size: 6
519
- },
520
- {
521
- name: 'home',
522
- kind: 'directory',
523
- size: 0
524
- },
525
- {
526
- name: 'mcp',
527
- kind: 'directory',
528
- size: 0
529
- }
530
- ]);
531
- });
532
- test('should handle nested paths correctly', function() {
533
- var s3Response = [
534
- {
535
- Key: 'data/2024/01/file.csv',
536
- Size: 1024
537
- },
538
- {
539
- Key: 'data/2024/02/',
540
- Size: 0
541
- },
542
- {
543
- Key: 'data/config.json',
544
- Size: 256
545
- }
546
- ];
547
- var prefix = 'data/';
548
- var results = s3Response.map(function(obj) {
549
- var key = obj.Key;
550
- var relativeKey = key.startsWith(prefix) ? key.slice(prefix.length) : key;
551
- var isDir = key.endsWith('/');
552
- var parts = relativeKey.split('/').filter(Boolean);
553
- var name = parts[0];
554
- return {
555
- key: key,
556
- relativeKey: relativeKey,
557
- name: name,
558
- isDir: isDir
559
- };
560
- });
561
- // For non-recursive listing, only want immediate children
562
- var immediateChildren = results.filter(function(r) {
563
- var keyWithoutTrailingSlash = r.relativeKey.replace(/\/$/, '');
564
- return !keyWithoutTrailingSlash.includes('/');
565
- });
566
- expect(immediateChildren).toHaveLength(1);
567
- expect(immediateChildren[0].name).toBe('config.json');
568
- });
569
- test('should correctly strip prefix and build file stat', function() {
570
- var prefix = 'myapp/data';
571
- var normalizedPrefix = prefix.replace(/^\/+/, '').replace(/\/+$/, '');
572
- var stripPrefix = function(key) {
573
- if (!normalizedPrefix || !key.startsWith(normalizedPrefix + '/')) {
574
- return key.startsWith('/') ? key : '/' + key;
575
- }
576
- var withoutPrefix = key.slice(normalizedPrefix.length);
577
- return withoutPrefix || '/';
578
- };
579
- expect(stripPrefix('myapp/data/file.txt')).toBe('/file.txt');
580
- expect(stripPrefix('myapp/data/subdir/')).toBe('/subdir/');
581
- expect(stripPrefix('myapp/data/')).toBe('/');
582
- expect(stripPrefix('other/path')).toBe('/other/path');
583
- });
388
+ */ describe('s3mini listObjects behavior', () => {
389
+ test('directory detection logic - directories end with / and have Size: 0', () => {
390
+ // Mock response similar to user's example
391
+ var mockResponse = [
392
+ {
393
+ Key: 'fusion/README.md',
394
+ LastModified: '2025-12-18T01:51:09.000Z',
395
+ ETag: '"adc69293e8fd256b2609664f1e11cb53"',
396
+ Size: 6,
397
+ StorageClass: 'STANDARD',
398
+ },
399
+ {
400
+ Key: 'fusion/home/',
401
+ Size: 0,
402
+ LastModified: new Date('1970-01-01T00:00:00.000Z'),
403
+ ETag: '',
404
+ StorageClass: '',
405
+ },
406
+ {
407
+ Key: 'fusion/mcp/',
408
+ Size: 0,
409
+ LastModified: new Date('1970-01-01T00:00:00.000Z'),
410
+ ETag: '',
411
+ StorageClass: '',
412
+ },
413
+ ];
414
+ var _iteratorNormalCompletion = true,
415
+ _didIteratorError = false,
416
+ _iteratorError;
417
+ try {
418
+ // Test directory detection logic
419
+ for (
420
+ var _iterator = mockResponse[Symbol.iterator](), _step;
421
+ !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
422
+ _iteratorNormalCompletion = true
423
+ ) {
424
+ var obj = _step.value;
425
+ var isDir = obj.Key.endsWith('/');
426
+ if (isDir) {
427
+ expect(obj.Size).toBe(0);
428
+ expect(obj.Key).toMatch(/\/$/);
429
+ } else {
430
+ expect(obj.Size).toBeGreaterThan(0);
431
+ expect(obj.Key).not.toMatch(/\/$/);
432
+ }
433
+ }
434
+ } catch (err) {
435
+ _didIteratorError = true;
436
+ _iteratorError = err;
437
+ } finally {
438
+ try {
439
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
440
+ _iterator.return();
441
+ }
442
+ } finally {
443
+ if (_didIteratorError) {
444
+ throw _iteratorError;
445
+ }
446
+ }
447
+ }
448
+ // Count directories and files
449
+ var dirs = mockResponse.filter((o) => o.Key.endsWith('/'));
450
+ var files = mockResponse.filter((o) => !o.Key.endsWith('/'));
451
+ expect(dirs).toHaveLength(2);
452
+ expect(files).toHaveLength(1);
453
+ });
454
+ test('readdir should properly identify directories from S3 response', () => {
455
+ var s3Response = [
456
+ {
457
+ Key: 'fusion/README.md',
458
+ Size: 6,
459
+ LastModified: new Date(),
460
+ ETag: '"abc"',
461
+ },
462
+ {
463
+ Key: 'fusion/home/',
464
+ Size: 0,
465
+ LastModified: new Date(0),
466
+ ETag: '',
467
+ },
468
+ {
469
+ Key: 'fusion/mcp/',
470
+ Size: 0,
471
+ LastModified: new Date(0),
472
+ ETag: '',
473
+ },
474
+ ];
475
+ var results = s3Response.map((obj) => {
476
+ var key = obj.Key;
477
+ var isDir = key.endsWith('/');
478
+ var name = isDir ? key.slice(0, -1).split('/').pop() : key.split('/').pop();
479
+ return {
480
+ name: name,
481
+ kind: isDir ? 'directory' : 'file',
482
+ size: obj.Size,
483
+ };
484
+ });
485
+ expect(results).toEqual([
486
+ {
487
+ name: 'README.md',
488
+ kind: 'file',
489
+ size: 6,
490
+ },
491
+ {
492
+ name: 'home',
493
+ kind: 'directory',
494
+ size: 0,
495
+ },
496
+ {
497
+ name: 'mcp',
498
+ kind: 'directory',
499
+ size: 0,
500
+ },
501
+ ]);
502
+ });
503
+ test('should handle nested paths correctly', () => {
504
+ var s3Response = [
505
+ {
506
+ Key: 'data/2024/01/file.csv',
507
+ Size: 1024,
508
+ },
509
+ {
510
+ Key: 'data/2024/02/',
511
+ Size: 0,
512
+ },
513
+ {
514
+ Key: 'data/config.json',
515
+ Size: 256,
516
+ },
517
+ ];
518
+ var prefix = 'data/';
519
+ var results = s3Response.map((obj) => {
520
+ var key = obj.Key;
521
+ var relativeKey = key.startsWith(prefix) ? key.slice(prefix.length) : key;
522
+ var isDir = key.endsWith('/');
523
+ var parts = relativeKey.split('/').filter(Boolean);
524
+ var name = parts[0];
525
+ return {
526
+ key: key,
527
+ relativeKey: relativeKey,
528
+ name: name,
529
+ isDir: isDir,
530
+ };
531
+ });
532
+ // For non-recursive listing, only want immediate children
533
+ var immediateChildren = results.filter((r) => {
534
+ var keyWithoutTrailingSlash = r.relativeKey.replace(/\/$/, '');
535
+ return !keyWithoutTrailingSlash.includes('/');
536
+ });
537
+ expect(immediateChildren).toHaveLength(1);
538
+ expect(immediateChildren[0].name).toBe('config.json');
539
+ });
540
+ test('should correctly strip prefix and build file stat', () => {
541
+ var prefix = 'myapp/data';
542
+ var normalizedPrefix = prefix.replace(/^\/+/, '').replace(/\/+$/, '');
543
+ var stripPrefix = (key) => {
544
+ if (!normalizedPrefix || !key.startsWith(normalizedPrefix + '/')) {
545
+ return key.startsWith('/') ? key : '/' + key;
546
+ }
547
+ var withoutPrefix = key.slice(normalizedPrefix.length);
548
+ return withoutPrefix || '/';
549
+ };
550
+ expect(stripPrefix('myapp/data/file.txt')).toBe('/file.txt');
551
+ expect(stripPrefix('myapp/data/subdir/')).toBe('/subdir/');
552
+ expect(stripPrefix('myapp/data/')).toBe('/');
553
+ expect(stripPrefix('other/path')).toBe('/other/path');
554
+ });
584
555
  });