@npio/filesystem
Version:
A free visual website editor, powered with your own SolidJS components.
99 lines (89 loc) • 2.85 kB
text/typescript
import * as Minio from "minio";
import { Driver } from "../types";
import { commonCacheAge, isFont, maxCacheAge, promisifyStream } from "../utils";
export type S3Options = {
endpoint: string;
publicUrl?: string;
port?: number;
useSSL?: boolean;
accessKey: string;
secretKey: string;
publicBucket?: string;
privateBucket?: string;
};
export const createS3 = (opts: S3Options) => {
const useSSL = opts.useSSL ?? true;
const port = opts.port ?? (useSSL ? 443 : 80);
const options = {
...opts,
port,
useSSL,
publicBucket: opts.publicBucket ?? "public",
privateBucket: opts.privateBucket ?? "private",
};
const client = new Minio.Client({
endPoint: options.endpoint,
port: options.port,
useSSL: options.useSSL,
accessKey: options.accessKey,
secretKey: options.secretKey,
});
const publicUrl =
options.publicUrl ||
`http${options.useSSL ? "s" : ""}://${options.endpoint}:${options.port}/`;
return {
async get(params) {
const bucket = params.private
? options.privateBucket
: options.publicBucket;
try {
const object = await client.statObject(bucket, params.name);
return {
lastModified: object.lastModified,
size: object.size,
stream: () => client.getObject(bucket, params.name),
};
} catch (err) {}
},
async deleteDir(params) {
const bucket = params.private
? options.privateBucket
: options.publicBucket;
// listObjects doesnt like if the name starts with the /
const name = params.name.startsWith("/")
? params.name.slice(1)
: params.name;
const objects = await client.listObjects(bucket, name, true).toArray();
await client.removeObjects(bucket, objects);
},
async delete(params) {
const bucket = params.private
? options.privateBucket
: options.publicBucket;
await client.removeObject(bucket, params.name);
},
publicUrl() {
return publicUrl + options.publicBucket + "/";
},
async put(params) {
const bucket = params.private
? options.privateBucket
: options.publicBucket;
const maxAge = isFont(params.name) ? maxCacheAge : commonCacheAge;
try {
const [result] = await Promise.all([
client.putObject(bucket, params.name, params.stream, params.size, {
"Content-Type": params.contentType,
"Cache-Control": `public, max-age=${maxAge}`,
}),
promisifyStream(params.stream),
]);
} catch (error) {
// Cleanup incomplete files
// Doesnt seem to be necessary with minio, here be dragons
// await this.delete(params);
throw new Error("Failed to save the file: " + error);
}
},
} satisfies Driver;
};