148 lines
4.1 KiB
TypeScript
148 lines
4.1 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { Agent as HttpsAgent } from 'node:https';
|
|
import { Client } from 'minio';
|
|
|
|
type MinioTarget = {
|
|
endPoint: string;
|
|
port: number;
|
|
useSSL: boolean;
|
|
origin: string;
|
|
};
|
|
|
|
const parseBoolean = (value: string | undefined, fallback: boolean): boolean => {
|
|
if (value == null || value.trim() === '') {
|
|
return fallback;
|
|
}
|
|
|
|
return value.toLowerCase() === 'true';
|
|
};
|
|
|
|
const resolveMinioTarget = ({
|
|
origin,
|
|
endpoint,
|
|
port,
|
|
useSSL,
|
|
}: {
|
|
origin?: string;
|
|
endpoint?: string;
|
|
port?: string | number;
|
|
useSSL: boolean;
|
|
}): MinioTarget => {
|
|
const rawOrigin = origin?.trim();
|
|
|
|
if (rawOrigin) {
|
|
const url = new URL(rawOrigin);
|
|
const targetUseSSL = url.protocol === 'https:';
|
|
const targetPort = Number(url.port || (targetUseSSL ? 443 : 80));
|
|
|
|
return {
|
|
endPoint: url.hostname,
|
|
port: targetPort,
|
|
useSSL: targetUseSSL,
|
|
origin: url.origin,
|
|
};
|
|
}
|
|
|
|
const rawEndpoint = endpoint?.trim() || 'localhost';
|
|
|
|
if (rawEndpoint.startsWith('http://') || rawEndpoint.startsWith('https://')) {
|
|
const url = new URL(rawEndpoint);
|
|
const targetUseSSL = url.protocol === 'https:';
|
|
const targetPort = Number(url.port || (targetUseSSL ? 443 : 80));
|
|
|
|
return {
|
|
endPoint: url.hostname,
|
|
port: targetPort,
|
|
useSSL: targetUseSSL,
|
|
origin: url.origin,
|
|
};
|
|
}
|
|
|
|
const targetPort = Number(port ?? (useSSL ? 443 : 80));
|
|
const includePort = !(useSSL && targetPort === 443) && !(!useSSL && targetPort === 80);
|
|
|
|
return {
|
|
endPoint: rawEndpoint,
|
|
port: targetPort,
|
|
useSSL,
|
|
origin: `${useSSL ? 'https' : 'http'}://${rawEndpoint}${includePort ? `:${targetPort}` : ''}`,
|
|
};
|
|
};
|
|
|
|
const accessKey = process.env.MINIO_ACCESS_KEY;
|
|
const secretKey = process.env.MINIO_SECRET_KEY;
|
|
const insecureSkipTlsVerify = parseBoolean(process.env.MINIO_INSECURE_SKIP_TLS_VERIFY, false);
|
|
const tlsRejectUnauthorized = parseBoolean(process.env.MINIO_TLS_REJECT_UNAUTHORIZED, true);
|
|
const minioCaCertPath = process.env.MINIO_CA_CERT_PATH?.trim();
|
|
const internalUseSSL = parseBoolean(process.env.MINIO_USE_SSL, false);
|
|
const internalTarget = resolveMinioTarget({
|
|
endpoint: process.env.MINIO_ENDPOINT ?? 'localhost',
|
|
port: process.env.MINIO_PORT ?? 9000,
|
|
useSSL: internalUseSSL,
|
|
});
|
|
const publicTarget = resolveMinioTarget({
|
|
origin: process.env.MINIO_PUBLIC_ORIGIN,
|
|
endpoint: process.env.MINIO_PUBLIC_ENDPOINT ?? internalTarget.endPoint,
|
|
port: process.env.MINIO_PUBLIC_PORT ?? internalTarget.port,
|
|
useSSL: parseBoolean(process.env.MINIO_PUBLIC_USE_SSL, internalTarget.useSSL),
|
|
});
|
|
|
|
if (!accessKey || !secretKey) {
|
|
throw new Error('MINIO_ACCESS_KEY and MINIO_SECRET_KEY must be set');
|
|
}
|
|
|
|
export const minioBucket = process.env.MINIO_BUCKET ?? 'videos';
|
|
export const minioPresignedExpirySeconds = Number(process.env.MINIO_PRESIGNED_EXPIRY_SECONDS ?? 60 * 10);
|
|
export const minioPublicOrigin = publicTarget.origin;
|
|
const customCa = minioCaCertPath ? readFileSync(minioCaCertPath) : undefined;
|
|
const transportAgent = internalTarget.useSSL
|
|
? new HttpsAgent({
|
|
keepAlive: true,
|
|
ca: customCa,
|
|
rejectUnauthorized: insecureSkipTlsVerify ? false : tlsRejectUnauthorized,
|
|
})
|
|
: undefined;
|
|
|
|
export const minioClient = new Client({
|
|
endPoint: internalTarget.endPoint,
|
|
port: internalTarget.port,
|
|
useSSL: internalTarget.useSSL,
|
|
accessKey,
|
|
secretKey,
|
|
region: process.env.MINIO_REGION ?? 'us-east-1',
|
|
transportAgent,
|
|
});
|
|
|
|
export const minioPresignClient = new Client({
|
|
endPoint: publicTarget.endPoint,
|
|
port: publicTarget.port,
|
|
useSSL: publicTarget.useSSL,
|
|
accessKey,
|
|
secretKey,
|
|
region: process.env.MINIO_REGION ?? 'us-east-1',
|
|
});
|
|
|
|
let ensureBucketPromise: Promise<void> | null = null;
|
|
|
|
export const ensureMinioBucket = async (): Promise<void> => {
|
|
if (ensureBucketPromise) {
|
|
return ensureBucketPromise;
|
|
}
|
|
|
|
ensureBucketPromise = (async () => {
|
|
const exists = await minioClient.bucketExists(minioBucket);
|
|
|
|
if (!exists) {
|
|
await minioClient.makeBucket(minioBucket, process.env.MINIO_REGION ?? 'us-east-1');
|
|
}
|
|
})();
|
|
|
|
try {
|
|
await ensureBucketPromise;
|
|
console.log("Minio Up")
|
|
} catch (error) {
|
|
ensureBucketPromise = null;
|
|
throw error;
|
|
}
|
|
};
|