rollup-plugin-google-cloud-storage
Version:
Uploads build assets to a bucket on Google Cloud Storage
105 lines (86 loc) • 2.65 kB
JavaScript
import { readdir } from "node:fs/promises";
import { Storage } from "@google-cloud/storage";
import ora from "ora";
import pLimit from "p-limit";
import { z } from "zod";
async function getFilenamesForDirectory(directory) {
const files = await readdir(directory, {
recursive: true,
withFileTypes: true,
});
return files
.filter((dirent) => dirent.isFile())
.map((file) => `${file.parentPath}/${file.name}`);
}
async function uploadToBucketFromDirectory(spinner, options) {
const { serviceKeyJson, bucketName, concurrency, directory, skipIfExists } =
options;
const limit = pLimit(concurrency);
let credentials = serviceKeyJson;
if (typeof credentials === "string") {
credentials = JSON.parse(credentials);
}
const storage = new Storage({ credentials });
function uploadFile(filePath) {
return storage.bucket(bucketName).upload(filePath, {
destination: filePath.replace(`${directory}/`, ""),
...(skipIfExists
? {
preconditionOpts: {
ifGenerationMatch: 0,
},
}
: {}),
});
}
let uploaded = 0;
let skipped = 0;
const files = await getFilenamesForDirectory(directory);
const promises = files.map((file) =>
limit(() =>
uploadFile(file)
.then(() => {
uploaded += 1;
// eslint-disable-next-line no-param-reassign
spinner.text = `uploaded ${file}`;
})
.catch(() => {
skipped += 1;
// eslint-disable-next-line no-param-reassign
spinner.text = `skipped ${file}`;
})
)
);
await Promise.all(promises);
return { uploaded, skipped };
}
export default function googleCloudStorageSync(options) {
const Options = z.object({
directory: z.string().default("dist"),
bucketName: z.string(),
serviceKeyJson: z.union([z.string(), z.object()]),
concurrency: z.number().default(5),
skipIfExists: z.boolean().default(true),
});
return {
name: "google-cloud-storage",
writeBundle: async () => {
const parsedOptions = Options.parse(options);
const spinner = ora(
`Uploading files from ${parsedOptions.directory} to ${parsedOptions.bucketName}`
).start();
try {
const { uploaded, skipped } = await uploadToBucketFromDirectory(
spinner,
parsedOptions
);
spinner.succeed(`${uploaded} files uploaded, ${skipped} skipped`);
} catch (error) {
spinner.fail(
"Something went wrong uploading the files to Google Cloud Storage"
);
throw error;
}
},
};
}