Skip to content

Instantly share code, notes, and snippets.

@erfanium
Created July 2, 2024 10:02
Show Gist options
  • Save erfanium/ebc49c288f41be2dbf5be60278642792 to your computer and use it in GitHub Desktop.
Save erfanium/ebc49c288f41be2dbf5be60278642792 to your computer and use it in GitHub Desktop.
bucket url pattern
import {
BucketItem,
BucketStream,
Client,
ItemBucketMetadata,
RemoveOptions,
UploadedObjectInfo,
} from 'minio';
import pino from 'pino';
import { Readable } from 'stream';
const logger = pino({
name: 's3',
});
const { ENSURE_BUCKETS } = process.env;
const enableEnsure = ENSURE_BUCKETS === 'true';
export interface Bucket {
name: string;
getObject(objectName: string): Promise<Readable>;
putObject(
objectName: string,
stream: Readable | Buffer | string,
metaData?: ItemBucketMetadata,
): Promise<UploadedObjectInfo>;
removeObject(objectName: string, removeOpts?: RemoveOptions): Promise<void>;
listObjects(prefix?: string, recursive?: boolean): BucketStream<BucketItem>;
ensure(): Promise<void>;
exists(): Promise<boolean>;
setPolicy(bucketPolicy: string): Promise<void>;
remove(): Promise<void>;
make(): Promise<void>;
}
const cache = new Map<string, Bucket>();
const createNullBucket = (name: string, envName: string): Bucket => {
return {
name,
getObject() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
putObject() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
removeObject() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
listObjects() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
setPolicy() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
ensure() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
exists() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
remove() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
make() {
throw new Error(`bucket not initialized. please set ${envName} env`);
},
};
};
export async function ensureBucket(client: Client, bucketName: string) {
const exists = await client.bucketExists(bucketName);
if (!exists) {
await client.makeBucket(bucketName);
}
}
export const getBucket = (name: string, envName: string): Bucket => {
const fromCache = cache.get(envName);
if (fromCache) return fromCache;
const _url: string | undefined = process.env[envName];
if (!_url) return createNullBucket(name, envName);
const url = new URL(_url);
const client = new Client({
endPoint: url.hostname,
port: url.port ? Number(url.port) : 9000,
useSSL: url.protocol.startsWith('https'),
accessKey: decodeURIComponent(url.username),
secretKey: decodeURIComponent(url.password),
});
const bucketName = url.pathname.replace('/', '');
const bucket: Bucket = {
name,
getObject: (objectName) => client.getObject(bucketName, objectName),
putObject: (...rest) => client.putObject(bucketName, ...rest),
removeObject: (...rest) => client.removeObject(bucketName, ...rest),
listObjects: (...rest) => client.listObjects(bucketName, ...rest),
setPolicy: (...rest) => client.setBucketPolicy(bucketName, ...rest),
ensure: () => ensureBucket(client, bucketName),
exists: () => client.bucketExists(bucketName),
remove: () => client.removeBucket(bucketName),
make: () => client.makeBucket(bucketName),
};
// do not await this
if (enableEnsure) {
bucket
.ensure()
.catch((e) => logger.error(e, `Error while ensureBucket for ${envName}`));
}
cache.set(envName, bucket);
return bucket;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment