@did-space/s3-driver 0.2.151 → 0.2.153

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.
@@ -57,8 +57,17 @@ export declare class S3SpaceOperator implements SpaceOperatorProtocol {
57
57
  * @memberof S3SpaceOperator
58
58
  */
59
59
  private listsOneLevel;
60
+ /**
61
+ * @description 列出当前文件夹下的所有文件夹和文件
62
+ * @private
63
+ * @param {string} prefix
64
+ * @return {*} {Promise<Object[]>}
65
+ * @memberof S3SpaceOperator
66
+ */
67
+ listsRecursiveAsOwner(prefix: string): Promise<Object[]>;
60
68
  /**
61
69
  *
70
+ * @FIXME: 还不够通用, options.key 还需要拼凑出来,这不好
62
71
  * @see 使用paginateListObjectsV2快速检索所有对象 https://stackoverflow.com/a/34912646
63
72
  * @see s3开发者指南 https://docs.aws.amazon.com/zh_cn/sdk-for-javascript/v3/developer-guide/javascript_s3_code_examples.html
64
73
  * @param {ListOptions} options
@@ -27,6 +27,7 @@ const lib_storage_1 = require("@aws-sdk/lib-storage");
27
27
  const mime_types_1 = __importDefault(require("mime-types"));
28
28
  const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
29
29
  const debug_1 = __importDefault(require("debug"));
30
+ const p_all_1 = __importDefault(require("p-all"));
30
31
  const { version: s3ClientVersion } = require('@aws-sdk/client-s3/package.json');
31
32
  const { version: libStorageVersion } = require('@aws-sdk/lib-storage/package.json');
32
33
  const debug = (0, debug_1.default)('@did-space/s3-driver:S3SpaceOperator');
@@ -110,19 +111,24 @@ class S3SpaceOperator {
110
111
  return __awaiter(this, void 0, void 0, function* () {
111
112
  yield this.s3Client.send(new client_s3_1.PutObjectCommand({
112
113
  Bucket: this.options.bucket,
113
- Key: `${yield this.getAppSpacePath(options)}/`,
114
+ Key: yield this.getAppSpacePath(options),
114
115
  }));
115
116
  });
116
117
  }
117
118
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
118
119
  destroyAppSpace(options) {
119
- // @see: https://stackoverflow.com/questions/20207063/how-can-i-delete-folder-on-s3-with-node-js
120
- // FIXME: @yejianchao 目前只能删除空文件夹
121
- throw new Error('Method not implemented.');
120
+ return __awaiter(this, void 0, void 0, function* () {
121
+ // @see: https://stackoverflow.com/questions/20207063/how-can-i-delete-folder-on-s3-with-node-js
122
+ // FIXME: @yejianchao 目前只能删除空文件夹
123
+ const folderKey = yield this.getAppSpacePath(options);
124
+ debug('destroyAppSpace.before', `options=${JSON.stringify(options)} folderKey=${folderKey}`);
125
+ yield this.deleteAsOwner(folderKey);
126
+ debug('destroyAppSpace.after', `options=${JSON.stringify(options)} folderKey=${folderKey}`);
127
+ });
122
128
  }
123
129
  getAppSpacePath(options) {
124
130
  // @ts-expect-error
125
- return (0, path_1.join)(this.options.root, S3SpaceOperator.APPS, options.appDid);
131
+ return (0, path_1.join)(this.options.root, S3SpaceOperator.APPS, options.appDid, '/');
126
132
  }
127
133
  getObjectKey(options) {
128
134
  return __awaiter(this, void 0, void 0, function* () {
@@ -325,8 +331,66 @@ class S3SpaceOperator {
325
331
  return objects;
326
332
  });
327
333
  }
334
+ /**
335
+ * @description 列出当前文件夹下的所有文件夹和文件
336
+ * @private
337
+ * @param {string} prefix
338
+ * @return {*} {Promise<Object[]>}
339
+ * @memberof S3SpaceOperator
340
+ */
341
+ listsRecursiveAsOwner(prefix) {
342
+ var _a, e_3, _b, _c;
343
+ var _d;
344
+ return __awaiter(this, void 0, void 0, function* () {
345
+ debug('_listsRecursiveAsOwner.before', `Prefix=${prefix}`);
346
+ const objects = [];
347
+ try {
348
+ for (var _e = true, _f = __asyncValues((0, client_s3_1.paginateListObjectsV2)({ client: this.s3Client }, {
349
+ Bucket: this.options.bucket,
350
+ // @note: 如果 key 以 / 结尾,则返回结果是文件夹 和 文件,如果 key 不以 / 结尾则会返回文件, 这个存疑 @jianchao
351
+ Prefix: prefix,
352
+ })), _g; _g = yield _f.next(), _a = _g.done, !_a;) {
353
+ _c = _g.value;
354
+ _e = false;
355
+ try {
356
+ const response = _c;
357
+ const contents = (_d = response === null || response === void 0 ? void 0 : response.Contents) !== null && _d !== void 0 ? _d : [];
358
+ contents.forEach((content) => {
359
+ const key = content.Key;
360
+ const name = (0, path_1.basename)(key);
361
+ if ((0, isEmpty_1.default)(name)) {
362
+ return;
363
+ }
364
+ objects.push({
365
+ key,
366
+ name,
367
+ isDir: name.endsWith('/'),
368
+ size: content.Size,
369
+ lastModified: new Date(content.LastModified).getTime(),
370
+ editable: core_1.Space.editable(key),
371
+ mimeType: mime_types_1.default.lookup(name) || 'unknown',
372
+ });
373
+ });
374
+ }
375
+ finally {
376
+ _e = true;
377
+ }
378
+ }
379
+ }
380
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
381
+ finally {
382
+ try {
383
+ if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
384
+ }
385
+ finally { if (e_3) throw e_3.error; }
386
+ }
387
+ debug('_listsRecursiveAsOwner.after', `Prefix=${prefix}`);
388
+ return objects;
389
+ });
390
+ }
328
391
  /**
329
392
  *
393
+ * @FIXME: 还不够通用, options.key 还需要拼凑出来,这不好
330
394
  * @see 使用paginateListObjectsV2快速检索所有对象 https://stackoverflow.com/a/34912646
331
395
  * @see s3开发者指南 https://docs.aws.amazon.com/zh_cn/sdk-for-javascript/v3/developer-guide/javascript_s3_code_examples.html
332
396
  * @param {ListOptions} options
@@ -334,10 +398,9 @@ class S3SpaceOperator {
334
398
  * @memberof S3SpaceOperator
335
399
  */
336
400
  lists(options) {
337
- var _a, e_3, _b, _c;
338
- var _d;
339
401
  return __awaiter(this, void 0, void 0, function* () {
340
402
  const prefix = (0, path_1.join)(this.options.root, options.key);
403
+ debug('lists.before', `Prefix=${prefix}`);
341
404
  if (!(yield this.existsAsOwner(options.key))) {
342
405
  return [];
343
406
  }
@@ -346,48 +409,14 @@ class S3SpaceOperator {
346
409
  return this.listsOneLevel(options);
347
410
  }
348
411
  if (options.recursive && options.ignoreDirectories) {
349
- const objects = [];
350
- try {
351
- for (var _e = true, _f = __asyncValues((0, client_s3_1.paginateListObjectsV2)({ client: this.s3Client }, {
352
- Bucket: this.options.bucket,
353
- Prefix: prefix,
354
- })), _g; _g = yield _f.next(), _a = _g.done, !_a;) {
355
- _c = _g.value;
356
- _e = false;
357
- try {
358
- const response = _c;
359
- const contents = (_d = response === null || response === void 0 ? void 0 : response.Contents) !== null && _d !== void 0 ? _d : [];
360
- contents.forEach((content) => {
361
- const key = content.Key.replace(prefix, '/');
362
- const name = (0, path_1.basename)(key);
363
- if ((0, isEmpty_1.default)(name)) {
364
- return;
365
- }
366
- objects.push({
367
- key,
368
- name,
369
- isDir: name.endsWith('/'),
370
- size: content.Size,
371
- lastModified: new Date(content.LastModified).getTime(),
372
- editable: core_1.Space.editable(key),
373
- mimeType: mime_types_1.default.lookup(name) || 'unknown',
374
- });
375
- });
376
- }
377
- finally {
378
- _e = true;
379
- }
380
- }
381
- }
382
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
383
- finally {
384
- try {
385
- if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
386
- }
387
- finally { if (e_3) throw e_3.error; }
388
- }
389
- return objects;
412
+ const objects = yield this.listsRecursiveAsOwner(prefix);
413
+ return objects.map((x) => {
414
+ // @FIXME: / 开头没问题,但是备份/还原的时候不统一
415
+ const $key = x.key.replace(new RegExp(`^${prefix}`), '/');
416
+ return Object.assign(Object.assign({}, x), { key: $key, editable: core_1.Space.editable($key) });
417
+ });
390
418
  }
419
+ debug('lists.after', `Prefix=${prefix}`);
391
420
  throw new Error(`Filter methods not yet supported:\n ${JSON.stringify(options, null, 2)}`);
392
421
  });
393
422
  }
@@ -433,10 +462,35 @@ class S3SpaceOperator {
433
462
  */
434
463
  deleteAsOwner(key) {
435
464
  return __awaiter(this, void 0, void 0, function* () {
436
- yield this.s3Client.send(new client_s3_1.DeleteObjectCommand({
437
- Bucket: this.options.bucket,
438
- Key: (0, path_1.join)(this.options.root, key),
439
- }));
465
+ debug('deleteAsOwner.before', `Bucket=${this.options.bucket} Key=${key}`);
466
+ if (key.endsWith('/')) {
467
+ const objects = yield this.listsRecursiveAsOwner(key);
468
+ const actions = objects.map((x) => {
469
+ return () => __awaiter(this, void 0, void 0, function* () {
470
+ yield this.s3Client.send(new client_s3_1.DeleteObjectCommand({
471
+ Bucket: this.options.bucket,
472
+ // @note: 注意 key 不能以 / 开头
473
+ Key: x.key,
474
+ }));
475
+ });
476
+ });
477
+ // 注意要删除这个空文件夹
478
+ actions.push(() => __awaiter(this, void 0, void 0, function* () {
479
+ yield this.s3Client.send(new client_s3_1.DeleteObjectCommand({
480
+ Bucket: this.options.bucket,
481
+ // @note: 注意 key 不能以 / 开头
482
+ Key: key,
483
+ }));
484
+ }));
485
+ yield (0, p_all_1.default)(actions, { concurrency: process.env.DRIVER_CONCURRENCY ? +process.env.DRIVER_CONCURRENCY : 32 });
486
+ }
487
+ else {
488
+ yield this.s3Client.send(new client_s3_1.DeleteObjectCommand({
489
+ Bucket: this.options.bucket,
490
+ Key: (0, path_1.join)(this.options.root, key),
491
+ }));
492
+ }
493
+ debug('deleteAsOwner.after', `Key=${key}`);
440
494
  });
441
495
  }
442
496
  readAsOwner(key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@did-space/s3-driver",
3
- "version": "0.2.151",
3
+ "version": "0.2.153",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,11 +34,12 @@
34
34
  "dependencies": {
35
35
  "@aws-sdk/client-s3": "3.370.0",
36
36
  "@aws-sdk/lib-storage": "3.370.0",
37
- "@did-space/core": "0.2.151",
37
+ "@did-space/core": "0.2.153",
38
38
  "debug": "^4.3.4",
39
39
  "js-yaml": "^4.1.0",
40
40
  "lodash": "^4.17.21",
41
- "mime-types": "^2.1.35"
41
+ "mime-types": "^2.1.35",
42
+ "p-all": "3.0.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@arcblock/eslint-config-ts": "^0.2.4",
@@ -56,5 +57,5 @@
56
57
  "ts-jest": "^28.0.6",
57
58
  "typescript": "^4.9.5"
58
59
  },
59
- "gitHead": "601fb081de61b2b9a8f3c741976f57f954be4ec5"
60
+ "gitHead": "81aef1bf0c58eaad18820e73707e3f4729340b8c"
60
61
  }