refactor(api): collapse single-impl interfaces and facades (#3382)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-10 23:04:42 +02:00
1 parent e7b13fd19f
commit c16d414d93
426 files changed
+2085 -6445

No files matched your search

@@ -12,18 +12,10 @@
"import": "./src/MediaProxyUtils.ts",
"types": "./src/MediaProxyUtils.ts"
},
"./src/ExternalMediaProxyUrlBuilder": {
"import": "./src/ExternalMediaProxyUrlBuilder.ts",
"types": "./src/ExternalMediaProxyUrlBuilder.ts"
},
"./src/ExternalMediaProxyPathCodec": {
"import": "./src/ExternalMediaProxyPathCodec.ts",
"types": "./src/ExternalMediaProxyPathCodec.ts"
},
"./src/MediaProxySigner": {
"import": "./src/MediaProxySigner.ts",
"types": "./src/MediaProxySigner.ts"
},
"./src/AttachmentUrlSignature": {
"import": "./src/AttachmentUrlSignature.ts",
"types": "./src/AttachmentUrlSignature.ts"
@@ -1,50 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {buildExternalMediaProxyPath} from '@pkgs/media_proxy_utils/src/ExternalMediaProxyPathCodec';
import {createMediaProxySigner, type IMediaProxySigner} from '@pkgs/media_proxy_utils/src/MediaProxySigner';
export interface ExternalMediaProxyUrlBuilderOptions {
mediaProxyEndpoint: string;
mediaProxySecretKey: string;
}
export interface IExternalMediaProxyUrlBuilder {
buildExternalMediaProxyUrl(inputUrl: string): string;
}
interface InternalExternalMediaProxyUrlBuilderOptions {
mediaProxyEndpoint: string;
mediaProxySigner: IMediaProxySigner;
}
function normalizeMediaProxyEndpoint(mediaProxyEndpoint: string): string {
return mediaProxyEndpoint.replace(/\/+$/u, '');
}
class ExternalMediaProxyUrlBuilder implements IExternalMediaProxyUrlBuilder {
private readonly mediaProxyEndpoint: string;
private readonly mediaProxySigner: IMediaProxySigner;
constructor(options: InternalExternalMediaProxyUrlBuilderOptions) {
this.mediaProxyEndpoint = options.mediaProxyEndpoint;
this.mediaProxySigner = options.mediaProxySigner;
}
buildExternalMediaProxyUrl(inputUrl: string): string {
const proxyUrlPath = buildExternalMediaProxyPath(inputUrl);
const signature = this.mediaProxySigner.createSignature(proxyUrlPath);
return `${this.mediaProxyEndpoint}/external/${signature}/${proxyUrlPath}`;
}
}
export function createExternalMediaProxyUrlBuilder(
options: ExternalMediaProxyUrlBuilderOptions,
): IExternalMediaProxyUrlBuilder {
const mediaProxySigner = createMediaProxySigner({
mediaProxySecretKey: options.mediaProxySecretKey,
});
return new ExternalMediaProxyUrlBuilder({
mediaProxyEndpoint: normalizeMediaProxyEndpoint(options.mediaProxyEndpoint),
mediaProxySigner,
});
}
@@ -1,42 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import crypto from 'node:crypto';
const BASE64_URL_PADDING_REGEX = /=*$/;
export interface MediaProxySignerOptions {
mediaProxySecretKey: string;
}
export interface IMediaProxySigner {
createSignature(proxyUrlPath: string): string;
verifySignature(proxyUrlPath: string, providedSignature: string): boolean;
}
class MediaProxySigner implements IMediaProxySigner {
private readonly mediaProxySecretKey: string;
constructor(options: MediaProxySignerOptions) {
this.mediaProxySecretKey = options.mediaProxySecretKey;
}
createSignature(proxyUrlPath: string): string {
const hmac = crypto.createHmac('sha256', this.mediaProxySecretKey);
hmac.update(proxyUrlPath);
return hmac.digest('base64url').replace(BASE64_URL_PADDING_REGEX, '');
}
verifySignature(proxyUrlPath: string, providedSignature: string): boolean {
const expectedSignature = this.createSignature(proxyUrlPath);
const expectedBuffer = Buffer.from(expectedSignature, 'utf8');
const providedBuffer = Buffer.from(providedSignature, 'utf8');
if (expectedBuffer.length !== providedBuffer.length) {
return false;
}
return crypto.timingSafeEqual(expectedBuffer, providedBuffer);
}
}
export function createMediaProxySigner(options: MediaProxySignerOptions): IMediaProxySigner {
return new MediaProxySigner(options);
}
@@ -1,25 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import crypto from 'node:crypto';
import {createExternalMediaProxyUrlBuilder} from '@pkgs/media_proxy_utils/src/ExternalMediaProxyUrlBuilder';
const BASE64_URL_REGEX = /=*$/;
export function createSignature(inputString: string, mediaProxySecretKey: string): string {
const hmac = crypto.createHmac('sha256', mediaProxySecretKey);
hmac.update(inputString);
return hmac.digest('base64url').replace(BASE64_URL_REGEX, '');
}
export function verifySignature(proxyUrlPath: string, providedSignature: string, mediaProxySecretKey: string): boolean {
const expectedSignature = createSignature(proxyUrlPath, mediaProxySecretKey);
const expectedBuffer = Buffer.from(expectedSignature);
const providedBuffer = Buffer.from(providedSignature);
if (expectedBuffer.length !== providedBuffer.length) {
return false;
}
return crypto.timingSafeEqual(expectedBuffer, providedBuffer);
}
import {buildExternalMediaProxyPath} from '@pkgs/media_proxy_utils/src/ExternalMediaProxyPathCodec';
export interface ExternalMediaProxyURLOptions {
inputURL: string;
@@ -28,9 +10,12 @@ export interface ExternalMediaProxyURLOptions {
}
export function getExternalMediaProxyURL(options: ExternalMediaProxyURLOptions): string {
const builder = createExternalMediaProxyUrlBuilder({
mediaProxyEndpoint: options.mediaProxyEndpoint,
mediaProxySecretKey: options.mediaProxySecretKey,
});
return builder.buildExternalMediaProxyUrl(options.inputURL);
const endpoint = options.mediaProxyEndpoint.replace(/\/+$/u, '');
const proxyUrlPath = buildExternalMediaProxyPath(options.inputURL);
const signature = crypto
.createHmac('sha256', options.mediaProxySecretKey)
.update(proxyUrlPath)
.digest('base64url')
.replace(/=*$/, '');
return `${endpoint}/external/${signature}/${proxyUrlPath}`;
}