UNPKG

@strapi-community/strapi-provider-upload-google-cloud-storage

Version:
1 lines 25.8 kB
{"version":3,"file":"index.mjs","sources":["../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { FileMetadata } from '@google-cloud/storage';\nimport type { ReadStream } from 'node:fs';\nimport path from 'node:path';\nimport slugify from 'slugify';\nimport { z } from 'zod';\n\nconst fileSchema = z.object({\n name: z.string(),\n alternativeText: z.string().optional(),\n caption: z.string().optional(),\n width: z.number().optional(),\n height: z.number().optional(),\n formats: z.record(z.string(), z.unknown()).optional(),\n hash: z.string(),\n ext: z.string().optional(),\n mime: z.string(),\n size: z.number(),\n sizeInBytes: z.number(),\n url: z.string(),\n previewUrl: z.string().optional(),\n path: z.string().optional(),\n provider: z.string().optional(),\n provider_metadata: z.record(z.string(), z.unknown()).optional(),\n stream: z.unknown().optional(), // `ReadStream` can't be validated easily, so `any` or skip\n buffer: z.unknown().optional(), // same for `Buffer`\n});\n\nexport type File = z.infer<typeof fileSchema> & {\n stream?: ReadStream;\n buffer?: Buffer;\n};\n\nexport type FileAttributes = {\n contentType: string;\n gzip: Options['gzip'];\n metadata: FileMetadata;\n public?: boolean;\n};\n\nexport const serviceAccountSchema = z.object({\n project_id: z.string({\n error: (issue) =>\n issue.input === undefined\n ? 'Error parsing data \"Service Account JSON\". Missing \"project_id\" field in JSON file.'\n : 'Error parsing data \"Service Account JSON\". Property \"project_id\" must be a string.',\n }),\n client_email: z.string({\n error: (issue) =>\n issue.input === undefined\n ? 'Error parsing data \"Service Account JSON\". Missing \"client_email\" field in JSON file.'\n : 'Error parsing data \"Service Account JSON\". Property \"client_email\" must be a string.',\n }),\n private_key: z.string({\n error: (issue) =>\n issue.input === undefined\n ? 'Error parsing data \"Service Account JSON\". Missing \"private_key\" field in JSON file.'\n : 'Error parsing data \"Service Account JSON\". Property \"private_key\" must be a string.',\n }),\n});\n\nexport type ServiceAccount = z.infer<typeof serviceAccountSchema>;\n\ntype MetadataFn = (file: File) => FileMetadata;\ntype GetContentTypeFn = (file: File) => string;\ntype GenerateUploadFileNameFn = (basePath: string, file: File) => Promise<string> | string;\n\nconst defaultGetContentType = (file: File) => file.mime;\n\nconst defaultGenerateUploadFileName = (basePath: string, file: File) => {\n const filePath = `${file.path ? file.path.slice(1) : file.hash}/`;\n const extension = file.ext?.toLowerCase() || '';\n const fileName = slugify(path.basename(file.hash));\n return `${basePath}${filePath}${fileName}${extension}`;\n};\n\nexport const optionsSchema = z.object({\n serviceAccount: z\n .preprocess((input) => {\n if (typeof input === 'string') {\n try {\n return JSON.parse(input);\n } catch {\n throw new Error(\n 'Error parsing data \"Service Account JSON\", please be sure to copy/paste the full JSON file.'\n );\n }\n }\n return input;\n }, serviceAccountSchema)\n .optional(),\n bucketName: z.string({\n error: (issue) =>\n issue.input === undefined\n ? 'Property \"bucketName\" is required'\n : 'Property \"bucketName\" must be a string',\n }),\n baseUrl: z.string().default('https://storage.googleapis.com/{bucket-name}'),\n basePath: z.string().default(''),\n publicFiles: z.boolean().or(z.stringbool()).default(true),\n uniform: z.boolean().or(z.stringbool()).default(false),\n skipCheckBucket: z.boolean().or(z.stringbool()).default(false),\n gzip: z.boolean().or(z.stringbool()).or(z.literal('auto')).default('auto'),\n cacheMaxAge: z.number().default(3600),\n expires: z\n .union([\n z.string(),\n z.date(),\n z\n .number()\n .min(0)\n .max(1000 * 60 * 60 * 24 * 7),\n ])\n .default(15 * 60 * 1000),\n metadata: z.custom<MetadataFn>((val) => typeof val === 'function').optional(),\n getContentType: z\n .custom<GetContentTypeFn>((val) => typeof val === 'function')\n .optional()\n .default(() => defaultGetContentType),\n generateUploadFileName: z\n .custom<GenerateUploadFileNameFn>((val) => typeof val === 'function')\n .optional()\n .default(() => defaultGenerateUploadFileName),\n});\n\nexport type Options = z.infer<typeof optionsSchema>;\n\nexport type DefaultOptions = Partial<Omit<Options, 'serviceAccount' | 'bucketName'>> & {\n bucketName: string;\n serviceAccount?: ServiceAccount | string;\n};\n","import type { Bucket, Storage } from '@google-cloud/storage';\nimport z from 'zod';\nimport {\n optionsSchema,\n type DefaultOptions,\n type File,\n type FileAttributes,\n type Options,\n} from './types';\n\nexport const getConfigDefaultValues = (config: DefaultOptions) => {\n try {\n const parsedConfig = optionsSchema.parse(config);\n\n // If no custom metadata function is provided, use the default one with the configured cacheMaxAge\n if (!config.metadata) {\n const defaultGetMetadata = (cacheMaxAge: number) => (file: File) => {\n const asciiFileName = file.name.normalize('NFKD').replace(/[\\u0300-\\u036f]/g, '');\n return {\n contentDisposition: `inline; filename=\"${asciiFileName}\"`,\n cacheControl: `public, max-age=${cacheMaxAge}`,\n };\n };\n parsedConfig.metadata = defaultGetMetadata(parsedConfig.cacheMaxAge);\n }\n\n return parsedConfig;\n } catch (err) {\n if (err instanceof z.ZodError) {\n throw new Error(err.issues[0]?.message);\n } else {\n throw err;\n }\n }\n};\n\nexport const getExpires = (expires: Date | number | string) => {\n if (typeof expires === 'number') {\n return Date.now() + expires;\n }\n return expires;\n};\n\nexport const checkBucket = async (bucket: Bucket, bucketName: string) => {\n const [exists] = await bucket.exists();\n if (!exists) {\n throw new Error(\n `An error occurs when we try to retrieve the Bucket \"${bucketName}\". Check if bucket exist on Google Cloud Platform.`\n );\n }\n};\n\nexport const prepareUploadFile = async (\n file: File,\n config: Options,\n basePath: string,\n GCS: Storage\n) => {\n const fullFileName = await config.generateUploadFileName(basePath, file);\n const bucket = GCS.bucket(config.bucketName);\n if (!config.skipCheckBucket) {\n await checkBucket(bucket, config.bucketName);\n }\n\n const bucketFile = bucket.file(fullFileName);\n const [fileExists] = await bucketFile.exists();\n\n const fileAttributes: FileAttributes = {\n contentType: config.getContentType(file),\n gzip: config.gzip,\n metadata: config.metadata!(file),\n };\n\n if (!config.uniform) {\n fileAttributes.public = config.publicFiles;\n }\n\n return { fileAttributes, bucketFile, fullFileName, fileExists };\n};\n","import type { GetSignedUrlConfig } from '@google-cloud/storage';\nimport { Storage } from '@google-cloud/storage';\nimport { pipeline } from 'node:stream/promises';\nimport type { DefaultOptions, File } from './types';\nimport { getConfigDefaultValues, getExpires, prepareUploadFile } from './utils';\n\nexport default {\n init(providedConfig: DefaultOptions) {\n const config = getConfigDefaultValues(providedConfig);\n const { serviceAccount } = config;\n\n const GCS = new Storage(\n serviceAccount && {\n projectId: serviceAccount.project_id,\n credentials: {\n client_email: serviceAccount.client_email,\n private_key: serviceAccount.private_key,\n },\n }\n );\n\n const basePath = `${config.basePath}/`.replace(/^\\/+/, '');\n const baseUrl = config.baseUrl.replace('{bucket-name}', config.bucketName);\n\n return {\n async upload(file: File) {\n try {\n const { fileAttributes, bucketFile, fullFileName, fileExists } = await prepareUploadFile(\n file,\n config,\n basePath,\n GCS\n );\n if (fileExists) {\n await this.delete(file);\n }\n\n if (file.buffer) {\n await bucketFile.save(file.buffer, fileAttributes);\n file.url = `${baseUrl}/${fullFileName}`;\n file.mime = fileAttributes.contentType;\n }\n } catch (error) {\n if (error instanceof Error && 'message' in error) {\n console.error(`Error uploading file to Google Cloud Storage: ${error.message}`);\n }\n throw error;\n }\n },\n async uploadStream(file: File) {\n try {\n const { fileAttributes, bucketFile, fullFileName, fileExists } = await prepareUploadFile(\n file,\n config,\n basePath,\n GCS\n );\n if (fileExists) {\n await this.delete(file);\n }\n\n if (file.stream) {\n await pipeline(file.stream, bucketFile.createWriteStream(fileAttributes));\n file.url = `${baseUrl}/${fullFileName}`;\n file.mime = fileAttributes.contentType;\n }\n } catch (error) {\n if (error instanceof Error && 'message' in error) {\n console.error(`Error uploading file to Google Cloud Storage: ${error.message}`);\n }\n throw error;\n }\n },\n async delete(file: File) {\n if (!file.url) {\n return;\n }\n\n const fileName = file.url.replace(`${baseUrl}/`, '');\n const bucket = GCS.bucket(config.bucketName);\n try {\n await bucket.file(fileName).delete();\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 404) {\n throw new Error('Remote file was not found, you may have to delete manually.');\n }\n throw error;\n }\n },\n isPrivate() {\n return !config.publicFiles;\n },\n async getSignedUrl(file: File) {\n try {\n // First, try to generate signed URL - this works with ADC in GCP environments\n const options: GetSignedUrlConfig = {\n version: 'v4',\n action: 'read',\n expires: getExpires(config.expires),\n };\n const fileName = file.url.replace(`${baseUrl}/`, '');\n const [url] = await GCS.bucket(config.bucketName).file(fileName).getSignedUrl(options);\n return { url };\n } catch (error) {\n // If signing fails, check if this is a credentials issue\n if (error instanceof Error && error.message.includes('Cannot sign data without')) {\n // Check if we're in a GCP environment where ADC should work\n const isGCPEnvironment = this.detectGCPEnvironment();\n\n if (!isGCPEnvironment && (!serviceAccount || !serviceAccount.client_email)) {\n // Non-GCP environment requires explicit service account credentials\n if (!config.publicFiles) {\n throw new Error(\n 'Cannot generate signed URLs without service account credentials. ' +\n 'Either:\\n' +\n '1. Provide serviceAccount with client_email and private_key in your configuration, or\\n' +\n '2. Set publicFiles to true to use direct URLs instead of signed URLs.\\n' +\n 'For more information, see: https://github.com/strapi-community/strapi-provider-upload-google-cloud-storage#setting-up-google-authentication'\n );\n }\n\n // Fallback to direct URL for public files in non-GCP environments\n console.warn(\n 'Warning: Cannot generate signed URL without service account credentials. ' +\n 'Returning direct URL instead. This works only for public files.'\n );\n return { url: file.url };\n }\n\n // For GCP environments, provide more specific error message\n if (isGCPEnvironment) {\n throw new Error(\n `Failed to generate signed URL in GCP environment: ${error.message}\\n` +\n 'This may indicate that your GCP service account lacks the necessary permissions for URL signing. ' +\n 'Please ensure your service account has the \"Storage Object Admin\" or \"Storage Admin\" role.'\n );\n }\n\n // Fallback error for other cases\n throw new Error(\n `Failed to generate signed URL: ${error.message}\\n` +\n 'This usually means your service account credentials are incomplete. ' +\n 'Please ensure your serviceAccount configuration includes both client_email and private_key fields.'\n );\n }\n\n // Re-throw other errors as-is\n throw error;\n }\n },\n\n detectGCPEnvironment() {\n // Check common GCP environment variables\n const gcpEnvVars = [\n 'GOOGLE_CLOUD_PROJECT',\n 'GCLOUD_PROJECT',\n 'GAE_APPLICATION', // App Engine\n 'GAE_SERVICE', // App Engine\n 'K_SERVICE', // Cloud Run\n 'FUNCTION_NAME', // Cloud Functions\n 'FUNCTION_TARGET', // Cloud Functions\n ];\n\n // Check if we're running in a GCP environment\n const hasGCPEnvVar = gcpEnvVars.some((envVar) => process.env[envVar]);\n\n // Additional check for Google metadata server (available in GCP environments)\n const hasGoogleMetadata =\n process.env.GCE_METADATA_HOST || process.env.KUBERNETES_SERVICE_HOST; // GKE\n\n return hasGCPEnvVar || !!hasGoogleMetadata;\n },\n };\n },\n};\n"],"names":["z","object","name","string","alternativeText","optional","caption","width","number","height","formats","record","unknown","hash","ext","mime","size","sizeInBytes","url","previewUrl","path","provider","provider_metadata","stream","buffer","serviceAccountSchema","project_id","error","issue","input","undefined","client_email","private_key","defaultGetContentType","file","defaultGenerateUploadFileName","basePath","filePath","slice","extension","toLowerCase","fileName","slugify","basename","optionsSchema","serviceAccount","preprocess","JSON","parse","Error","bucketName","baseUrl","default","publicFiles","boolean","or","stringbool","uniform","skipCheckBucket","gzip","literal","cacheMaxAge","expires","union","date","min","max","metadata","custom","val","getContentType","generateUploadFileName","getConfigDefaultValues","config","parsedConfig","defaultGetMetadata","asciiFileName","normalize","replace","contentDisposition","cacheControl","err","ZodError","issues","message","getExpires","Date","now","checkBucket","bucket","exists","prepareUploadFile","GCS","fullFileName","bucketFile","fileExists","fileAttributes","contentType","public","init","providedConfig","Storage","projectId","credentials","upload","delete","save","console","uploadStream","pipeline","createWriteStream","code","isPrivate","getSignedUrl","options","version","action","includes","isGCPEnvironment","detectGCPEnvironment","warn","gcpEnvVars","hasGCPEnvVar","some","envVar","process","env","hasGoogleMetadata","GCE_METADATA_HOST","KUBERNETES_SERVICE_HOST"],"mappings":"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"}