extensions.mjs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * MinIO Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import * as stream from "stream";
  17. import * as errors from "../errors.mjs";
  18. import { isBoolean, isString, isValidBucketName, isValidPrefix, uriEscape } from "./helper.mjs";
  19. import { readAsString } from "./response.mjs";
  20. import { parseListObjectsV2WithMetadata } from "./xml-parser.mjs";
  21. export class Extensions {
  22. constructor(client) {
  23. this.client = client;
  24. }
  25. /**
  26. * List the objects in the bucket using S3 ListObjects V2 With Metadata
  27. *
  28. * @param bucketName - name of the bucket
  29. * @param prefix - the prefix of the objects that should be listed (optional, default `''`)
  30. * @param recursive - `true` indicates recursive style listing and `false` indicates directory style listing delimited by '/'. (optional, default `false`)
  31. * @param startAfter - Specifies the key to start after when listing objects in a bucket. (optional, default `''`)
  32. * @returns stream emitting the objects in the bucket, the object is of the format:
  33. */
  34. listObjectsV2WithMetadata(bucketName, prefix, recursive, startAfter) {
  35. if (prefix === undefined) {
  36. prefix = '';
  37. }
  38. if (recursive === undefined) {
  39. recursive = false;
  40. }
  41. if (startAfter === undefined) {
  42. startAfter = '';
  43. }
  44. if (!isValidBucketName(bucketName)) {
  45. throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
  46. }
  47. if (!isValidPrefix(prefix)) {
  48. throw new errors.InvalidPrefixError(`Invalid prefix : ${prefix}`);
  49. }
  50. if (!isString(prefix)) {
  51. throw new TypeError('prefix should be of type "string"');
  52. }
  53. if (!isBoolean(recursive)) {
  54. throw new TypeError('recursive should be of type "boolean"');
  55. }
  56. if (!isString(startAfter)) {
  57. throw new TypeError('startAfter should be of type "string"');
  58. }
  59. // if recursive is false set delimiter to '/'
  60. const delimiter = recursive ? '' : '/';
  61. return stream.Readable.from(this.listObjectsV2WithMetadataGen(bucketName, prefix, delimiter, startAfter), {
  62. objectMode: true
  63. });
  64. }
  65. async *listObjectsV2WithMetadataGen(bucketName, prefix, delimiter, startAfter) {
  66. let ended = false;
  67. let continuationToken = '';
  68. do {
  69. const result = await this.listObjectsV2WithMetadataQuery(bucketName, prefix, continuationToken, delimiter, startAfter);
  70. ended = !result.isTruncated;
  71. continuationToken = result.nextContinuationToken;
  72. for (const obj of result.objects) {
  73. yield obj;
  74. }
  75. } while (!ended);
  76. }
  77. async listObjectsV2WithMetadataQuery(bucketName, prefix, continuationToken, delimiter, startAfter) {
  78. const queries = [];
  79. // Call for listing objects v2 API
  80. queries.push(`list-type=2`);
  81. queries.push(`encoding-type=url`);
  82. // escape every value in query string, except maxKeys
  83. queries.push(`prefix=${uriEscape(prefix)}`);
  84. queries.push(`delimiter=${uriEscape(delimiter)}`);
  85. queries.push(`metadata=true`);
  86. if (continuationToken) {
  87. continuationToken = uriEscape(continuationToken);
  88. queries.push(`continuation-token=${continuationToken}`);
  89. }
  90. // Set start-after
  91. if (startAfter) {
  92. startAfter = uriEscape(startAfter);
  93. queries.push(`start-after=${startAfter}`);
  94. }
  95. queries.push(`max-keys=1000`);
  96. queries.sort();
  97. let query = '';
  98. if (queries.length > 0) {
  99. query = `${queries.join('&')}`;
  100. }
  101. const method = 'GET';
  102. const res = await this.client.makeRequestAsync({
  103. method,
  104. bucketName,
  105. query
  106. });
  107. return parseListObjectsV2WithMetadata(await readAsString(res));
  108. }
  109. }
  110. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJzdHJlYW0iLCJlcnJvcnMiLCJpc0Jvb2xlYW4iLCJpc1N0cmluZyIsImlzVmFsaWRCdWNrZXROYW1lIiwiaXNWYWxpZFByZWZpeCIsInVyaUVzY2FwZSIsInJlYWRBc1N0cmluZyIsInBhcnNlTGlzdE9iamVjdHNWMldpdGhNZXRhZGF0YSIsIkV4dGVuc2lvbnMiLCJjb25zdHJ1Y3RvciIsImNsaWVudCIsImxpc3RPYmplY3RzVjJXaXRoTWV0YWRhdGEiLCJidWNrZXROYW1lIiwicHJlZml4IiwicmVjdXJzaXZlIiwic3RhcnRBZnRlciIsInVuZGVmaW5lZCIsIkludmFsaWRCdWNrZXROYW1lRXJyb3IiLCJJbnZhbGlkUHJlZml4RXJyb3IiLCJUeXBlRXJyb3IiLCJkZWxpbWl0ZXIiLCJSZWFkYWJsZSIsImZyb20iLCJsaXN0T2JqZWN0c1YyV2l0aE1ldGFkYXRhR2VuIiwib2JqZWN0TW9kZSIsImVuZGVkIiwiY29udGludWF0aW9uVG9rZW4iLCJyZXN1bHQiLCJsaXN0T2JqZWN0c1YyV2l0aE1ldGFkYXRhUXVlcnkiLCJpc1RydW5jYXRlZCIsIm5leHRDb250aW51YXRpb25Ub2tlbiIsIm9iaiIsIm9iamVjdHMiLCJxdWVyaWVzIiwicHVzaCIsInNvcnQiLCJxdWVyeSIsImxlbmd0aCIsImpvaW4iLCJtZXRob2QiLCJyZXMiLCJtYWtlUmVxdWVzdEFzeW5jIl0sInNvdXJjZXMiOlsiZXh0ZW5zaW9ucy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogTWluSU8gSmF2YXNjcmlwdCBMaWJyYXJ5IGZvciBBbWF6b24gUzMgQ29tcGF0aWJsZSBDbG91ZCBTdG9yYWdlLCAoQykgMjAyMCBNaW5JTywgSW5jLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgKiBhcyBzdHJlYW0gZnJvbSAnbm9kZTpzdHJlYW0nXG5cbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tICcuLi9lcnJvcnMudHMnXG5pbXBvcnQgdHlwZSB7IFR5cGVkQ2xpZW50IH0gZnJvbSAnLi9jbGllbnQudHMnXG5pbXBvcnQgeyBpc0Jvb2xlYW4sIGlzU3RyaW5nLCBpc1ZhbGlkQnVja2V0TmFtZSwgaXNWYWxpZFByZWZpeCwgdXJpRXNjYXBlIH0gZnJvbSAnLi9oZWxwZXIudHMnXG5pbXBvcnQgeyByZWFkQXNTdHJpbmcgfSBmcm9tICcuL3Jlc3BvbnNlLnRzJ1xuaW1wb3J0IHR5cGUgeyBCdWNrZXRJdGVtV2l0aE1ldGFkYXRhLCBCdWNrZXRTdHJlYW0gfSBmcm9tICcuL3R5cGUudHMnXG5pbXBvcnQgeyBwYXJzZUxpc3RPYmplY3RzVjJXaXRoTWV0YWRhdGEgfSBmcm9tICcuL3htbC1wYXJzZXIudHMnXG5cbmV4cG9ydCBjbGFzcyBFeHRlbnNpb25zIHtcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFR5cGVkQ2xpZW50XG5cbiAgY29uc3RydWN0b3IoY2xpZW50OiBUeXBlZENsaWVudCkge1xuICAgIHRoaXMuY2xpZW50ID0gY2xpZW50XG4gIH1cblxuICAvKipcbiAgICogTGlzdCB0aGUgb2JqZWN0cyBpbiB0aGUgYnVja2V0IHVzaW5nIFMzIExpc3RPYmplY3RzIFYyIFdpdGggTWV0YWRhdGFcbiAgICpcbiAgICogQHBhcmFtIGJ1Y2tldE5hbWUgLSBuYW1lIG9mIHRoZSBidWNrZXRcbiAgICogQHBhcmFtIHByZWZpeCAtIHRoZSBwcmVmaXggb2YgdGhlIG9iamVjdHMgdGhhdCBzaG91bGQgYmUgbGlzdGVkIChvcHRpb25hbCwgZGVmYXVsdCBgJydgKVxuICAgKiBAcGFyYW0gcmVjdXJzaXZlIC0gYHRydWVgIGluZGljYXRlcyByZWN1cnNpdmUgc3R5bGUgbGlzdGluZyBhbmQgYGZhbHNlYCBpbmRpY2F0ZXMgZGlyZWN0b3J5IHN0eWxlIGxpc3RpbmcgZGVsaW1pdGVkIGJ5ICcvJy4gKG9wdGlvbmFsLCBkZWZhdWx0IGBmYWxzZWApXG4gICAqIEBwYXJhbSBzdGFydEFmdGVyIC0gU3BlY2lmaWVzIHRoZSBrZXkgdG8gc3RhcnQgYWZ0ZXIgd2hlbiBsaXN0aW5nIG9iamVjdHMgaW4gYSBidWNrZXQuIChvcHRpb25hbCwgZGVmYXVsdCBgJydgKVxuICAgKiBAcmV0dXJucyBzdHJlYW0gZW1pdHRpbmcgdGhlIG9iamVjdHMgaW4gdGhlIGJ1Y2tldCwgdGhlIG9iamVjdCBpcyBvZiB0aGUgZm9ybWF0OlxuICAgKi9cbiAgcHVibGljIGxpc3RPYmplY3RzVjJXaXRoTWV0YWRhdGEoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIHByZWZpeD86IHN0cmluZyxcbiAgICByZWN1cnNpdmU/OiBib29sZWFuLFxuICAgIHN0YXJ0QWZ0ZXI/OiBzdHJpbmcsXG4gICk6IEJ1Y2tldFN0cmVhbTxCdWNrZXRJdGVtV2l0aE1ldGFkYXRhPiB7XG4gICAgaWYgKHByZWZpeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcmVmaXggPSAnJ1xuICAgIH1cbiAgICBpZiAocmVjdXJzaXZlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlY3Vyc2l2ZSA9IGZhbHNlXG4gICAgfVxuICAgIGlmIChzdGFydEFmdGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHN0YXJ0QWZ0ZXIgPSAnJ1xuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRQcmVmaXgocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUHJlZml4RXJyb3IoYEludmFsaWQgcHJlZml4IDogJHtwcmVmaXh9YClcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwcmVmaXggc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNCb29sZWFuKHJlY3Vyc2l2ZSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlY3Vyc2l2ZSBzaG91bGQgYmUgb2YgdHlwZSBcImJvb2xlYW5cIicpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcoc3RhcnRBZnRlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3N0YXJ0QWZ0ZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuXG4gICAgLy8gaWYgcmVjdXJzaXZlIGlzIGZhbHNlIHNldCBkZWxpbWl0ZXIgdG8gJy8nXG4gICAgY29uc3QgZGVsaW1pdGVyID0gcmVjdXJzaXZlID8gJycgOiAnLydcbiAgICByZXR1cm4gc3RyZWFtLlJlYWRhYmxlLmZyb20odGhpcy5saXN0T2JqZWN0c1YyV2l0aE1ldGFkYXRhR2VuKGJ1Y2tldE5hbWUsIHByZWZpeCwgZGVsaW1pdGVyLCBzdGFydEFmdGVyKSwge1xuICAgICAgb2JqZWN0TW9kZTogdHJ1ZSxcbiAgICB9KVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyAqbGlzdE9iamVjdHNWMldpdGhNZXRhZGF0YUdlbihcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgcHJlZml4OiBzdHJpbmcsXG4gICAgZGVsaW1pdGVyOiBzdHJpbmcsXG4gICAgc3RhcnRBZnRlcjogc3RyaW5nLFxuICApOiBBc3luY0l0ZXJhYmxlPEJ1Y2tldEl0ZW1XaXRoTWV0YWRhdGE+IHtcbiAgICBsZXQgZW5kZWQgPSBmYWxzZVxuICAgIGxldCBjb250aW51YXRpb25Ub2tlbiA9ICcnXG4gICAgZG8ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5saXN0T2JqZWN0c1YyV2l0aE1ldGFkYXRhUXVlcnkoXG4gICAgICAgIGJ1Y2tldE5hbWUsXG4gICAgICAgIHByZWZpeCxcbiAgICAgICAgY29udGludWF0aW9uVG9rZW4sXG4gICAgICAgIGRlbGltaXRlcixcbiAgICAgICAgc3RhcnRBZnRlcixcbiAgICAgIClcbiAgICAgIGVuZGVkID0gIXJlc3VsdC5pc1RydW5jYXRlZFxuICAgICAgY29udGludWF0aW9uVG9rZW4gPSByZXN1bHQubmV4dENvbnRpbnVhdGlvblRva2VuXG4gICAgICBmb3IgKGNvbnN0IG9iaiBvZiByZXN1bHQub2JqZWN0cykge1xuICAgICAgICB5aWVsZCBvYmpcbiAgICAgIH1cbiAgICB9IHdoaWxlICghZW5kZWQpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxpc3RPYmplY3RzVjJXaXRoTWV0YWRhdGFRdWVyeShcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgcHJlZml4OiBzdHJpbmcsXG4gICAgY29udGludWF0aW9uVG9rZW46IHN0cmluZyxcbiAgICBkZWxpbWl0ZXI6IHN0cmluZyxcbiAgICBzdGFydEFmdGVyOiBzdHJpbmcsXG4gICkge1xuICAgIGNvbnN0IHF1ZXJpZXMgPSBbXVxuXG4gICAgLy8gQ2FsbCBmb3IgbGlzdGluZyBvYmplY3RzIHYyIEFQSVxuICAgIHF1ZXJpZXMucHVzaChgbGlzdC10eXBlPTJgKVxuICAgIHF1ZXJpZXMucHVzaChgZW5jb2RpbmctdHlwZT11cmxgKVxuICAgIC8vIGVzY2FwZSBldmVyeSB2YWx1ZSBpbiBxdWVyeSBzdHJpbmcsIGV4Y2VwdCBtYXhLZXlzXG4gICAgcXVlcmllcy5wdXNoKGBwcmVmaXg9JHt1cmlFc2NhcGUocHJlZml4KX1gKVxuICAgIHF1ZXJpZXMucHVzaChgZGVsaW1pdGVyPSR7dXJpRXNjYXBlKGRlbGltaXRlcil9YClcbiAgICBxdWVyaWVzLnB1c2goYG1ldGFkYXRhPXRydWVgKVxuXG4gICAgaWYgKGNvbnRpbnVhdGlvblRva2VuKSB7XG4gICAgICBjb250aW51YXRpb25Ub2tlbiA9IHVyaUVzY2FwZShjb250aW51YXRpb25Ub2tlbilcbiAgICAgIHF1ZXJpZXMucHVzaChgY29udGludWF0aW9uLXRva2VuPSR7Y29udGludWF0aW9uVG9rZW59YClcbiAgICB9XG4gICAgLy8gU2V0IHN0YXJ0LWFmdGVyXG4gICAgaWYgKHN0YXJ0QWZ0ZXIpIHtcbiAgICAgIHN0YXJ0QWZ0ZXIgPSB1cmlFc2NhcGUoc3RhcnRBZnRlcilcbiAgICAgIHF1ZXJpZXMucHVzaChgc3RhcnQtYWZ0ZXI9JHtzdGFydEFmdGVyfWApXG4gICAgfVxuICAgIHF1ZXJpZXMucHVzaChgbWF4LWtleXM9MTAwMGApXG4gICAgcXVlcmllcy5zb3J0KClcbiAgICBsZXQgcXVlcnkgPSAnJ1xuICAgIGlmIChxdWVyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHF1ZXJ5ID0gYCR7cXVlcmllcy5qb2luKCcmJyl9YFxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMuY2xpZW50Lm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH0pXG4gICAgcmV0dXJuIHBhcnNlTGlzdE9iamVjdHNWMldpdGhNZXRhZGF0YShhd2FpdCByZWFkQXNTdHJpbmcocmVzKSlcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTyxLQUFLQSxNQUFNO0FBRWxCLE9BQU8sS0FBS0MsTUFBTSxNQUFNLGVBQWM7QUFFdEMsU0FBU0MsU0FBUyxFQUFFQyxRQUFRLEVBQUVDLGlCQUFpQixFQUFFQyxhQUFhLEVBQUVDLFNBQVMsUUFBUSxjQUFhO0FBQzlGLFNBQVNDLFlBQVksUUFBUSxnQkFBZTtBQUU1QyxTQUFTQyw4QkFBOEIsUUFBUSxrQkFBaUI7QUFFaEUsT0FBTyxNQUFNQyxVQUFVLENBQUM7RUFHdEJDLFdBQVdBLENBQUNDLE1BQW1CLEVBQUU7SUFDL0IsSUFBSSxDQUFDQSxNQUFNLEdBQUdBLE1BQU07RUFDdEI7O0VBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ1NDLHlCQUF5QkEsQ0FDOUJDLFVBQWtCLEVBQ2xCQyxNQUFlLEVBQ2ZDLFNBQW1CLEVBQ25CQyxVQUFtQixFQUNtQjtJQUN0QyxJQUFJRixNQUFNLEtBQUtHLFNBQVMsRUFBRTtNQUN4QkgsTUFBTSxHQUFHLEVBQUU7SUFDYjtJQUNBLElBQUlDLFNBQVMsS0FBS0UsU0FBUyxFQUFFO01BQzNCRixTQUFTLEdBQUcsS0FBSztJQUNuQjtJQUNBLElBQUlDLFVBQVUsS0FBS0MsU0FBUyxFQUFFO01BQzVCRCxVQUFVLEdBQUcsRUFBRTtJQUNqQjtJQUNBLElBQUksQ0FBQ1osaUJBQWlCLENBQUNTLFVBQVUsQ0FBQyxFQUFFO01BQ2xDLE1BQU0sSUFBSVosTUFBTSxDQUFDaUIsc0JBQXNCLENBQUMsdUJBQXVCLEdBQUdMLFVBQVUsQ0FBQztJQUMvRTtJQUNBLElBQUksQ0FBQ1IsYUFBYSxDQUFDUyxNQUFNLENBQUMsRUFBRTtN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