UNPKG

@aws-amplify/storage

Version:

Storage category of aws-amplify

1 lines 15.7 kB
{"version":3,"file":"list.mjs","sources":["../../../../../../src/providers/s3/apis/internal/list.ts"],"sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { StorageAction } from '@aws-amplify/core/internals/utils';\nimport { resolveS3ConfigAndInput, urlDecode, validateBucketOwnerID, validateStorageOperationInputWithPrefix, } from '../../utils';\nimport { listObjectsV2, } from '../../utils/client/s3data';\nimport { getStorageUserAgentValue } from '../../utils/userAgent';\nimport { logger } from '../../../../utils';\nimport { DEFAULT_DELIMITER, STORAGE_INPUT_PREFIX } from '../../utils/constants';\nimport { IntegrityError } from '../../../../errors/IntegrityError';\nconst MAX_PAGE_SIZE = 1000;\nexport const list = async (amplify, input) => {\n const { options = {} } = input;\n const { s3Config, bucket, keyPrefix: generatedPrefix, identityId, } = await resolveS3ConfigAndInput(amplify, input);\n const { inputType, objectKey } = validateStorageOperationInputWithPrefix(input, identityId);\n validateBucketOwnerID(options.expectedBucketOwner);\n const isInputWithPrefix = inputType === STORAGE_INPUT_PREFIX;\n // @ts-expect-error pageSize and nextToken should not coexist with listAll\n if (options?.listAll && (options?.pageSize || options?.nextToken)) {\n const anyOptions = options;\n logger.debug(`listAll is set to true, ignoring ${anyOptions?.pageSize ? `pageSize: ${anyOptions?.pageSize}` : ''} ${anyOptions?.nextToken ? `nextToken: ${anyOptions?.nextToken}` : ''}.`);\n }\n const listParams = {\n Bucket: bucket,\n Prefix: isInputWithPrefix ? `${generatedPrefix}${objectKey}` : objectKey,\n MaxKeys: options?.listAll ? undefined : options?.pageSize,\n ContinuationToken: options?.listAll ? undefined : options?.nextToken,\n Delimiter: getDelimiter(options),\n ExpectedBucketOwner: options?.expectedBucketOwner,\n EncodingType: 'url',\n };\n logger.debug(`listing items from \"${listParams.Prefix}\"`);\n const listInputArgs = {\n s3Config,\n listParams,\n };\n if (options.listAll) {\n if (isInputWithPrefix) {\n return _listAllWithPrefix({\n ...listInputArgs,\n generatedPrefix,\n });\n }\n else {\n return _listAllWithPath(listInputArgs);\n }\n }\n else {\n if (isInputWithPrefix) {\n return _listWithPrefix({ ...listInputArgs, generatedPrefix });\n }\n else {\n return _listWithPath(listInputArgs);\n }\n }\n};\n/** @deprecated Use {@link _listAllWithPath} instead. */\nconst _listAllWithPrefix = async ({ s3Config, listParams, generatedPrefix, }) => {\n const listResult = [];\n let continuationToken = listParams.ContinuationToken;\n do {\n const { items: pageResults, nextToken: pageNextToken } = await _listWithPrefix({\n generatedPrefix,\n s3Config,\n listParams: {\n ...listParams,\n ContinuationToken: continuationToken,\n MaxKeys: MAX_PAGE_SIZE,\n },\n });\n listResult.push(...pageResults);\n continuationToken = pageNextToken;\n } while (continuationToken);\n return {\n items: listResult,\n };\n};\n/** @deprecated Use {@link _listWithPath} instead. */\nconst _listWithPrefix = async ({ s3Config, listParams, generatedPrefix, }) => {\n const listParamsClone = { ...listParams };\n if (!listParamsClone.MaxKeys || listParamsClone.MaxKeys > MAX_PAGE_SIZE) {\n logger.debug(`defaulting pageSize to ${MAX_PAGE_SIZE}.`);\n listParamsClone.MaxKeys = MAX_PAGE_SIZE;\n }\n const response = await listObjectsV2({\n ...s3Config,\n userAgentValue: getStorageUserAgentValue(StorageAction.List),\n }, listParamsClone);\n const listOutput = decodeEncodedElements(response);\n validateEchoedElements(listParamsClone, listOutput);\n if (!listOutput?.Contents) {\n return {\n items: [],\n };\n }\n return {\n items: listOutput.Contents.map(item => ({\n key: generatedPrefix\n ? item.Key.substring(generatedPrefix.length)\n : item.Key,\n eTag: item.ETag,\n lastModified: item.LastModified,\n size: item.Size,\n })),\n nextToken: listOutput.NextContinuationToken,\n };\n};\nconst _listAllWithPath = async ({ s3Config, listParams, }) => {\n const listResult = [];\n const excludedSubpaths = [];\n let continuationToken = listParams.ContinuationToken;\n do {\n const { items: pageResults, excludedSubpaths: pageExcludedSubpaths, nextToken: pageNextToken, } = await _listWithPath({\n s3Config,\n listParams: {\n ...listParams,\n ContinuationToken: continuationToken,\n MaxKeys: MAX_PAGE_SIZE,\n },\n });\n listResult.push(...pageResults);\n excludedSubpaths.push(...(pageExcludedSubpaths ?? []));\n continuationToken = pageNextToken;\n } while (continuationToken);\n return {\n items: listResult,\n excludedSubpaths,\n };\n};\nconst _listWithPath = async ({ s3Config, listParams, }) => {\n const listParamsClone = { ...listParams };\n if (!listParamsClone.MaxKeys || listParamsClone.MaxKeys > MAX_PAGE_SIZE) {\n logger.debug(`defaulting pageSize to ${MAX_PAGE_SIZE}.`);\n listParamsClone.MaxKeys = MAX_PAGE_SIZE;\n }\n const response = await listObjectsV2({\n ...s3Config,\n userAgentValue: getStorageUserAgentValue(StorageAction.List),\n }, listParamsClone);\n const listOutput = decodeEncodedElements(response);\n validateEchoedElements(listParamsClone, listOutput);\n const { Contents: contents, NextContinuationToken: nextContinuationToken, CommonPrefixes: commonPrefixes, } = listOutput;\n const excludedSubpaths = commonPrefixes && mapCommonPrefixesToExcludedSubpaths(commonPrefixes);\n if (!contents) {\n return {\n items: [],\n nextToken: nextContinuationToken,\n excludedSubpaths,\n };\n }\n return {\n items: contents.map(item => ({\n path: item.Key,\n eTag: item.ETag,\n lastModified: item.LastModified,\n size: item.Size,\n })),\n nextToken: nextContinuationToken,\n excludedSubpaths,\n };\n};\nconst mapCommonPrefixesToExcludedSubpaths = (commonPrefixes) => {\n return commonPrefixes.reduce((mappedSubpaths, { Prefix }) => {\n if (Prefix) {\n mappedSubpaths.push(Prefix);\n }\n return mappedSubpaths;\n }, []);\n};\nconst getDelimiter = (options) => {\n if (options?.subpathStrategy?.strategy === 'exclude') {\n return options?.subpathStrategy?.delimiter ?? DEFAULT_DELIMITER;\n }\n};\nconst validateEchoedElements = (listInput, listOutput) => {\n const validEchoedParameters = listInput.Bucket === listOutput.Name &&\n listInput.Delimiter === listOutput.Delimiter &&\n listInput.MaxKeys === listOutput.MaxKeys &&\n listInput.Prefix === listOutput.Prefix &&\n listInput.ContinuationToken === listOutput.ContinuationToken;\n if (!validEchoedParameters) {\n throw new IntegrityError({ metadata: listOutput.$metadata });\n }\n};\n/**\n * Decodes URL-encoded elements in the S3 `ListObjectsV2Output` response when `EncodingType` is `'url'`.\n * Applies to values for 'Delimiter', 'Prefix', 'StartAfter' and 'Key' in the response.\n */\nconst decodeEncodedElements = (listOutput) => {\n if (listOutput.EncodingType !== 'url') {\n return listOutput;\n }\n const decodedListOutput = { ...listOutput };\n // Decode top-level properties\n ['Delimiter', 'Prefix', 'StartAfter'].forEach(prop => {\n const value = listOutput[prop];\n if (typeof value === 'string') {\n decodedListOutput[prop] = urlDecode(value);\n }\n });\n // Decode 'Key' in each item of 'Contents', if it exists\n if (listOutput.Contents) {\n decodedListOutput.Contents = listOutput.Contents.map(content => ({\n ...content,\n Key: content.Key ? urlDecode(content.Key) : content.Key,\n }));\n }\n // Decode 'Prefix' in each item of 'CommonPrefixes', if it exists\n if (listOutput.CommonPrefixes) {\n decodedListOutput.CommonPrefixes = listOutput.CommonPrefixes.map(content => ({\n ...content,\n Prefix: content.Prefix ? urlDecode(content.Prefix) : content.Prefix,\n }));\n }\n return decodedListOutput;\n};\n"],"names":[],"mappings":"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"}