@strapi/provider-upload-aws-s3 5.37.1 → 5.38.1

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { ReadStream } from 'node:fs';\nimport { getOr } from 'lodash/fp';\nimport {\n S3Client,\n GetObjectCommand,\n DeleteObjectCommand,\n DeleteObjectCommandOutput,\n HeadObjectCommand,\n PutObjectCommandInput,\n CompleteMultipartUploadCommandOutput,\n AbortMultipartUploadCommandOutput,\n S3ClientConfig,\n ObjectCannedACL,\n ChecksumAlgorithm,\n StorageClass,\n ServerSideEncryption,\n} from '@aws-sdk/client-s3';\nimport type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport { Upload } from '@aws-sdk/lib-storage';\nimport { extractCredentials, isUrlFromBucket } from './utils';\n\n/**\n * Supported checksum algorithms for data integrity validation.\n * CRC64NVME is recommended for best performance on modern hardware.\n */\nexport type SupportedChecksumAlgorithm = 'CRC32' | 'CRC32C' | 'SHA1' | 'SHA256' | 'CRC64NVME';\n\n/**\n * Supported S3 storage classes for cost optimization.\n */\nexport type SupportedStorageClass =\n | 'STANDARD'\n | 'REDUCED_REDUNDANCY'\n | 'STANDARD_IA'\n | 'ONEZONE_IA'\n | 'INTELLIGENT_TIERING'\n | 'GLACIER'\n | 'DEEP_ARCHIVE'\n | 'GLACIER_IR';\n\n/**\n * Server-side encryption types.\n */\nexport type EncryptionType = 'AES256' | 'aws:kms' | 'aws:kms:dsse';\n\n/**\n * Encryption configuration for server-side encryption.\n */\nexport interface EncryptionConfig {\n type: EncryptionType;\n kmsKeyId?: string;\n}\n\n/**\n * Multipart upload configuration for large files.\n */\nexport interface MultipartConfig {\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n}\n\nexport interface File {\n name: string;\n alternativeText?: string;\n caption?: string;\n width?: number;\n height?: number;\n formats?: Record<string, unknown>;\n hash: string;\n ext?: string;\n mime: string;\n size: number;\n sizeInBytes: number;\n url: string;\n previewUrl?: string;\n path?: string;\n provider?: string;\n provider_metadata?: Record<string, unknown>;\n stream?: ReadStream;\n buffer?: Buffer;\n etag?: string;\n}\n\nexport type UploadCommandOutput = (\n | CompleteMultipartUploadCommandOutput\n | AbortMultipartUploadCommandOutput\n) & {\n Location: string;\n ETag?: string;\n};\n\nexport interface AWSParams {\n Bucket: string;\n ACL?: ObjectCannedACL;\n signedUrlExpires?: number;\n}\n\n/**\n * Extended configuration options for the S3 provider.\n */\nexport interface ProviderConfig {\n /**\n * Checksum algorithm for data integrity validation during upload.\n * When enabled, the SDK calculates a checksum and S3 validates it server-side.\n */\n checksumAlgorithm?: SupportedChecksumAlgorithm;\n\n /**\n * When true, uploads will fail if an object with the same key already exists.\n * This prevents accidental overwrites due to race conditions.\n */\n preventOverwrite?: boolean;\n\n /**\n * S3 storage class for uploaded objects.\n * Use lower-cost classes for infrequently accessed data.\n */\n storageClass?: SupportedStorageClass;\n\n /**\n * Server-side encryption configuration.\n */\n encryption?: EncryptionConfig;\n\n /**\n * Tags to apply to uploaded objects.\n * Useful for cost allocation and lifecycle policies.\n */\n tags?: Record<string, string>;\n\n /**\n * Multipart upload configuration for large files.\n */\n multipart?: MultipartConfig;\n}\n\nexport interface DefaultOptions extends S3ClientConfig {\n // TODO Remove this in V5\n accessKeyId?: AwsCredentialIdentity['accessKeyId'];\n secretAccessKey?: AwsCredentialIdentity['secretAccessKey'];\n // Keep this for V5\n credentials?: AwsCredentialIdentity;\n params?: AWSParams;\n [k: string]: unknown;\n}\n\nexport type InitOptions = (DefaultOptions | { s3Options: DefaultOptions }) & {\n baseUrl?: string;\n rootPath?: string;\n providerConfig?: ProviderConfig;\n [k: string]: unknown;\n};\n\n/**\n * Validates that a URL uses HTTP or HTTPS protocol.\n * Rejects dangerous protocols like file://, javascript:, data:, etc.\n */\nconst assertUrlProtocol = (url: string) => {\n return /^https?:\\/\\//.test(url);\n};\n\n/**\n * Sanitizes a path component to prevent path traversal attacks.\n * Removes directory traversal sequences and normalizes the path.\n */\nconst sanitizePathComponent = (component: string | undefined): string => {\n if (!component) return '';\n return component\n .replace(/\\.\\./g, '')\n .replace(/^\\/+|\\/+$/g, '')\n .replace(/\\/+/g, '/');\n};\n\n/**\n * Maps the provider checksum algorithm to the AWS SDK checksum algorithm.\n */\nconst mapChecksumAlgorithm = (\n algorithm?: SupportedChecksumAlgorithm\n): ChecksumAlgorithm | undefined => {\n if (!algorithm) return undefined;\n const mapping: Record<SupportedChecksumAlgorithm, ChecksumAlgorithm> = {\n CRC32: ChecksumAlgorithm.CRC32,\n CRC32C: ChecksumAlgorithm.CRC32C,\n SHA1: ChecksumAlgorithm.SHA1,\n SHA256: ChecksumAlgorithm.SHA256,\n CRC64NVME: ChecksumAlgorithm.CRC64NVME,\n };\n return mapping[algorithm];\n};\n\n/**\n * Maps the provider storage class to the AWS SDK storage class.\n */\nconst mapStorageClass = (storageClass?: SupportedStorageClass): StorageClass | undefined => {\n if (!storageClass) return undefined;\n const mapping: Record<SupportedStorageClass, StorageClass> = {\n STANDARD: StorageClass.STANDARD,\n REDUCED_REDUNDANCY: StorageClass.REDUCED_REDUNDANCY,\n STANDARD_IA: StorageClass.STANDARD_IA,\n ONEZONE_IA: StorageClass.ONEZONE_IA,\n INTELLIGENT_TIERING: StorageClass.INTELLIGENT_TIERING,\n GLACIER: StorageClass.GLACIER,\n DEEP_ARCHIVE: StorageClass.DEEP_ARCHIVE,\n GLACIER_IR: StorageClass.GLACIER_IR,\n };\n return mapping[storageClass];\n};\n\n/**\n * Maps the provider encryption type to the AWS SDK server-side encryption.\n */\nconst mapServerSideEncryption = (type?: EncryptionType): ServerSideEncryption | undefined => {\n if (!type) return undefined;\n const mapping: Record<EncryptionType, ServerSideEncryption> = {\n AES256: ServerSideEncryption.AES256,\n 'aws:kms': ServerSideEncryption.aws_kms,\n 'aws:kms:dsse': ServerSideEncryption.aws_kms_dsse,\n };\n return mapping[type];\n};\n\n/**\n * Converts a tags object to the S3 Tagging header format.\n * Format: key1=value1&key2=value2\n */\nconst formatTagsForHeader = (tags?: Record<string, string>): string | undefined => {\n if (!tags || Object.keys(tags).length === 0) return undefined;\n return Object.entries(tags)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&');\n};\n\n/**\n * Checks if the endpoint appears to be a non-AWS S3-compatible provider.\n */\nconst isNonAwsEndpoint = (endpoint?: string): boolean => {\n if (!endpoint) return false;\n const awsPatterns = [/\\.amazonaws\\.com$/i, /\\.amazonaws\\.com\\.cn$/i];\n return !awsPatterns.some((pattern) => pattern.test(endpoint));\n};\n\n/**\n * Validates provider configuration and emits warnings for potential compatibility issues.\n */\nconst validateProviderConfig = (\n providerConfig: ProviderConfig | undefined,\n s3Options: DefaultOptions | undefined\n): void => {\n if (!providerConfig) return;\n\n const endpoint = s3Options?.endpoint?.toString() || '';\n const isNonAws = isNonAwsEndpoint(endpoint);\n\n // Warn about AWS-specific features when using non-AWS endpoints\n if (isNonAws) {\n if (providerConfig.storageClass) {\n process.emitWarning(\n `Storage class '${providerConfig.storageClass}' is AWS S3-specific and may be ignored by your S3-compatible provider.`\n );\n }\n\n if (providerConfig.encryption?.type && providerConfig.encryption.type !== 'AES256') {\n process.emitWarning(\n `Encryption type '${providerConfig.encryption.type}' is AWS S3-specific. Consider using 'AES256' for better compatibility.`\n );\n }\n }\n\n // Validate multipart configuration\n if (providerConfig.multipart?.partSize) {\n const minPartSize = 5 * 1024 * 1024; // 5MB\n const maxPartSize = 5 * 1024 * 1024 * 1024; // 5GB\n\n if (providerConfig.multipart.partSize < minPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} is below the minimum of 5MB. This may cause upload failures.`\n );\n }\n\n if (providerConfig.multipart.partSize > maxPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} exceeds the maximum of 5GB. This may cause upload failures.`\n );\n }\n }\n\n if (providerConfig.multipart?.queueSize && providerConfig.multipart.queueSize > 16) {\n process.emitWarning(\n `Multipart queueSize ${providerConfig.multipart.queueSize} is high and may cause memory issues. Consider using 4-8.`\n );\n }\n};\n\nconst getConfig = ({\n s3Options,\n legacyS3Options,\n}: {\n s3Options: DefaultOptions;\n legacyS3Options: Record<string, unknown>;\n}) => {\n if (Object.keys(legacyS3Options).length > 0) {\n process.emitWarning(\n \"S3 configuration options passed at root level of the plugin's providerOptions is deprecated and will be removed in a future release. Please wrap them inside the 's3Options:{}' property.\"\n );\n }\n const credentials = extractCredentials({ s3Options, ...legacyS3Options });\n const config = {\n ...s3Options,\n ...legacyS3Options,\n ...(credentials ? { credentials } : {}),\n };\n\n if (config.params !== undefined) {\n // Only set default ACL when ACL is not explicitly present in params.\n // Since April 2023, new AWS S3 buckets have ACLs disabled by default\n // (\"Bucket owner enforced\"). Sending an ACL header to such buckets\n // throws AccessControlListNotSupported. To disable ACLs, users should\n // simply not include ACL in their params configuration.\n if (!('ACL' in config.params)) {\n config.params.ACL = ObjectCannedACL.public_read;\n }\n } else {\n throw new Error('Upload AWS S3 provider: `params` are required in the config object');\n }\n\n return config as DefaultOptions & {\n params: AWSParams;\n };\n};\n\nexport default {\n init({ baseUrl, rootPath, s3Options, providerConfig, ...legacyS3Options }: InitOptions) {\n // Validate configuration and emit warnings for potential issues\n validateProviderConfig(providerConfig, s3Options as DefaultOptions);\n\n // TODO V5 change config structure to avoid having to do this\n const config = getConfig({ s3Options: s3Options as DefaultOptions, legacyS3Options });\n const s3Client = new S3Client(config);\n const filePrefix = rootPath ? `${rootPath.replace(/\\/+$/, '')}/` : '';\n\n const getFileKey = (file: File) => {\n const sanitizedPath = sanitizePathComponent(file.path);\n const path = sanitizedPath ? `${sanitizedPath}/` : '';\n const sanitizedHash = sanitizePathComponent(file.hash);\n const sanitizedExt = file.ext ? file.ext.replace(/[^a-zA-Z0-9.]/g, '') : '';\n return `${filePrefix}${path}${sanitizedHash}${sanitizedExt}`;\n };\n\n /**\n * Builds the upload parameters including all configured features.\n */\n const buildUploadParams = (\n file: File,\n fileKey: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ): PutObjectCommandInput => {\n const params: PutObjectCommandInput = {\n Bucket: config.params.Bucket,\n Key: fileKey,\n Body: file.stream || Buffer.from(file.buffer as any, 'binary'),\n // ACL is optional to support providers like Cloudflare R2 that don't support ACLs.\n // Set params.ACL to undefined or omit it entirely to disable ACL headers.\n ...(config.params.ACL ? { ACL: config.params.ACL } : {}),\n ContentType: file.mime,\n };\n\n // Checksum validation\n const checksumAlgorithm = mapChecksumAlgorithm(providerConfig?.checksumAlgorithm);\n if (checksumAlgorithm) {\n params.ChecksumAlgorithm = checksumAlgorithm;\n }\n\n // Conditional writes - prevent overwrite\n if (providerConfig?.preventOverwrite) {\n params.IfNoneMatch = '*';\n }\n\n // Storage class\n const storageClass = mapStorageClass(providerConfig?.storageClass);\n if (storageClass) {\n params.StorageClass = storageClass;\n }\n\n // Server-side encryption\n if (providerConfig?.encryption) {\n const sse = mapServerSideEncryption(providerConfig.encryption.type);\n if (sse) {\n params.ServerSideEncryption = sse;\n if (providerConfig.encryption.kmsKeyId) {\n params.SSEKMSKeyId = providerConfig.encryption.kmsKeyId;\n }\n }\n }\n\n // Object tagging\n const tagging = formatTagsForHeader(providerConfig?.tags);\n if (tagging) {\n params.Tagging = tagging;\n }\n\n // Merge customParams but preserve critical security parameters\n // Bucket, Key, and Body must not be overridden by customParams\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, Body, ...safeCustomParams } = customParams as any;\n return { ...params, ...safeCustomParams };\n };\n\n /**\n * Constructs the correct file URL.\n * Handles S3-compatible providers that return incorrect Location formats.\n */\n const constructFileUrl = (fileKey: string, uploadLocation: string): string => {\n // Priority 1: Use baseUrl if configured (CDN or custom domain)\n if (baseUrl) {\n const cleanBase = baseUrl.replace(/\\/+$/, '');\n return `${cleanBase}/${fileKey}`;\n }\n\n // Priority 2: Construct URL from endpoint if configured\n // This fixes issues with S3-compatible providers (IONOS, MinIO, etc.)\n // that return Location in incorrect format for multipart uploads\n const endpoint = config.endpoint?.toString();\n if (endpoint) {\n const endpointUrl = endpoint.startsWith('http') ? endpoint : `https://${endpoint}`;\n const cleanEndpoint = endpointUrl.replace(/\\/+$/, '');\n return `${cleanEndpoint}/${config.params.Bucket}/${fileKey}`;\n }\n\n // Priority 3: Use the Location from S3 response\n if (assertUrlProtocol(uploadLocation)) {\n return uploadLocation;\n }\n\n // Priority 4: Prepend https if protocol is missing\n return `https://${uploadLocation}`;\n };\n\n const upload = async (file: File, customParams: Partial<PutObjectCommandInput> = {}) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, customParams);\n\n const uploadOptions: {\n client: S3Client;\n params: PutObjectCommandInput;\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n } = {\n client: s3Client,\n params,\n };\n\n // Multipart configuration\n if (providerConfig?.multipart) {\n if (providerConfig.multipart.partSize) {\n uploadOptions.partSize = providerConfig.multipart.partSize;\n }\n if (providerConfig.multipart.queueSize) {\n uploadOptions.queueSize = providerConfig.multipart.queueSize;\n }\n if (providerConfig.multipart.leavePartsOnError !== undefined) {\n uploadOptions.leavePartsOnError = providerConfig.multipart.leavePartsOnError;\n }\n }\n\n const uploadObj = new Upload(uploadOptions);\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n // Store ETag for potential future conditional updates\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Uploads a file only if the existing object matches the expected ETag.\n * This implements optimistic locking to prevent lost updates.\n */\n const uploadIfMatch = async (\n file: File,\n expectedETag: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, {\n ...customParams,\n IfMatch: expectedETag,\n });\n\n const uploadObj = new Upload({\n client: s3Client,\n params,\n });\n\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Retrieves metadata for an object including its ETag.\n */\n const getObjectMetadata = async (file: File) => {\n const command = new HeadObjectCommand({\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n\n const response = await s3Client.send(command);\n\n return {\n etag: response.ETag?.replace(/\"/g, ''),\n contentLength: response.ContentLength,\n contentType: response.ContentType,\n lastModified: response.LastModified,\n storageClass: response.StorageClass,\n serverSideEncryption: response.ServerSideEncryption,\n };\n };\n\n /**\n * Checks if an object exists in the bucket.\n */\n const objectExists = async (file: File): Promise<boolean> => {\n try {\n await getObjectMetadata(file);\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound' || error.$metadata?.httpStatusCode === 404) {\n return false;\n }\n throw error;\n }\n };\n\n return {\n /**\n * Returns whether the bucket is configured with private ACL.\n */\n isPrivate() {\n return config.params.ACL === 'private';\n },\n\n /**\n * Returns the current provider configuration.\n */\n getProviderConfig(): ProviderConfig | undefined {\n return providerConfig;\n },\n\n /**\n * Generates a signed URL for accessing a private object.\n */\n async getSignedUrl(file: File, customParams: any): Promise<{ url: string }> {\n if (!isUrlFromBucket(file.url, config.params.Bucket, baseUrl)) {\n return { url: file.url };\n }\n const fileKey = getFileKey(file);\n\n // Spread customParams first, then override with secure values\n // This prevents malicious override of Bucket and Key\n const url = await getSignedUrl(\n s3Client,\n new GetObjectCommand({\n ...customParams,\n Bucket: config.params.Bucket,\n Key: fileKey,\n }),\n {\n expiresIn: getOr(15 * 60, ['params', 'signedUrlExpires'], config),\n }\n );\n\n return { url };\n },\n\n /**\n * Uploads a file using streaming.\n */\n uploadStream(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file to S3.\n */\n upload(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file only if it matches the expected ETag (optimistic locking).\n * Throws PreconditionFailed error if ETag does not match.\n */\n uploadIfMatch(file: File, expectedETag: string, customParams = {}) {\n return uploadIfMatch(file, expectedETag, customParams);\n },\n\n /**\n * Retrieves object metadata including ETag.\n */\n getObjectMetadata(file: File) {\n return getObjectMetadata(file);\n },\n\n /**\n * Checks if an object exists in the bucket.\n */\n objectExists(file: File) {\n return objectExists(file);\n },\n\n /**\n * Deletes an object from S3.\n */\n delete(file: File, customParams = {}): Promise<DeleteObjectCommandOutput> {\n // Spread customParams first, then override with secure values\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, ...safeParams } = customParams as any;\n const command = new DeleteObjectCommand({\n ...safeParams,\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n return s3Client.send(command);\n },\n };\n },\n};\n"],"names":["assertUrlProtocol","url","test","sanitizePathComponent","component","replace","mapChecksumAlgorithm","algorithm","undefined","mapping","CRC32","ChecksumAlgorithm","CRC32C","SHA1","SHA256","CRC64NVME","mapStorageClass","storageClass","STANDARD","StorageClass","REDUCED_REDUNDANCY","STANDARD_IA","ONEZONE_IA","INTELLIGENT_TIERING","GLACIER","DEEP_ARCHIVE","GLACIER_IR","mapServerSideEncryption","type","AES256","ServerSideEncryption","aws_kms","aws_kms_dsse","formatTagsForHeader","tags","Object","keys","length","entries","map","key","value","encodeURIComponent","join","isNonAwsEndpoint","endpoint","awsPatterns","some","pattern","validateProviderConfig","providerConfig","s3Options","toString","isNonAws","process","emitWarning","encryption","multipart","partSize","minPartSize","maxPartSize","queueSize","getConfig","legacyS3Options","credentials","extractCredentials","config","params","ACL","ObjectCannedACL","public_read","Error","init","baseUrl","rootPath","s3Client","S3Client","filePrefix","getFileKey","file","sanitizedPath","path","sanitizedHash","hash","sanitizedExt","ext","buildUploadParams","fileKey","customParams","Bucket","Key","Body","stream","Buffer","from","buffer","ContentType","mime","checksumAlgorithm","preventOverwrite","IfNoneMatch","sse","kmsKeyId","SSEKMSKeyId","tagging","Tagging","safeCustomParams","constructFileUrl","uploadLocation","cleanBase","endpointUrl","startsWith","cleanEndpoint","upload","uploadOptions","client","leavePartsOnError","uploadObj","Upload","result","done","Location","ETag","etag","uploadIfMatch","expectedETag","IfMatch","getObjectMetadata","command","HeadObjectCommand","response","send","contentLength","ContentLength","contentType","lastModified","LastModified","serverSideEncryption","objectExists","error","name","$metadata","httpStatusCode","isPrivate","getProviderConfig","getSignedUrl","isUrlFromBucket","GetObjectCommand","expiresIn","getOr","uploadStream","delete","safeParams","DeleteObjectCommand"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { ReadStream } from 'node:fs';\nimport { getOr } from 'lodash/fp';\nimport {\n S3Client,\n GetObjectCommand,\n DeleteObjectCommand,\n DeleteObjectCommandOutput,\n HeadObjectCommand,\n PutObjectCommandInput,\n CompleteMultipartUploadCommandOutput,\n AbortMultipartUploadCommandOutput,\n S3ClientConfig,\n ObjectCannedACL,\n ChecksumAlgorithm,\n StorageClass,\n ServerSideEncryption,\n} from '@aws-sdk/client-s3';\nimport type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport { Upload } from '@aws-sdk/lib-storage';\nimport { extractCredentials, isUrlFromBucket } from './utils';\n\n/**\n * Supported checksum algorithms for data integrity validation.\n * CRC64NVME is recommended for best performance on modern hardware.\n */\nexport type SupportedChecksumAlgorithm = 'CRC32' | 'CRC32C' | 'SHA1' | 'SHA256' | 'CRC64NVME';\n\n/**\n * Supported S3 storage classes for cost optimization.\n */\nexport type SupportedStorageClass =\n | 'STANDARD'\n | 'REDUCED_REDUNDANCY'\n | 'STANDARD_IA'\n | 'ONEZONE_IA'\n | 'INTELLIGENT_TIERING'\n | 'GLACIER'\n | 'DEEP_ARCHIVE'\n | 'GLACIER_IR';\n\n/**\n * Server-side encryption types.\n */\nexport type EncryptionType = 'AES256' | 'aws:kms' | 'aws:kms:dsse';\n\n/**\n * Encryption configuration for server-side encryption.\n */\nexport interface EncryptionConfig {\n type: EncryptionType;\n kmsKeyId?: string;\n}\n\n/**\n * Multipart upload configuration for large files.\n */\nexport interface MultipartConfig {\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n}\n\nexport interface File {\n name: string;\n alternativeText?: string;\n caption?: string;\n width?: number;\n height?: number;\n formats?: Record<string, unknown>;\n hash: string;\n ext?: string;\n mime: string;\n size: number;\n sizeInBytes: number;\n url: string;\n previewUrl?: string;\n path?: string;\n provider?: string;\n provider_metadata?: Record<string, unknown>;\n stream?: ReadStream;\n buffer?: Buffer;\n etag?: string;\n}\n\nexport type UploadCommandOutput = (\n | CompleteMultipartUploadCommandOutput\n | AbortMultipartUploadCommandOutput\n) & {\n Location: string;\n ETag?: string;\n};\n\nexport interface AWSParams {\n Bucket: string;\n ACL?: ObjectCannedACL;\n signedUrlExpires?: number;\n}\n\n/**\n * Extended configuration options for the S3 provider.\n */\nexport interface ProviderConfig {\n /**\n * Checksum algorithm for data integrity validation during upload.\n * When enabled, the SDK calculates a checksum and S3 validates it server-side.\n */\n checksumAlgorithm?: SupportedChecksumAlgorithm;\n\n /**\n * When true, uploads will fail if an object with the same key already exists.\n * This prevents accidental overwrites due to race conditions.\n */\n preventOverwrite?: boolean;\n\n /**\n * S3 storage class for uploaded objects.\n * Use lower-cost classes for infrequently accessed data.\n */\n storageClass?: SupportedStorageClass;\n\n /**\n * Server-side encryption configuration.\n */\n encryption?: EncryptionConfig;\n\n /**\n * Tags to apply to uploaded objects.\n * Useful for cost allocation and lifecycle policies.\n */\n tags?: Record<string, string>;\n\n /**\n * Multipart upload configuration for large files.\n */\n multipart?: MultipartConfig;\n}\n\nexport interface DefaultOptions extends S3ClientConfig {\n // TODO Remove this in V5\n accessKeyId?: AwsCredentialIdentity['accessKeyId'];\n secretAccessKey?: AwsCredentialIdentity['secretAccessKey'];\n // Keep this for V5\n credentials?: AwsCredentialIdentity;\n params?: AWSParams;\n [k: string]: unknown;\n}\n\nexport type InitOptions = (DefaultOptions | { s3Options: DefaultOptions }) & {\n baseUrl?: string;\n rootPath?: string;\n providerConfig?: ProviderConfig;\n [k: string]: unknown;\n};\n\n/**\n * Validates that a URL uses HTTP or HTTPS protocol.\n * Rejects dangerous protocols like file://, javascript:, data:, etc.\n */\nconst assertUrlProtocol = (url: string) => {\n return /^https?:\\/\\//.test(url);\n};\n\n/**\n * Sanitizes a path component to prevent path traversal attacks.\n * Removes directory traversal sequences and normalizes the path.\n */\nconst sanitizePathComponent = (component: string | undefined): string => {\n if (!component) return '';\n return component\n .replace(/\\.\\./g, '')\n .replace(/^\\/+|\\/+$/g, '')\n .replace(/\\/+/g, '/');\n};\n\n/**\n * Maps the provider checksum algorithm to the AWS SDK checksum algorithm.\n */\nconst mapChecksumAlgorithm = (\n algorithm?: SupportedChecksumAlgorithm\n): ChecksumAlgorithm | undefined => {\n if (!algorithm) return undefined;\n const mapping: Record<SupportedChecksumAlgorithm, ChecksumAlgorithm> = {\n CRC32: ChecksumAlgorithm.CRC32,\n CRC32C: ChecksumAlgorithm.CRC32C,\n SHA1: ChecksumAlgorithm.SHA1,\n SHA256: ChecksumAlgorithm.SHA256,\n CRC64NVME: ChecksumAlgorithm.CRC64NVME,\n };\n return mapping[algorithm];\n};\n\n/**\n * Maps the provider storage class to the AWS SDK storage class.\n */\nconst mapStorageClass = (storageClass?: SupportedStorageClass): StorageClass | undefined => {\n if (!storageClass) return undefined;\n const mapping: Record<SupportedStorageClass, StorageClass> = {\n STANDARD: StorageClass.STANDARD,\n REDUCED_REDUNDANCY: StorageClass.REDUCED_REDUNDANCY,\n STANDARD_IA: StorageClass.STANDARD_IA,\n ONEZONE_IA: StorageClass.ONEZONE_IA,\n INTELLIGENT_TIERING: StorageClass.INTELLIGENT_TIERING,\n GLACIER: StorageClass.GLACIER,\n DEEP_ARCHIVE: StorageClass.DEEP_ARCHIVE,\n GLACIER_IR: StorageClass.GLACIER_IR,\n };\n return mapping[storageClass];\n};\n\n/**\n * Maps the provider encryption type to the AWS SDK server-side encryption.\n */\nconst mapServerSideEncryption = (type?: EncryptionType): ServerSideEncryption | undefined => {\n if (!type) return undefined;\n const mapping: Record<EncryptionType, ServerSideEncryption> = {\n AES256: ServerSideEncryption.AES256,\n 'aws:kms': ServerSideEncryption.aws_kms,\n 'aws:kms:dsse': ServerSideEncryption.aws_kms_dsse,\n };\n return mapping[type];\n};\n\n/**\n * Converts a tags object to the S3 Tagging header format.\n * Format: key1=value1&key2=value2\n */\nconst formatTagsForHeader = (tags?: Record<string, string>): string | undefined => {\n if (!tags || Object.keys(tags).length === 0) return undefined;\n return Object.entries(tags)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&');\n};\n\n/**\n * Checks if the endpoint appears to be a non-AWS S3-compatible provider.\n */\nconst isNonAwsEndpoint = (endpoint?: string): boolean => {\n if (!endpoint) return false;\n const awsPatterns = [/\\.amazonaws\\.com$/i, /\\.amazonaws\\.com\\.cn$/i];\n return !awsPatterns.some((pattern) => pattern.test(endpoint));\n};\n\n/**\n * Validates provider configuration and emits warnings for potential compatibility issues.\n */\nconst validateProviderConfig = (\n providerConfig: ProviderConfig | undefined,\n s3Options: DefaultOptions | undefined\n): void => {\n if (!providerConfig) return;\n\n const endpoint = s3Options?.endpoint?.toString() || '';\n const isNonAws = isNonAwsEndpoint(endpoint);\n\n // Warn about AWS-specific features when using non-AWS endpoints\n if (isNonAws) {\n if (providerConfig.storageClass) {\n process.emitWarning(\n `Storage class '${providerConfig.storageClass}' is AWS S3-specific and may be ignored by your S3-compatible provider.`\n );\n }\n\n if (providerConfig.encryption?.type && providerConfig.encryption.type !== 'AES256') {\n process.emitWarning(\n `Encryption type '${providerConfig.encryption.type}' is AWS S3-specific. Consider using 'AES256' for better compatibility.`\n );\n }\n }\n\n // Validate multipart configuration\n if (providerConfig.multipart?.partSize) {\n const minPartSize = 5 * 1024 * 1024; // 5MB\n const maxPartSize = 5 * 1024 * 1024 * 1024; // 5GB\n\n if (providerConfig.multipart.partSize < minPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} is below the minimum of 5MB. This may cause upload failures.`\n );\n }\n\n if (providerConfig.multipart.partSize > maxPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} exceeds the maximum of 5GB. This may cause upload failures.`\n );\n }\n }\n\n if (providerConfig.multipart?.queueSize && providerConfig.multipart.queueSize > 16) {\n process.emitWarning(\n `Multipart queueSize ${providerConfig.multipart.queueSize} is high and may cause memory issues. Consider using 4-8.`\n );\n }\n};\n\nconst getConfig = ({\n s3Options,\n legacyS3Options,\n}: {\n s3Options: DefaultOptions;\n legacyS3Options: Record<string, unknown>;\n}) => {\n if (Object.keys(legacyS3Options).length > 0) {\n process.emitWarning(\n \"S3 configuration options passed at root level of the plugin's providerOptions is deprecated and will be removed in a future release. Please wrap them inside the 's3Options:{}' property.\"\n );\n }\n const credentials = extractCredentials({ s3Options, ...legacyS3Options });\n const config = {\n ...s3Options,\n ...legacyS3Options,\n ...(credentials ? { credentials } : {}),\n };\n\n if (config.params !== undefined) {\n // Only set default ACL when ACL is not explicitly present in params.\n // Since April 2023, new AWS S3 buckets have ACLs disabled by default\n // (\"Bucket owner enforced\"). Sending an ACL header to such buckets\n // throws AccessControlListNotSupported. To disable ACLs, users should\n // simply not include ACL in their params configuration.\n if (!('ACL' in config.params)) {\n config.params.ACL = ObjectCannedACL.public_read;\n }\n } else {\n throw new Error('Upload AWS S3 provider: `params` are required in the config object');\n }\n\n return config as DefaultOptions & {\n params: AWSParams;\n };\n};\n\nexport default {\n init({ baseUrl, rootPath, s3Options, providerConfig, ...legacyS3Options }: InitOptions) {\n // Validate configuration and emit warnings for potential issues\n validateProviderConfig(providerConfig, s3Options as DefaultOptions);\n\n // TODO V5 change config structure to avoid having to do this\n const config = getConfig({ s3Options: s3Options as DefaultOptions, legacyS3Options });\n const s3Client = new S3Client(config);\n const filePrefix = rootPath ? `${rootPath.replace(/\\/+$/, '')}/` : '';\n\n const getFileKey = (file: File) => {\n const sanitizedPath = sanitizePathComponent(file.path);\n const path = sanitizedPath ? `${sanitizedPath}/` : '';\n const sanitizedHash = sanitizePathComponent(file.hash);\n const sanitizedExt = file.ext ? file.ext.replace(/[^a-zA-Z0-9.]/g, '') : '';\n return `${filePrefix}${path}${sanitizedHash}${sanitizedExt}`;\n };\n\n /**\n * Builds the upload parameters including all configured features.\n */\n const buildUploadParams = (\n file: File,\n fileKey: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ): PutObjectCommandInput => {\n const params: PutObjectCommandInput = {\n Bucket: config.params.Bucket,\n Key: fileKey,\n Body: file.stream || Buffer.from(file.buffer as any, 'binary'),\n // ACL is optional to support providers like Cloudflare R2 that don't support ACLs.\n // Set params.ACL to undefined or omit it entirely to disable ACL headers.\n ...(config.params.ACL ? { ACL: config.params.ACL } : {}),\n ContentType: file.mime,\n };\n\n // Checksum validation\n const checksumAlgorithm = mapChecksumAlgorithm(providerConfig?.checksumAlgorithm);\n if (checksumAlgorithm) {\n params.ChecksumAlgorithm = checksumAlgorithm;\n }\n\n // Conditional writes - prevent overwrite\n if (providerConfig?.preventOverwrite) {\n params.IfNoneMatch = '*';\n }\n\n // Storage class\n const storageClass = mapStorageClass(providerConfig?.storageClass);\n if (storageClass) {\n params.StorageClass = storageClass;\n }\n\n // Server-side encryption\n if (providerConfig?.encryption) {\n const sse = mapServerSideEncryption(providerConfig.encryption.type);\n if (sse) {\n params.ServerSideEncryption = sse;\n if (providerConfig.encryption.kmsKeyId) {\n params.SSEKMSKeyId = providerConfig.encryption.kmsKeyId;\n }\n }\n }\n\n // Object tagging\n const tagging = formatTagsForHeader(providerConfig?.tags);\n if (tagging) {\n params.Tagging = tagging;\n }\n\n // Merge customParams but preserve critical security parameters\n // Bucket, Key, and Body must not be overridden by customParams\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, Body, ...safeCustomParams } = customParams as any;\n return { ...params, ...safeCustomParams };\n };\n\n /**\n * Constructs the correct file URL.\n * Handles S3-compatible providers that return incorrect Location formats.\n */\n const constructFileUrl = (fileKey: string, uploadLocation: string): string => {\n // Priority 1: Use baseUrl if configured (CDN or custom domain)\n if (baseUrl) {\n const cleanBase = baseUrl.replace(/\\/+$/, '');\n return `${cleanBase}/${fileKey}`;\n }\n\n // Priority 2: Construct URL from endpoint if configured\n // This fixes issues with S3-compatible providers (IONOS, MinIO, etc.)\n // that return Location in incorrect format for multipart uploads\n const endpoint = config.endpoint?.toString();\n if (endpoint) {\n const endpointUrl = endpoint.startsWith('http') ? endpoint : `https://${endpoint}`;\n const cleanEndpoint = endpointUrl.replace(/\\/+$/, '');\n return `${cleanEndpoint}/${config.params.Bucket}/${fileKey}`;\n }\n\n // Priority 3: Use the Location from S3 response\n if (assertUrlProtocol(uploadLocation)) {\n return uploadLocation;\n }\n\n // Priority 4: Prepend https if protocol is missing\n return `https://${uploadLocation}`;\n };\n\n const upload = async (file: File, customParams: Partial<PutObjectCommandInput> = {}) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, customParams);\n\n const uploadOptions: {\n client: S3Client;\n params: PutObjectCommandInput;\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n } = {\n client: s3Client,\n params,\n };\n\n // Multipart configuration\n if (providerConfig?.multipart) {\n if (providerConfig.multipart.partSize) {\n uploadOptions.partSize = providerConfig.multipart.partSize;\n }\n if (providerConfig.multipart.queueSize) {\n uploadOptions.queueSize = providerConfig.multipart.queueSize;\n }\n if (providerConfig.multipart.leavePartsOnError !== undefined) {\n uploadOptions.leavePartsOnError = providerConfig.multipart.leavePartsOnError;\n }\n }\n\n const uploadObj = new Upload(uploadOptions);\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n // Store ETag for potential future conditional updates\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Uploads a file only if the existing object matches the expected ETag.\n * This implements optimistic locking to prevent lost updates.\n */\n const uploadIfMatch = async (\n file: File,\n expectedETag: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, {\n ...customParams,\n IfMatch: expectedETag,\n });\n\n const uploadObj = new Upload({\n client: s3Client,\n params,\n });\n\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Retrieves metadata for an object including its ETag.\n */\n const getObjectMetadata = async (file: File) => {\n const command = new HeadObjectCommand({\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n\n const response = await s3Client.send(command);\n\n return {\n etag: response.ETag?.replace(/\"/g, ''),\n contentLength: response.ContentLength,\n contentType: response.ContentType,\n lastModified: response.LastModified,\n storageClass: response.StorageClass,\n serverSideEncryption: response.ServerSideEncryption,\n };\n };\n\n /**\n * Checks if an object exists in the bucket.\n */\n const objectExists = async (file: File): Promise<boolean> => {\n try {\n await getObjectMetadata(file);\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound' || error.$metadata?.httpStatusCode === 404) {\n return false;\n }\n throw error;\n }\n };\n\n return {\n /**\n * Returns whether the bucket is configured with private ACL.\n */\n isPrivate() {\n return config.params.ACL === 'private';\n },\n\n /**\n * Returns the current provider configuration.\n */\n getProviderConfig(): ProviderConfig | undefined {\n return providerConfig;\n },\n\n /**\n * Generates a signed URL for accessing a private object.\n */\n async getSignedUrl(file: File, customParams: any): Promise<{ url: string }> {\n if (!isUrlFromBucket(file.url, config.params.Bucket, baseUrl)) {\n return { url: file.url };\n }\n const fileKey = getFileKey(file);\n\n // Spread customParams first, then override with secure values\n // This prevents malicious override of Bucket and Key\n const url = await getSignedUrl(\n s3Client,\n new GetObjectCommand({\n ...customParams,\n Bucket: config.params.Bucket,\n Key: fileKey,\n }),\n {\n expiresIn: getOr(15 * 60, ['params', 'signedUrlExpires'], config),\n }\n );\n\n return { url };\n },\n\n /**\n * Uploads a file using streaming.\n */\n uploadStream(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file to S3.\n */\n upload(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file only if it matches the expected ETag (optimistic locking).\n * Throws PreconditionFailed error if ETag does not match.\n */\n uploadIfMatch(file: File, expectedETag: string, customParams = {}) {\n return uploadIfMatch(file, expectedETag, customParams);\n },\n\n /**\n * Retrieves object metadata including ETag.\n */\n getObjectMetadata(file: File) {\n return getObjectMetadata(file);\n },\n\n /**\n * Checks if an object exists in the bucket.\n */\n objectExists(file: File) {\n return objectExists(file);\n },\n\n /**\n * Deletes an object from S3.\n */\n delete(file: File, customParams = {}): Promise<DeleteObjectCommandOutput> {\n // Spread customParams first, then override with secure values\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, ...safeParams } = customParams as any;\n const command = new DeleteObjectCommand({\n ...safeParams,\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n return s3Client.send(command);\n },\n };\n },\n};\n"],"names":["assertUrlProtocol","url","test","sanitizePathComponent","component","replace","mapChecksumAlgorithm","algorithm","undefined","mapping","CRC32","ChecksumAlgorithm","CRC32C","SHA1","SHA256","CRC64NVME","mapStorageClass","storageClass","STANDARD","StorageClass","REDUCED_REDUNDANCY","STANDARD_IA","ONEZONE_IA","INTELLIGENT_TIERING","GLACIER","DEEP_ARCHIVE","GLACIER_IR","mapServerSideEncryption","type","AES256","ServerSideEncryption","aws_kms","aws_kms_dsse","formatTagsForHeader","tags","Object","keys","length","entries","map","key","value","encodeURIComponent","join","isNonAwsEndpoint","endpoint","awsPatterns","some","pattern","validateProviderConfig","providerConfig","s3Options","toString","isNonAws","process","emitWarning","encryption","multipart","partSize","minPartSize","maxPartSize","queueSize","getConfig","legacyS3Options","credentials","extractCredentials","config","params","ACL","ObjectCannedACL","public_read","Error","init","baseUrl","rootPath","s3Client","S3Client","filePrefix","getFileKey","file","sanitizedPath","path","sanitizedHash","hash","sanitizedExt","ext","buildUploadParams","fileKey","customParams","Bucket","Key","Body","stream","Buffer","from","buffer","ContentType","mime","checksumAlgorithm","preventOverwrite","IfNoneMatch","sse","kmsKeyId","SSEKMSKeyId","tagging","Tagging","safeCustomParams","constructFileUrl","uploadLocation","cleanBase","endpointUrl","startsWith","cleanEndpoint","upload","uploadOptions","client","leavePartsOnError","uploadObj","Upload","result","done","Location","ETag","etag","uploadIfMatch","expectedETag","IfMatch","getObjectMetadata","command","HeadObjectCommand","response","send","contentLength","ContentLength","contentType","lastModified","LastModified","serverSideEncryption","objectExists","error","name","$metadata","httpStatusCode","isPrivate","getProviderConfig","getSignedUrl","isUrlFromBucket","GetObjectCommand","expiresIn","getOr","uploadStream","delete","safeParams","DeleteObjectCommand"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { getOr } from 'lodash/fp';
2
- import { S3Client, GetObjectCommand, DeleteObjectCommand, ObjectCannedACL, HeadObjectCommand, ChecksumAlgorithm, StorageClass, ServerSideEncryption } from '@aws-sdk/client-s3';
2
+ import { S3Client, DeleteObjectCommand, GetObjectCommand, ObjectCannedACL, HeadObjectCommand, ChecksumAlgorithm, StorageClass, ServerSideEncryption } from '@aws-sdk/client-s3';
3
3
  import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
4
4
  import { Upload } from '@aws-sdk/lib-storage';
5
5
  import { isUrlFromBucket, extractCredentials } from './utils.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import type { ReadStream } from 'node:fs';\nimport { getOr } from 'lodash/fp';\nimport {\n S3Client,\n GetObjectCommand,\n DeleteObjectCommand,\n DeleteObjectCommandOutput,\n HeadObjectCommand,\n PutObjectCommandInput,\n CompleteMultipartUploadCommandOutput,\n AbortMultipartUploadCommandOutput,\n S3ClientConfig,\n ObjectCannedACL,\n ChecksumAlgorithm,\n StorageClass,\n ServerSideEncryption,\n} from '@aws-sdk/client-s3';\nimport type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport { Upload } from '@aws-sdk/lib-storage';\nimport { extractCredentials, isUrlFromBucket } from './utils';\n\n/**\n * Supported checksum algorithms for data integrity validation.\n * CRC64NVME is recommended for best performance on modern hardware.\n */\nexport type SupportedChecksumAlgorithm = 'CRC32' | 'CRC32C' | 'SHA1' | 'SHA256' | 'CRC64NVME';\n\n/**\n * Supported S3 storage classes for cost optimization.\n */\nexport type SupportedStorageClass =\n | 'STANDARD'\n | 'REDUCED_REDUNDANCY'\n | 'STANDARD_IA'\n | 'ONEZONE_IA'\n | 'INTELLIGENT_TIERING'\n | 'GLACIER'\n | 'DEEP_ARCHIVE'\n | 'GLACIER_IR';\n\n/**\n * Server-side encryption types.\n */\nexport type EncryptionType = 'AES256' | 'aws:kms' | 'aws:kms:dsse';\n\n/**\n * Encryption configuration for server-side encryption.\n */\nexport interface EncryptionConfig {\n type: EncryptionType;\n kmsKeyId?: string;\n}\n\n/**\n * Multipart upload configuration for large files.\n */\nexport interface MultipartConfig {\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n}\n\nexport interface File {\n name: string;\n alternativeText?: string;\n caption?: string;\n width?: number;\n height?: number;\n formats?: Record<string, unknown>;\n hash: string;\n ext?: string;\n mime: string;\n size: number;\n sizeInBytes: number;\n url: string;\n previewUrl?: string;\n path?: string;\n provider?: string;\n provider_metadata?: Record<string, unknown>;\n stream?: ReadStream;\n buffer?: Buffer;\n etag?: string;\n}\n\nexport type UploadCommandOutput = (\n | CompleteMultipartUploadCommandOutput\n | AbortMultipartUploadCommandOutput\n) & {\n Location: string;\n ETag?: string;\n};\n\nexport interface AWSParams {\n Bucket: string;\n ACL?: ObjectCannedACL;\n signedUrlExpires?: number;\n}\n\n/**\n * Extended configuration options for the S3 provider.\n */\nexport interface ProviderConfig {\n /**\n * Checksum algorithm for data integrity validation during upload.\n * When enabled, the SDK calculates a checksum and S3 validates it server-side.\n */\n checksumAlgorithm?: SupportedChecksumAlgorithm;\n\n /**\n * When true, uploads will fail if an object with the same key already exists.\n * This prevents accidental overwrites due to race conditions.\n */\n preventOverwrite?: boolean;\n\n /**\n * S3 storage class for uploaded objects.\n * Use lower-cost classes for infrequently accessed data.\n */\n storageClass?: SupportedStorageClass;\n\n /**\n * Server-side encryption configuration.\n */\n encryption?: EncryptionConfig;\n\n /**\n * Tags to apply to uploaded objects.\n * Useful for cost allocation and lifecycle policies.\n */\n tags?: Record<string, string>;\n\n /**\n * Multipart upload configuration for large files.\n */\n multipart?: MultipartConfig;\n}\n\nexport interface DefaultOptions extends S3ClientConfig {\n // TODO Remove this in V5\n accessKeyId?: AwsCredentialIdentity['accessKeyId'];\n secretAccessKey?: AwsCredentialIdentity['secretAccessKey'];\n // Keep this for V5\n credentials?: AwsCredentialIdentity;\n params?: AWSParams;\n [k: string]: unknown;\n}\n\nexport type InitOptions = (DefaultOptions | { s3Options: DefaultOptions }) & {\n baseUrl?: string;\n rootPath?: string;\n providerConfig?: ProviderConfig;\n [k: string]: unknown;\n};\n\n/**\n * Validates that a URL uses HTTP or HTTPS protocol.\n * Rejects dangerous protocols like file://, javascript:, data:, etc.\n */\nconst assertUrlProtocol = (url: string) => {\n return /^https?:\\/\\//.test(url);\n};\n\n/**\n * Sanitizes a path component to prevent path traversal attacks.\n * Removes directory traversal sequences and normalizes the path.\n */\nconst sanitizePathComponent = (component: string | undefined): string => {\n if (!component) return '';\n return component\n .replace(/\\.\\./g, '')\n .replace(/^\\/+|\\/+$/g, '')\n .replace(/\\/+/g, '/');\n};\n\n/**\n * Maps the provider checksum algorithm to the AWS SDK checksum algorithm.\n */\nconst mapChecksumAlgorithm = (\n algorithm?: SupportedChecksumAlgorithm\n): ChecksumAlgorithm | undefined => {\n if (!algorithm) return undefined;\n const mapping: Record<SupportedChecksumAlgorithm, ChecksumAlgorithm> = {\n CRC32: ChecksumAlgorithm.CRC32,\n CRC32C: ChecksumAlgorithm.CRC32C,\n SHA1: ChecksumAlgorithm.SHA1,\n SHA256: ChecksumAlgorithm.SHA256,\n CRC64NVME: ChecksumAlgorithm.CRC64NVME,\n };\n return mapping[algorithm];\n};\n\n/**\n * Maps the provider storage class to the AWS SDK storage class.\n */\nconst mapStorageClass = (storageClass?: SupportedStorageClass): StorageClass | undefined => {\n if (!storageClass) return undefined;\n const mapping: Record<SupportedStorageClass, StorageClass> = {\n STANDARD: StorageClass.STANDARD,\n REDUCED_REDUNDANCY: StorageClass.REDUCED_REDUNDANCY,\n STANDARD_IA: StorageClass.STANDARD_IA,\n ONEZONE_IA: StorageClass.ONEZONE_IA,\n INTELLIGENT_TIERING: StorageClass.INTELLIGENT_TIERING,\n GLACIER: StorageClass.GLACIER,\n DEEP_ARCHIVE: StorageClass.DEEP_ARCHIVE,\n GLACIER_IR: StorageClass.GLACIER_IR,\n };\n return mapping[storageClass];\n};\n\n/**\n * Maps the provider encryption type to the AWS SDK server-side encryption.\n */\nconst mapServerSideEncryption = (type?: EncryptionType): ServerSideEncryption | undefined => {\n if (!type) return undefined;\n const mapping: Record<EncryptionType, ServerSideEncryption> = {\n AES256: ServerSideEncryption.AES256,\n 'aws:kms': ServerSideEncryption.aws_kms,\n 'aws:kms:dsse': ServerSideEncryption.aws_kms_dsse,\n };\n return mapping[type];\n};\n\n/**\n * Converts a tags object to the S3 Tagging header format.\n * Format: key1=value1&key2=value2\n */\nconst formatTagsForHeader = (tags?: Record<string, string>): string | undefined => {\n if (!tags || Object.keys(tags).length === 0) return undefined;\n return Object.entries(tags)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&');\n};\n\n/**\n * Checks if the endpoint appears to be a non-AWS S3-compatible provider.\n */\nconst isNonAwsEndpoint = (endpoint?: string): boolean => {\n if (!endpoint) return false;\n const awsPatterns = [/\\.amazonaws\\.com$/i, /\\.amazonaws\\.com\\.cn$/i];\n return !awsPatterns.some((pattern) => pattern.test(endpoint));\n};\n\n/**\n * Validates provider configuration and emits warnings for potential compatibility issues.\n */\nconst validateProviderConfig = (\n providerConfig: ProviderConfig | undefined,\n s3Options: DefaultOptions | undefined\n): void => {\n if (!providerConfig) return;\n\n const endpoint = s3Options?.endpoint?.toString() || '';\n const isNonAws = isNonAwsEndpoint(endpoint);\n\n // Warn about AWS-specific features when using non-AWS endpoints\n if (isNonAws) {\n if (providerConfig.storageClass) {\n process.emitWarning(\n `Storage class '${providerConfig.storageClass}' is AWS S3-specific and may be ignored by your S3-compatible provider.`\n );\n }\n\n if (providerConfig.encryption?.type && providerConfig.encryption.type !== 'AES256') {\n process.emitWarning(\n `Encryption type '${providerConfig.encryption.type}' is AWS S3-specific. Consider using 'AES256' for better compatibility.`\n );\n }\n }\n\n // Validate multipart configuration\n if (providerConfig.multipart?.partSize) {\n const minPartSize = 5 * 1024 * 1024; // 5MB\n const maxPartSize = 5 * 1024 * 1024 * 1024; // 5GB\n\n if (providerConfig.multipart.partSize < minPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} is below the minimum of 5MB. This may cause upload failures.`\n );\n }\n\n if (providerConfig.multipart.partSize > maxPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} exceeds the maximum of 5GB. This may cause upload failures.`\n );\n }\n }\n\n if (providerConfig.multipart?.queueSize && providerConfig.multipart.queueSize > 16) {\n process.emitWarning(\n `Multipart queueSize ${providerConfig.multipart.queueSize} is high and may cause memory issues. Consider using 4-8.`\n );\n }\n};\n\nconst getConfig = ({\n s3Options,\n legacyS3Options,\n}: {\n s3Options: DefaultOptions;\n legacyS3Options: Record<string, unknown>;\n}) => {\n if (Object.keys(legacyS3Options).length > 0) {\n process.emitWarning(\n \"S3 configuration options passed at root level of the plugin's providerOptions is deprecated and will be removed in a future release. Please wrap them inside the 's3Options:{}' property.\"\n );\n }\n const credentials = extractCredentials({ s3Options, ...legacyS3Options });\n const config = {\n ...s3Options,\n ...legacyS3Options,\n ...(credentials ? { credentials } : {}),\n };\n\n if (config.params !== undefined) {\n // Only set default ACL when ACL is not explicitly present in params.\n // Since April 2023, new AWS S3 buckets have ACLs disabled by default\n // (\"Bucket owner enforced\"). Sending an ACL header to such buckets\n // throws AccessControlListNotSupported. To disable ACLs, users should\n // simply not include ACL in their params configuration.\n if (!('ACL' in config.params)) {\n config.params.ACL = ObjectCannedACL.public_read;\n }\n } else {\n throw new Error('Upload AWS S3 provider: `params` are required in the config object');\n }\n\n return config as DefaultOptions & {\n params: AWSParams;\n };\n};\n\nexport default {\n init({ baseUrl, rootPath, s3Options, providerConfig, ...legacyS3Options }: InitOptions) {\n // Validate configuration and emit warnings for potential issues\n validateProviderConfig(providerConfig, s3Options as DefaultOptions);\n\n // TODO V5 change config structure to avoid having to do this\n const config = getConfig({ s3Options: s3Options as DefaultOptions, legacyS3Options });\n const s3Client = new S3Client(config);\n const filePrefix = rootPath ? `${rootPath.replace(/\\/+$/, '')}/` : '';\n\n const getFileKey = (file: File) => {\n const sanitizedPath = sanitizePathComponent(file.path);\n const path = sanitizedPath ? `${sanitizedPath}/` : '';\n const sanitizedHash = sanitizePathComponent(file.hash);\n const sanitizedExt = file.ext ? file.ext.replace(/[^a-zA-Z0-9.]/g, '') : '';\n return `${filePrefix}${path}${sanitizedHash}${sanitizedExt}`;\n };\n\n /**\n * Builds the upload parameters including all configured features.\n */\n const buildUploadParams = (\n file: File,\n fileKey: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ): PutObjectCommandInput => {\n const params: PutObjectCommandInput = {\n Bucket: config.params.Bucket,\n Key: fileKey,\n Body: file.stream || Buffer.from(file.buffer as any, 'binary'),\n // ACL is optional to support providers like Cloudflare R2 that don't support ACLs.\n // Set params.ACL to undefined or omit it entirely to disable ACL headers.\n ...(config.params.ACL ? { ACL: config.params.ACL } : {}),\n ContentType: file.mime,\n };\n\n // Checksum validation\n const checksumAlgorithm = mapChecksumAlgorithm(providerConfig?.checksumAlgorithm);\n if (checksumAlgorithm) {\n params.ChecksumAlgorithm = checksumAlgorithm;\n }\n\n // Conditional writes - prevent overwrite\n if (providerConfig?.preventOverwrite) {\n params.IfNoneMatch = '*';\n }\n\n // Storage class\n const storageClass = mapStorageClass(providerConfig?.storageClass);\n if (storageClass) {\n params.StorageClass = storageClass;\n }\n\n // Server-side encryption\n if (providerConfig?.encryption) {\n const sse = mapServerSideEncryption(providerConfig.encryption.type);\n if (sse) {\n params.ServerSideEncryption = sse;\n if (providerConfig.encryption.kmsKeyId) {\n params.SSEKMSKeyId = providerConfig.encryption.kmsKeyId;\n }\n }\n }\n\n // Object tagging\n const tagging = formatTagsForHeader(providerConfig?.tags);\n if (tagging) {\n params.Tagging = tagging;\n }\n\n // Merge customParams but preserve critical security parameters\n // Bucket, Key, and Body must not be overridden by customParams\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, Body, ...safeCustomParams } = customParams as any;\n return { ...params, ...safeCustomParams };\n };\n\n /**\n * Constructs the correct file URL.\n * Handles S3-compatible providers that return incorrect Location formats.\n */\n const constructFileUrl = (fileKey: string, uploadLocation: string): string => {\n // Priority 1: Use baseUrl if configured (CDN or custom domain)\n if (baseUrl) {\n const cleanBase = baseUrl.replace(/\\/+$/, '');\n return `${cleanBase}/${fileKey}`;\n }\n\n // Priority 2: Construct URL from endpoint if configured\n // This fixes issues with S3-compatible providers (IONOS, MinIO, etc.)\n // that return Location in incorrect format for multipart uploads\n const endpoint = config.endpoint?.toString();\n if (endpoint) {\n const endpointUrl = endpoint.startsWith('http') ? endpoint : `https://${endpoint}`;\n const cleanEndpoint = endpointUrl.replace(/\\/+$/, '');\n return `${cleanEndpoint}/${config.params.Bucket}/${fileKey}`;\n }\n\n // Priority 3: Use the Location from S3 response\n if (assertUrlProtocol(uploadLocation)) {\n return uploadLocation;\n }\n\n // Priority 4: Prepend https if protocol is missing\n return `https://${uploadLocation}`;\n };\n\n const upload = async (file: File, customParams: Partial<PutObjectCommandInput> = {}) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, customParams);\n\n const uploadOptions: {\n client: S3Client;\n params: PutObjectCommandInput;\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n } = {\n client: s3Client,\n params,\n };\n\n // Multipart configuration\n if (providerConfig?.multipart) {\n if (providerConfig.multipart.partSize) {\n uploadOptions.partSize = providerConfig.multipart.partSize;\n }\n if (providerConfig.multipart.queueSize) {\n uploadOptions.queueSize = providerConfig.multipart.queueSize;\n }\n if (providerConfig.multipart.leavePartsOnError !== undefined) {\n uploadOptions.leavePartsOnError = providerConfig.multipart.leavePartsOnError;\n }\n }\n\n const uploadObj = new Upload(uploadOptions);\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n // Store ETag for potential future conditional updates\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Uploads a file only if the existing object matches the expected ETag.\n * This implements optimistic locking to prevent lost updates.\n */\n const uploadIfMatch = async (\n file: File,\n expectedETag: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, {\n ...customParams,\n IfMatch: expectedETag,\n });\n\n const uploadObj = new Upload({\n client: s3Client,\n params,\n });\n\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Retrieves metadata for an object including its ETag.\n */\n const getObjectMetadata = async (file: File) => {\n const command = new HeadObjectCommand({\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n\n const response = await s3Client.send(command);\n\n return {\n etag: response.ETag?.replace(/\"/g, ''),\n contentLength: response.ContentLength,\n contentType: response.ContentType,\n lastModified: response.LastModified,\n storageClass: response.StorageClass,\n serverSideEncryption: response.ServerSideEncryption,\n };\n };\n\n /**\n * Checks if an object exists in the bucket.\n */\n const objectExists = async (file: File): Promise<boolean> => {\n try {\n await getObjectMetadata(file);\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound' || error.$metadata?.httpStatusCode === 404) {\n return false;\n }\n throw error;\n }\n };\n\n return {\n /**\n * Returns whether the bucket is configured with private ACL.\n */\n isPrivate() {\n return config.params.ACL === 'private';\n },\n\n /**\n * Returns the current provider configuration.\n */\n getProviderConfig(): ProviderConfig | undefined {\n return providerConfig;\n },\n\n /**\n * Generates a signed URL for accessing a private object.\n */\n async getSignedUrl(file: File, customParams: any): Promise<{ url: string }> {\n if (!isUrlFromBucket(file.url, config.params.Bucket, baseUrl)) {\n return { url: file.url };\n }\n const fileKey = getFileKey(file);\n\n // Spread customParams first, then override with secure values\n // This prevents malicious override of Bucket and Key\n const url = await getSignedUrl(\n s3Client,\n new GetObjectCommand({\n ...customParams,\n Bucket: config.params.Bucket,\n Key: fileKey,\n }),\n {\n expiresIn: getOr(15 * 60, ['params', 'signedUrlExpires'], config),\n }\n );\n\n return { url };\n },\n\n /**\n * Uploads a file using streaming.\n */\n uploadStream(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file to S3.\n */\n upload(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file only if it matches the expected ETag (optimistic locking).\n * Throws PreconditionFailed error if ETag does not match.\n */\n uploadIfMatch(file: File, expectedETag: string, customParams = {}) {\n return uploadIfMatch(file, expectedETag, customParams);\n },\n\n /**\n * Retrieves object metadata including ETag.\n */\n getObjectMetadata(file: File) {\n return getObjectMetadata(file);\n },\n\n /**\n * Checks if an object exists in the bucket.\n */\n objectExists(file: File) {\n return objectExists(file);\n },\n\n /**\n * Deletes an object from S3.\n */\n delete(file: File, customParams = {}): Promise<DeleteObjectCommandOutput> {\n // Spread customParams first, then override with secure values\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, ...safeParams } = customParams as any;\n const command = new DeleteObjectCommand({\n ...safeParams,\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n return s3Client.send(command);\n },\n };\n },\n};\n"],"names":["assertUrlProtocol","url","test","sanitizePathComponent","component","replace","mapChecksumAlgorithm","algorithm","undefined","mapping","CRC32","ChecksumAlgorithm","CRC32C","SHA1","SHA256","CRC64NVME","mapStorageClass","storageClass","STANDARD","StorageClass","REDUCED_REDUNDANCY","STANDARD_IA","ONEZONE_IA","INTELLIGENT_TIERING","GLACIER","DEEP_ARCHIVE","GLACIER_IR","mapServerSideEncryption","type","AES256","ServerSideEncryption","aws_kms","aws_kms_dsse","formatTagsForHeader","tags","Object","keys","length","entries","map","key","value","encodeURIComponent","join","isNonAwsEndpoint","endpoint","awsPatterns","some","pattern","validateProviderConfig","providerConfig","s3Options","toString","isNonAws","process","emitWarning","encryption","multipart","partSize","minPartSize","maxPartSize","queueSize","getConfig","legacyS3Options","credentials","extractCredentials","config","params","ACL","ObjectCannedACL","public_read","Error","init","baseUrl","rootPath","s3Client","S3Client","filePrefix","getFileKey","file","sanitizedPath","path","sanitizedHash","hash","sanitizedExt","ext","buildUploadParams","fileKey","customParams","Bucket","Key","Body","stream","Buffer","from","buffer","ContentType","mime","checksumAlgorithm","preventOverwrite","IfNoneMatch","sse","kmsKeyId","SSEKMSKeyId","tagging","Tagging","safeCustomParams","constructFileUrl","uploadLocation","cleanBase","endpointUrl","startsWith","cleanEndpoint","upload","uploadOptions","client","leavePartsOnError","uploadObj","Upload","result","done","Location","ETag","etag","uploadIfMatch","expectedETag","IfMatch","getObjectMetadata","command","HeadObjectCommand","response","send","contentLength","ContentLength","contentType","lastModified","LastModified","serverSideEncryption","objectExists","error","name","$metadata","httpStatusCode","isPrivate","getProviderConfig","getSignedUrl","isUrlFromBucket","GetObjectCommand","expiresIn","getOr","uploadStream","delete","safeParams","DeleteObjectCommand"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import type { ReadStream } from 'node:fs';\nimport { getOr } from 'lodash/fp';\nimport {\n S3Client,\n GetObjectCommand,\n DeleteObjectCommand,\n DeleteObjectCommandOutput,\n HeadObjectCommand,\n PutObjectCommandInput,\n CompleteMultipartUploadCommandOutput,\n AbortMultipartUploadCommandOutput,\n S3ClientConfig,\n ObjectCannedACL,\n ChecksumAlgorithm,\n StorageClass,\n ServerSideEncryption,\n} from '@aws-sdk/client-s3';\nimport type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport { Upload } from '@aws-sdk/lib-storage';\nimport { extractCredentials, isUrlFromBucket } from './utils';\n\n/**\n * Supported checksum algorithms for data integrity validation.\n * CRC64NVME is recommended for best performance on modern hardware.\n */\nexport type SupportedChecksumAlgorithm = 'CRC32' | 'CRC32C' | 'SHA1' | 'SHA256' | 'CRC64NVME';\n\n/**\n * Supported S3 storage classes for cost optimization.\n */\nexport type SupportedStorageClass =\n | 'STANDARD'\n | 'REDUCED_REDUNDANCY'\n | 'STANDARD_IA'\n | 'ONEZONE_IA'\n | 'INTELLIGENT_TIERING'\n | 'GLACIER'\n | 'DEEP_ARCHIVE'\n | 'GLACIER_IR';\n\n/**\n * Server-side encryption types.\n */\nexport type EncryptionType = 'AES256' | 'aws:kms' | 'aws:kms:dsse';\n\n/**\n * Encryption configuration for server-side encryption.\n */\nexport interface EncryptionConfig {\n type: EncryptionType;\n kmsKeyId?: string;\n}\n\n/**\n * Multipart upload configuration for large files.\n */\nexport interface MultipartConfig {\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n}\n\nexport interface File {\n name: string;\n alternativeText?: string;\n caption?: string;\n width?: number;\n height?: number;\n formats?: Record<string, unknown>;\n hash: string;\n ext?: string;\n mime: string;\n size: number;\n sizeInBytes: number;\n url: string;\n previewUrl?: string;\n path?: string;\n provider?: string;\n provider_metadata?: Record<string, unknown>;\n stream?: ReadStream;\n buffer?: Buffer;\n etag?: string;\n}\n\nexport type UploadCommandOutput = (\n | CompleteMultipartUploadCommandOutput\n | AbortMultipartUploadCommandOutput\n) & {\n Location: string;\n ETag?: string;\n};\n\nexport interface AWSParams {\n Bucket: string;\n ACL?: ObjectCannedACL;\n signedUrlExpires?: number;\n}\n\n/**\n * Extended configuration options for the S3 provider.\n */\nexport interface ProviderConfig {\n /**\n * Checksum algorithm for data integrity validation during upload.\n * When enabled, the SDK calculates a checksum and S3 validates it server-side.\n */\n checksumAlgorithm?: SupportedChecksumAlgorithm;\n\n /**\n * When true, uploads will fail if an object with the same key already exists.\n * This prevents accidental overwrites due to race conditions.\n */\n preventOverwrite?: boolean;\n\n /**\n * S3 storage class for uploaded objects.\n * Use lower-cost classes for infrequently accessed data.\n */\n storageClass?: SupportedStorageClass;\n\n /**\n * Server-side encryption configuration.\n */\n encryption?: EncryptionConfig;\n\n /**\n * Tags to apply to uploaded objects.\n * Useful for cost allocation and lifecycle policies.\n */\n tags?: Record<string, string>;\n\n /**\n * Multipart upload configuration for large files.\n */\n multipart?: MultipartConfig;\n}\n\nexport interface DefaultOptions extends S3ClientConfig {\n // TODO Remove this in V5\n accessKeyId?: AwsCredentialIdentity['accessKeyId'];\n secretAccessKey?: AwsCredentialIdentity['secretAccessKey'];\n // Keep this for V5\n credentials?: AwsCredentialIdentity;\n params?: AWSParams;\n [k: string]: unknown;\n}\n\nexport type InitOptions = (DefaultOptions | { s3Options: DefaultOptions }) & {\n baseUrl?: string;\n rootPath?: string;\n providerConfig?: ProviderConfig;\n [k: string]: unknown;\n};\n\n/**\n * Validates that a URL uses HTTP or HTTPS protocol.\n * Rejects dangerous protocols like file://, javascript:, data:, etc.\n */\nconst assertUrlProtocol = (url: string) => {\n return /^https?:\\/\\//.test(url);\n};\n\n/**\n * Sanitizes a path component to prevent path traversal attacks.\n * Removes directory traversal sequences and normalizes the path.\n */\nconst sanitizePathComponent = (component: string | undefined): string => {\n if (!component) return '';\n return component\n .replace(/\\.\\./g, '')\n .replace(/^\\/+|\\/+$/g, '')\n .replace(/\\/+/g, '/');\n};\n\n/**\n * Maps the provider checksum algorithm to the AWS SDK checksum algorithm.\n */\nconst mapChecksumAlgorithm = (\n algorithm?: SupportedChecksumAlgorithm\n): ChecksumAlgorithm | undefined => {\n if (!algorithm) return undefined;\n const mapping: Record<SupportedChecksumAlgorithm, ChecksumAlgorithm> = {\n CRC32: ChecksumAlgorithm.CRC32,\n CRC32C: ChecksumAlgorithm.CRC32C,\n SHA1: ChecksumAlgorithm.SHA1,\n SHA256: ChecksumAlgorithm.SHA256,\n CRC64NVME: ChecksumAlgorithm.CRC64NVME,\n };\n return mapping[algorithm];\n};\n\n/**\n * Maps the provider storage class to the AWS SDK storage class.\n */\nconst mapStorageClass = (storageClass?: SupportedStorageClass): StorageClass | undefined => {\n if (!storageClass) return undefined;\n const mapping: Record<SupportedStorageClass, StorageClass> = {\n STANDARD: StorageClass.STANDARD,\n REDUCED_REDUNDANCY: StorageClass.REDUCED_REDUNDANCY,\n STANDARD_IA: StorageClass.STANDARD_IA,\n ONEZONE_IA: StorageClass.ONEZONE_IA,\n INTELLIGENT_TIERING: StorageClass.INTELLIGENT_TIERING,\n GLACIER: StorageClass.GLACIER,\n DEEP_ARCHIVE: StorageClass.DEEP_ARCHIVE,\n GLACIER_IR: StorageClass.GLACIER_IR,\n };\n return mapping[storageClass];\n};\n\n/**\n * Maps the provider encryption type to the AWS SDK server-side encryption.\n */\nconst mapServerSideEncryption = (type?: EncryptionType): ServerSideEncryption | undefined => {\n if (!type) return undefined;\n const mapping: Record<EncryptionType, ServerSideEncryption> = {\n AES256: ServerSideEncryption.AES256,\n 'aws:kms': ServerSideEncryption.aws_kms,\n 'aws:kms:dsse': ServerSideEncryption.aws_kms_dsse,\n };\n return mapping[type];\n};\n\n/**\n * Converts a tags object to the S3 Tagging header format.\n * Format: key1=value1&key2=value2\n */\nconst formatTagsForHeader = (tags?: Record<string, string>): string | undefined => {\n if (!tags || Object.keys(tags).length === 0) return undefined;\n return Object.entries(tags)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&');\n};\n\n/**\n * Checks if the endpoint appears to be a non-AWS S3-compatible provider.\n */\nconst isNonAwsEndpoint = (endpoint?: string): boolean => {\n if (!endpoint) return false;\n const awsPatterns = [/\\.amazonaws\\.com$/i, /\\.amazonaws\\.com\\.cn$/i];\n return !awsPatterns.some((pattern) => pattern.test(endpoint));\n};\n\n/**\n * Validates provider configuration and emits warnings for potential compatibility issues.\n */\nconst validateProviderConfig = (\n providerConfig: ProviderConfig | undefined,\n s3Options: DefaultOptions | undefined\n): void => {\n if (!providerConfig) return;\n\n const endpoint = s3Options?.endpoint?.toString() || '';\n const isNonAws = isNonAwsEndpoint(endpoint);\n\n // Warn about AWS-specific features when using non-AWS endpoints\n if (isNonAws) {\n if (providerConfig.storageClass) {\n process.emitWarning(\n `Storage class '${providerConfig.storageClass}' is AWS S3-specific and may be ignored by your S3-compatible provider.`\n );\n }\n\n if (providerConfig.encryption?.type && providerConfig.encryption.type !== 'AES256') {\n process.emitWarning(\n `Encryption type '${providerConfig.encryption.type}' is AWS S3-specific. Consider using 'AES256' for better compatibility.`\n );\n }\n }\n\n // Validate multipart configuration\n if (providerConfig.multipart?.partSize) {\n const minPartSize = 5 * 1024 * 1024; // 5MB\n const maxPartSize = 5 * 1024 * 1024 * 1024; // 5GB\n\n if (providerConfig.multipart.partSize < minPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} is below the minimum of 5MB. This may cause upload failures.`\n );\n }\n\n if (providerConfig.multipart.partSize > maxPartSize) {\n process.emitWarning(\n `Multipart partSize ${providerConfig.multipart.partSize} exceeds the maximum of 5GB. This may cause upload failures.`\n );\n }\n }\n\n if (providerConfig.multipart?.queueSize && providerConfig.multipart.queueSize > 16) {\n process.emitWarning(\n `Multipart queueSize ${providerConfig.multipart.queueSize} is high and may cause memory issues. Consider using 4-8.`\n );\n }\n};\n\nconst getConfig = ({\n s3Options,\n legacyS3Options,\n}: {\n s3Options: DefaultOptions;\n legacyS3Options: Record<string, unknown>;\n}) => {\n if (Object.keys(legacyS3Options).length > 0) {\n process.emitWarning(\n \"S3 configuration options passed at root level of the plugin's providerOptions is deprecated and will be removed in a future release. Please wrap them inside the 's3Options:{}' property.\"\n );\n }\n const credentials = extractCredentials({ s3Options, ...legacyS3Options });\n const config = {\n ...s3Options,\n ...legacyS3Options,\n ...(credentials ? { credentials } : {}),\n };\n\n if (config.params !== undefined) {\n // Only set default ACL when ACL is not explicitly present in params.\n // Since April 2023, new AWS S3 buckets have ACLs disabled by default\n // (\"Bucket owner enforced\"). Sending an ACL header to such buckets\n // throws AccessControlListNotSupported. To disable ACLs, users should\n // simply not include ACL in their params configuration.\n if (!('ACL' in config.params)) {\n config.params.ACL = ObjectCannedACL.public_read;\n }\n } else {\n throw new Error('Upload AWS S3 provider: `params` are required in the config object');\n }\n\n return config as DefaultOptions & {\n params: AWSParams;\n };\n};\n\nexport default {\n init({ baseUrl, rootPath, s3Options, providerConfig, ...legacyS3Options }: InitOptions) {\n // Validate configuration and emit warnings for potential issues\n validateProviderConfig(providerConfig, s3Options as DefaultOptions);\n\n // TODO V5 change config structure to avoid having to do this\n const config = getConfig({ s3Options: s3Options as DefaultOptions, legacyS3Options });\n const s3Client = new S3Client(config);\n const filePrefix = rootPath ? `${rootPath.replace(/\\/+$/, '')}/` : '';\n\n const getFileKey = (file: File) => {\n const sanitizedPath = sanitizePathComponent(file.path);\n const path = sanitizedPath ? `${sanitizedPath}/` : '';\n const sanitizedHash = sanitizePathComponent(file.hash);\n const sanitizedExt = file.ext ? file.ext.replace(/[^a-zA-Z0-9.]/g, '') : '';\n return `${filePrefix}${path}${sanitizedHash}${sanitizedExt}`;\n };\n\n /**\n * Builds the upload parameters including all configured features.\n */\n const buildUploadParams = (\n file: File,\n fileKey: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ): PutObjectCommandInput => {\n const params: PutObjectCommandInput = {\n Bucket: config.params.Bucket,\n Key: fileKey,\n Body: file.stream || Buffer.from(file.buffer as any, 'binary'),\n // ACL is optional to support providers like Cloudflare R2 that don't support ACLs.\n // Set params.ACL to undefined or omit it entirely to disable ACL headers.\n ...(config.params.ACL ? { ACL: config.params.ACL } : {}),\n ContentType: file.mime,\n };\n\n // Checksum validation\n const checksumAlgorithm = mapChecksumAlgorithm(providerConfig?.checksumAlgorithm);\n if (checksumAlgorithm) {\n params.ChecksumAlgorithm = checksumAlgorithm;\n }\n\n // Conditional writes - prevent overwrite\n if (providerConfig?.preventOverwrite) {\n params.IfNoneMatch = '*';\n }\n\n // Storage class\n const storageClass = mapStorageClass(providerConfig?.storageClass);\n if (storageClass) {\n params.StorageClass = storageClass;\n }\n\n // Server-side encryption\n if (providerConfig?.encryption) {\n const sse = mapServerSideEncryption(providerConfig.encryption.type);\n if (sse) {\n params.ServerSideEncryption = sse;\n if (providerConfig.encryption.kmsKeyId) {\n params.SSEKMSKeyId = providerConfig.encryption.kmsKeyId;\n }\n }\n }\n\n // Object tagging\n const tagging = formatTagsForHeader(providerConfig?.tags);\n if (tagging) {\n params.Tagging = tagging;\n }\n\n // Merge customParams but preserve critical security parameters\n // Bucket, Key, and Body must not be overridden by customParams\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, Body, ...safeCustomParams } = customParams as any;\n return { ...params, ...safeCustomParams };\n };\n\n /**\n * Constructs the correct file URL.\n * Handles S3-compatible providers that return incorrect Location formats.\n */\n const constructFileUrl = (fileKey: string, uploadLocation: string): string => {\n // Priority 1: Use baseUrl if configured (CDN or custom domain)\n if (baseUrl) {\n const cleanBase = baseUrl.replace(/\\/+$/, '');\n return `${cleanBase}/${fileKey}`;\n }\n\n // Priority 2: Construct URL from endpoint if configured\n // This fixes issues with S3-compatible providers (IONOS, MinIO, etc.)\n // that return Location in incorrect format for multipart uploads\n const endpoint = config.endpoint?.toString();\n if (endpoint) {\n const endpointUrl = endpoint.startsWith('http') ? endpoint : `https://${endpoint}`;\n const cleanEndpoint = endpointUrl.replace(/\\/+$/, '');\n return `${cleanEndpoint}/${config.params.Bucket}/${fileKey}`;\n }\n\n // Priority 3: Use the Location from S3 response\n if (assertUrlProtocol(uploadLocation)) {\n return uploadLocation;\n }\n\n // Priority 4: Prepend https if protocol is missing\n return `https://${uploadLocation}`;\n };\n\n const upload = async (file: File, customParams: Partial<PutObjectCommandInput> = {}) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, customParams);\n\n const uploadOptions: {\n client: S3Client;\n params: PutObjectCommandInput;\n partSize?: number;\n queueSize?: number;\n leavePartsOnError?: boolean;\n } = {\n client: s3Client,\n params,\n };\n\n // Multipart configuration\n if (providerConfig?.multipart) {\n if (providerConfig.multipart.partSize) {\n uploadOptions.partSize = providerConfig.multipart.partSize;\n }\n if (providerConfig.multipart.queueSize) {\n uploadOptions.queueSize = providerConfig.multipart.queueSize;\n }\n if (providerConfig.multipart.leavePartsOnError !== undefined) {\n uploadOptions.leavePartsOnError = providerConfig.multipart.leavePartsOnError;\n }\n }\n\n const uploadObj = new Upload(uploadOptions);\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n // Store ETag for potential future conditional updates\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Uploads a file only if the existing object matches the expected ETag.\n * This implements optimistic locking to prevent lost updates.\n */\n const uploadIfMatch = async (\n file: File,\n expectedETag: string,\n customParams: Partial<PutObjectCommandInput> = {}\n ) => {\n const fileKey = getFileKey(file);\n const params = buildUploadParams(file, fileKey, {\n ...customParams,\n IfMatch: expectedETag,\n });\n\n const uploadObj = new Upload({\n client: s3Client,\n params,\n });\n\n const result = (await uploadObj.done()) as UploadCommandOutput;\n\n // Construct the correct URL (handles S3-compatible provider quirks)\n file.url = constructFileUrl(fileKey, result.Location);\n\n if (result.ETag) {\n file.etag = result.ETag.replace(/\"/g, '');\n }\n };\n\n /**\n * Retrieves metadata for an object including its ETag.\n */\n const getObjectMetadata = async (file: File) => {\n const command = new HeadObjectCommand({\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n\n const response = await s3Client.send(command);\n\n return {\n etag: response.ETag?.replace(/\"/g, ''),\n contentLength: response.ContentLength,\n contentType: response.ContentType,\n lastModified: response.LastModified,\n storageClass: response.StorageClass,\n serverSideEncryption: response.ServerSideEncryption,\n };\n };\n\n /**\n * Checks if an object exists in the bucket.\n */\n const objectExists = async (file: File): Promise<boolean> => {\n try {\n await getObjectMetadata(file);\n return true;\n } catch (error: any) {\n if (error.name === 'NotFound' || error.$metadata?.httpStatusCode === 404) {\n return false;\n }\n throw error;\n }\n };\n\n return {\n /**\n * Returns whether the bucket is configured with private ACL.\n */\n isPrivate() {\n return config.params.ACL === 'private';\n },\n\n /**\n * Returns the current provider configuration.\n */\n getProviderConfig(): ProviderConfig | undefined {\n return providerConfig;\n },\n\n /**\n * Generates a signed URL for accessing a private object.\n */\n async getSignedUrl(file: File, customParams: any): Promise<{ url: string }> {\n if (!isUrlFromBucket(file.url, config.params.Bucket, baseUrl)) {\n return { url: file.url };\n }\n const fileKey = getFileKey(file);\n\n // Spread customParams first, then override with secure values\n // This prevents malicious override of Bucket and Key\n const url = await getSignedUrl(\n s3Client,\n new GetObjectCommand({\n ...customParams,\n Bucket: config.params.Bucket,\n Key: fileKey,\n }),\n {\n expiresIn: getOr(15 * 60, ['params', 'signedUrlExpires'], config),\n }\n );\n\n return { url };\n },\n\n /**\n * Uploads a file using streaming.\n */\n uploadStream(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file to S3.\n */\n upload(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n\n /**\n * Uploads a file only if it matches the expected ETag (optimistic locking).\n * Throws PreconditionFailed error if ETag does not match.\n */\n uploadIfMatch(file: File, expectedETag: string, customParams = {}) {\n return uploadIfMatch(file, expectedETag, customParams);\n },\n\n /**\n * Retrieves object metadata including ETag.\n */\n getObjectMetadata(file: File) {\n return getObjectMetadata(file);\n },\n\n /**\n * Checks if an object exists in the bucket.\n */\n objectExists(file: File) {\n return objectExists(file);\n },\n\n /**\n * Deletes an object from S3.\n */\n delete(file: File, customParams = {}): Promise<DeleteObjectCommandOutput> {\n // Spread customParams first, then override with secure values\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { Bucket, Key, ...safeParams } = customParams as any;\n const command = new DeleteObjectCommand({\n ...safeParams,\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n });\n return s3Client.send(command);\n },\n };\n },\n};\n"],"names":["assertUrlProtocol","url","test","sanitizePathComponent","component","replace","mapChecksumAlgorithm","algorithm","undefined","mapping","CRC32","ChecksumAlgorithm","CRC32C","SHA1","SHA256","CRC64NVME","mapStorageClass","storageClass","STANDARD","StorageClass","REDUCED_REDUNDANCY","STANDARD_IA","ONEZONE_IA","INTELLIGENT_TIERING","GLACIER","DEEP_ARCHIVE","GLACIER_IR","mapServerSideEncryption","type","AES256","ServerSideEncryption","aws_kms","aws_kms_dsse","formatTagsForHeader","tags","Object","keys","length","entries","map","key","value","encodeURIComponent","join","isNonAwsEndpoint","endpoint","awsPatterns","some","pattern","validateProviderConfig","providerConfig","s3Options","toString","isNonAws","process","emitWarning","encryption","multipart","partSize","minPartSize","maxPartSize","queueSize","getConfig","legacyS3Options","credentials","extractCredentials","config","params","ACL","ObjectCannedACL","public_read","Error","init","baseUrl","rootPath","s3Client","S3Client","filePrefix","getFileKey","file","sanitizedPath","path","sanitizedHash","hash","sanitizedExt","ext","buildUploadParams","fileKey","customParams","Bucket","Key","Body","stream","Buffer","from","buffer","ContentType","mime","checksumAlgorithm","preventOverwrite","IfNoneMatch","sse","kmsKeyId","SSEKMSKeyId","tagging","Tagging","safeCustomParams","constructFileUrl","uploadLocation","cleanBase","endpointUrl","startsWith","cleanEndpoint","upload","uploadOptions","client","leavePartsOnError","uploadObj","Upload","result","done","Location","ETag","etag","uploadIfMatch","expectedETag","IfMatch","getObjectMetadata","command","HeadObjectCommand","response","send","contentLength","ContentLength","contentType","lastModified","LastModified","serverSideEncryption","objectExists","error","name","$metadata","httpStatusCode","isPrivate","getProviderConfig","getSignedUrl","isUrlFromBucket","GetObjectCommand","expiresIn","getOr","uploadStream","delete","safeParams","DeleteObjectCommand"],"mappings":"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"}
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":["import type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport type { DefaultOptions, InitOptions } from '.';\n\nconst ENDPOINT_PATTERN = /^(.+\\.)?s3[.-]([a-z0-9-]+)\\./;\n\ninterface BucketInfo {\n bucket?: string | null;\n err?: string;\n}\n\nexport function isUrlFromBucket(fileUrl: string, bucketName: string, baseUrl = ''): boolean {\n const url = new URL(fileUrl);\n\n // Check if the file URL is using a base URL (e.g. a CDN).\n // In this case do not sign the URL.\n if (baseUrl) {\n return false;\n }\n\n const { bucket } = getBucketFromAwsUrl(fileUrl);\n\n if (bucket) {\n return bucket === bucketName;\n }\n\n // File URL might be of an S3-compatible provider. (or an invalid URL)\n // In this case, check if the bucket name appears in the URL host or path.\n // e.g. https://minio.example.com/bucket-name/object-key\n // e.g. https://bucket.nyc3.digitaloceanspaces.com/folder/img.png\n return url.host.startsWith(`${bucketName}.`) || url.pathname.includes(`/${bucketName}/`);\n}\n\n/**\n * Parse the bucket name from a URL.\n * See all URL formats in https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html\n *\n * @param {string} fileUrl - the URL to parse\n * @returns {object} result\n * @returns {string} result.bucket - the bucket name\n * @returns {string} result.err - if any\n */\nfunction getBucketFromAwsUrl(fileUrl: string): BucketInfo {\n const url = new URL(fileUrl);\n\n // S3://<bucket-name>/<key>\n if (url.protocol === 's3:') {\n const bucket = url.host;\n\n if (!bucket) {\n return { err: `Invalid S3 url: no bucket: ${url}` };\n }\n return { bucket };\n }\n\n if (!url.host) {\n return { err: `Invalid S3 url: no hostname: ${url}` };\n }\n\n const matches = url.host.match(ENDPOINT_PATTERN);\n if (!matches) {\n return { err: `Invalid S3 url: hostname does not appear to be a valid S3 endpoint: ${url}` };\n }\n\n const prefix = matches[1];\n // https://s3.amazonaws.com/<bucket-name>\n if (!prefix) {\n if (url.pathname === '/') {\n return { bucket: null };\n }\n\n const index = url.pathname.indexOf('/', 1);\n\n // https://s3.amazonaws.com/<bucket-name>\n if (index === -1) {\n return { bucket: url.pathname.substring(1) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/\n if (index === url.pathname.length - 1) {\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/key\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://<bucket-name>.s3.amazonaws.com/\n return { bucket: prefix.substring(0, prefix.length - 1) };\n}\n\nexport const extractCredentials = (options: InitOptions): AwsCredentialIdentity | null => {\n const s3Options = (options as { s3Options?: DefaultOptions }).s3Options;\n\n if (s3Options?.credentials) {\n // Support AWS STS session tokens for temporary credentials\n return {\n accessKeyId: s3Options.credentials.accessKeyId,\n secretAccessKey: s3Options.credentials.secretAccessKey,\n ...(s3Options.credentials.sessionToken\n ? { sessionToken: s3Options.credentials.sessionToken }\n : {}),\n };\n }\n return null;\n};\n"],"names":["ENDPOINT_PATTERN","isUrlFromBucket","fileUrl","bucketName","baseUrl","url","URL","bucket","getBucketFromAwsUrl","host","startsWith","pathname","includes","protocol","err","matches","match","prefix","index","indexOf","substring","length","extractCredentials","options","s3Options","credentials","accessKeyId","secretAccessKey","sessionToken"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":["import type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport type { DefaultOptions, InitOptions } from '.';\n\nconst ENDPOINT_PATTERN = /^(.+\\.)?s3[.-]([a-z0-9-]+)\\./;\n\ninterface BucketInfo {\n bucket?: string | null;\n err?: string;\n}\n\nexport function isUrlFromBucket(fileUrl: string, bucketName: string, baseUrl = ''): boolean {\n const url = new URL(fileUrl);\n\n // Check if the file URL is using a base URL (e.g. a CDN).\n // In this case do not sign the URL.\n if (baseUrl) {\n return false;\n }\n\n const { bucket } = getBucketFromAwsUrl(fileUrl);\n\n if (bucket) {\n return bucket === bucketName;\n }\n\n // File URL might be of an S3-compatible provider. (or an invalid URL)\n // In this case, check if the bucket name appears in the URL host or path.\n // e.g. https://minio.example.com/bucket-name/object-key\n // e.g. https://bucket.nyc3.digitaloceanspaces.com/folder/img.png\n return url.host.startsWith(`${bucketName}.`) || url.pathname.includes(`/${bucketName}/`);\n}\n\n/**\n * Parse the bucket name from a URL.\n * See all URL formats in https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html\n *\n * @param {string} fileUrl - the URL to parse\n * @returns {object} result\n * @returns {string} result.bucket - the bucket name\n * @returns {string} result.err - if any\n */\nfunction getBucketFromAwsUrl(fileUrl: string): BucketInfo {\n const url = new URL(fileUrl);\n\n // S3://<bucket-name>/<key>\n if (url.protocol === 's3:') {\n const bucket = url.host;\n\n if (!bucket) {\n return { err: `Invalid S3 url: no bucket: ${url}` };\n }\n return { bucket };\n }\n\n if (!url.host) {\n return { err: `Invalid S3 url: no hostname: ${url}` };\n }\n\n const matches = url.host.match(ENDPOINT_PATTERN);\n if (!matches) {\n return { err: `Invalid S3 url: hostname does not appear to be a valid S3 endpoint: ${url}` };\n }\n\n const prefix = matches[1];\n // https://s3.amazonaws.com/<bucket-name>\n if (!prefix) {\n if (url.pathname === '/') {\n return { bucket: null };\n }\n\n const index = url.pathname.indexOf('/', 1);\n\n // https://s3.amazonaws.com/<bucket-name>\n if (index === -1) {\n return { bucket: url.pathname.substring(1) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/\n if (index === url.pathname.length - 1) {\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/key\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://<bucket-name>.s3.amazonaws.com/\n return { bucket: prefix.substring(0, prefix.length - 1) };\n}\n\nexport const extractCredentials = (options: InitOptions): AwsCredentialIdentity | null => {\n const s3Options = (options as { s3Options?: DefaultOptions }).s3Options;\n\n if (s3Options?.credentials) {\n // Support AWS STS session tokens for temporary credentials\n return {\n accessKeyId: s3Options.credentials.accessKeyId,\n secretAccessKey: s3Options.credentials.secretAccessKey,\n ...(s3Options.credentials.sessionToken\n ? { sessionToken: s3Options.credentials.sessionToken }\n : {}),\n };\n }\n return null;\n};\n"],"names":["ENDPOINT_PATTERN","isUrlFromBucket","fileUrl","bucketName","baseUrl","url","URL","bucket","getBucketFromAwsUrl","host","startsWith","pathname","includes","protocol","err","matches","match","prefix","index","indexOf","substring","length","extractCredentials","options","s3Options","credentials","accessKeyId","secretAccessKey","sessionToken"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sources":["../src/utils.ts"],"sourcesContent":["import type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport type { DefaultOptions, InitOptions } from '.';\n\nconst ENDPOINT_PATTERN = /^(.+\\.)?s3[.-]([a-z0-9-]+)\\./;\n\ninterface BucketInfo {\n bucket?: string | null;\n err?: string;\n}\n\nexport function isUrlFromBucket(fileUrl: string, bucketName: string, baseUrl = ''): boolean {\n const url = new URL(fileUrl);\n\n // Check if the file URL is using a base URL (e.g. a CDN).\n // In this case do not sign the URL.\n if (baseUrl) {\n return false;\n }\n\n const { bucket } = getBucketFromAwsUrl(fileUrl);\n\n if (bucket) {\n return bucket === bucketName;\n }\n\n // File URL might be of an S3-compatible provider. (or an invalid URL)\n // In this case, check if the bucket name appears in the URL host or path.\n // e.g. https://minio.example.com/bucket-name/object-key\n // e.g. https://bucket.nyc3.digitaloceanspaces.com/folder/img.png\n return url.host.startsWith(`${bucketName}.`) || url.pathname.includes(`/${bucketName}/`);\n}\n\n/**\n * Parse the bucket name from a URL.\n * See all URL formats in https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html\n *\n * @param {string} fileUrl - the URL to parse\n * @returns {object} result\n * @returns {string} result.bucket - the bucket name\n * @returns {string} result.err - if any\n */\nfunction getBucketFromAwsUrl(fileUrl: string): BucketInfo {\n const url = new URL(fileUrl);\n\n // S3://<bucket-name>/<key>\n if (url.protocol === 's3:') {\n const bucket = url.host;\n\n if (!bucket) {\n return { err: `Invalid S3 url: no bucket: ${url}` };\n }\n return { bucket };\n }\n\n if (!url.host) {\n return { err: `Invalid S3 url: no hostname: ${url}` };\n }\n\n const matches = url.host.match(ENDPOINT_PATTERN);\n if (!matches) {\n return { err: `Invalid S3 url: hostname does not appear to be a valid S3 endpoint: ${url}` };\n }\n\n const prefix = matches[1];\n // https://s3.amazonaws.com/<bucket-name>\n if (!prefix) {\n if (url.pathname === '/') {\n return { bucket: null };\n }\n\n const index = url.pathname.indexOf('/', 1);\n\n // https://s3.amazonaws.com/<bucket-name>\n if (index === -1) {\n return { bucket: url.pathname.substring(1) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/\n if (index === url.pathname.length - 1) {\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/key\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://<bucket-name>.s3.amazonaws.com/\n return { bucket: prefix.substring(0, prefix.length - 1) };\n}\n\nexport const extractCredentials = (options: InitOptions): AwsCredentialIdentity | null => {\n const s3Options = (options as { s3Options?: DefaultOptions }).s3Options;\n\n if (s3Options?.credentials) {\n // Support AWS STS session tokens for temporary credentials\n return {\n accessKeyId: s3Options.credentials.accessKeyId,\n secretAccessKey: s3Options.credentials.secretAccessKey,\n ...(s3Options.credentials.sessionToken\n ? { sessionToken: s3Options.credentials.sessionToken }\n : {}),\n };\n }\n return null;\n};\n"],"names":["ENDPOINT_PATTERN","isUrlFromBucket","fileUrl","bucketName","baseUrl","url","URL","bucket","getBucketFromAwsUrl","host","startsWith","pathname","includes","protocol","err","matches","match","prefix","index","indexOf","substring","length","extractCredentials","options","s3Options","credentials","accessKeyId","secretAccessKey","sessionToken"],"mappings":"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"}
1
+ {"version":3,"file":"utils.mjs","sources":["../src/utils.ts"],"sourcesContent":["import type { AwsCredentialIdentity } from '@aws-sdk/types';\nimport type { DefaultOptions, InitOptions } from '.';\n\nconst ENDPOINT_PATTERN = /^(.+\\.)?s3[.-]([a-z0-9-]+)\\./;\n\ninterface BucketInfo {\n bucket?: string | null;\n err?: string;\n}\n\nexport function isUrlFromBucket(fileUrl: string, bucketName: string, baseUrl = ''): boolean {\n const url = new URL(fileUrl);\n\n // Check if the file URL is using a base URL (e.g. a CDN).\n // In this case do not sign the URL.\n if (baseUrl) {\n return false;\n }\n\n const { bucket } = getBucketFromAwsUrl(fileUrl);\n\n if (bucket) {\n return bucket === bucketName;\n }\n\n // File URL might be of an S3-compatible provider. (or an invalid URL)\n // In this case, check if the bucket name appears in the URL host or path.\n // e.g. https://minio.example.com/bucket-name/object-key\n // e.g. https://bucket.nyc3.digitaloceanspaces.com/folder/img.png\n return url.host.startsWith(`${bucketName}.`) || url.pathname.includes(`/${bucketName}/`);\n}\n\n/**\n * Parse the bucket name from a URL.\n * See all URL formats in https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html\n *\n * @param {string} fileUrl - the URL to parse\n * @returns {object} result\n * @returns {string} result.bucket - the bucket name\n * @returns {string} result.err - if any\n */\nfunction getBucketFromAwsUrl(fileUrl: string): BucketInfo {\n const url = new URL(fileUrl);\n\n // S3://<bucket-name>/<key>\n if (url.protocol === 's3:') {\n const bucket = url.host;\n\n if (!bucket) {\n return { err: `Invalid S3 url: no bucket: ${url}` };\n }\n return { bucket };\n }\n\n if (!url.host) {\n return { err: `Invalid S3 url: no hostname: ${url}` };\n }\n\n const matches = url.host.match(ENDPOINT_PATTERN);\n if (!matches) {\n return { err: `Invalid S3 url: hostname does not appear to be a valid S3 endpoint: ${url}` };\n }\n\n const prefix = matches[1];\n // https://s3.amazonaws.com/<bucket-name>\n if (!prefix) {\n if (url.pathname === '/') {\n return { bucket: null };\n }\n\n const index = url.pathname.indexOf('/', 1);\n\n // https://s3.amazonaws.com/<bucket-name>\n if (index === -1) {\n return { bucket: url.pathname.substring(1) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/\n if (index === url.pathname.length - 1) {\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://s3.amazonaws.com/<bucket-name>/key\n return { bucket: url.pathname.substring(1, index) };\n }\n\n // https://<bucket-name>.s3.amazonaws.com/\n return { bucket: prefix.substring(0, prefix.length - 1) };\n}\n\nexport const extractCredentials = (options: InitOptions): AwsCredentialIdentity | null => {\n const s3Options = (options as { s3Options?: DefaultOptions }).s3Options;\n\n if (s3Options?.credentials) {\n // Support AWS STS session tokens for temporary credentials\n return {\n accessKeyId: s3Options.credentials.accessKeyId,\n secretAccessKey: s3Options.credentials.secretAccessKey,\n ...(s3Options.credentials.sessionToken\n ? { sessionToken: s3Options.credentials.sessionToken }\n : {}),\n };\n }\n return null;\n};\n"],"names":["ENDPOINT_PATTERN","isUrlFromBucket","fileUrl","bucketName","baseUrl","url","URL","bucket","getBucketFromAwsUrl","host","startsWith","pathname","includes","protocol","err","matches","match","prefix","index","indexOf","substring","length","extractCredentials","options","s3Options","credentials","accessKeyId","secretAccessKey","sessionToken"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/provider-upload-aws-s3",
3
- "version": "5.37.1",
3
+ "version": "5.38.1",
4
4
  "description": "AWS S3 provider for strapi upload",
5
5
  "keywords": [
6
6
  "upload",
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "repository": {
16
16
  "type": "git",
17
- "url": "git://github.com/strapi/strapi.git"
17
+ "url": "git://github.com/strapi/strapi.git",
18
+ "directory": "packages/providers/upload-aws-s3"
18
19
  },
19
20
  "license": "SEE LICENSE IN LICENSE",
20
21
  "author": {
@@ -55,8 +56,8 @@
55
56
  },
56
57
  "devDependencies": {
57
58
  "@types/jest": "29.5.2",
58
- "eslint-config-custom": "5.37.1",
59
- "tsconfig": "5.37.1"
59
+ "eslint-config-custom": "5.38.1",
60
+ "tsconfig": "5.38.1"
60
61
  },
61
62
  "engines": {
62
63
  "node": ">=20.0.0 <=24.x.x",