@strapi/provider-upload-aws-s3
Version:
AWS S3 provider for strapi upload
1 lines • 9.52 kB
Source Map (JSON)
{"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 PutObjectCommandInput,\n CompleteMultipartUploadCommandOutput,\n AbortMultipartUploadCommandOutput,\n S3ClientConfig,\n ObjectCannedACL,\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\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}\n\nexport type UploadCommandOutput = (\n | CompleteMultipartUploadCommandOutput\n | AbortMultipartUploadCommandOutput\n) & {\n Location: string;\n};\n\nexport interface AWSParams {\n Bucket: string; // making it required\n ACL?: ObjectCannedACL;\n signedUrlExpires?: number;\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]: any;\n}\n\nexport type InitOptions = (DefaultOptions | { s3Options: DefaultOptions }) & {\n baseUrl?: string;\n rootPath?: string;\n [k: string]: any;\n};\n\nconst assertUrlProtocol = (url: string) => {\n // Regex to test protocol like \"http://\", \"https://\"\n return /^\\w*:\\/\\//.test(url);\n};\n\nconst getConfig = ({ baseUrl, rootPath, s3Options, ...legacyS3Options }: InitOptions) => {\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 config.params.ACL = getOr(ObjectCannedACL.public_read, ['params', 'ACL'], config);\n\n return config;\n};\n\nexport default {\n init({ baseUrl, rootPath, s3Options, ...legacyS3Options }: InitOptions) {\n // TODO V5 change config structure to avoid having to do this\n const config = getConfig({ baseUrl, rootPath, s3Options, ...legacyS3Options });\n const s3Client = new S3Client(config);\n const filePrefix = rootPath ? `${rootPath.replace(/\\/+$/, '')}/` : '';\n\n const getFileKey = (file: File) => {\n const path = file.path ? `${file.path}/` : '';\n return `${filePrefix}${path}${file.hash}${file.ext}`;\n };\n\n const upload = async (file: File, customParams: Partial<PutObjectCommandInput> = {}) => {\n const fileKey = getFileKey(file);\n const uploadObj = new Upload({\n client: s3Client,\n params: {\n Bucket: config.params.Bucket,\n Key: fileKey,\n Body: file.stream || Buffer.from(file.buffer as any, 'binary'),\n ACL: config.params.ACL,\n ContentType: file.mime,\n ...customParams,\n },\n });\n\n const upload = (await uploadObj.done()) as UploadCommandOutput;\n\n if (assertUrlProtocol(upload.Location)) {\n file.url = baseUrl ? `${baseUrl}/${fileKey}` : upload.Location;\n } else {\n // Default protocol to https protocol\n file.url = `https://${upload.Location}`;\n }\n };\n\n return {\n isPrivate() {\n return config.params.ACL === 'private';\n },\n\n async getSignedUrl(file: File, customParams: any): Promise<{ url: string }> {\n // Do not sign the url if it does not come from the same bucket.\n if (!isUrlFromBucket(file.url, config.params.Bucket, baseUrl)) {\n return { url: file.url };\n }\n const fileKey = getFileKey(file);\n\n const url = await getSignedUrl(\n // @ts-expect-error - TODO fix client type\n s3Client,\n new GetObjectCommand({\n Bucket: config.params.Bucket,\n Key: fileKey,\n ...customParams,\n }),\n {\n expiresIn: getOr(15 * 60, ['params', 'signedUrlExpires'], config),\n }\n );\n\n return { url };\n },\n uploadStream(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n upload(file: File, customParams = {}) {\n return upload(file, customParams);\n },\n delete(file: File, customParams = {}): Promise<DeleteObjectCommandOutput> {\n const command = new DeleteObjectCommand({\n Bucket: config.params.Bucket,\n Key: getFileKey(file),\n ...customParams,\n });\n return s3Client.send(command);\n },\n };\n },\n};\n"],"names":["assertUrlProtocol","url","test","getConfig","baseUrl","rootPath","s3Options","legacyS3Options","Object","keys","length","process","emitWarning","credentials","extractCredentials","config","params","ACL","getOr","ObjectCannedACL","public_read","init","s3Client","S3Client","filePrefix","replace","getFileKey","file","path","hash","ext","upload","customParams","fileKey","uploadObj","Upload","client","Bucket","Key","Body","stream","Buffer","from","buffer","ContentType","mime","done","Location","isPrivate","getSignedUrl","isUrlFromBucket","GetObjectCommand","expiresIn","uploadStream","delete","command","DeleteObjectCommand","send"],"mappings":"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"}