BIG MOOOOVE to Object Storage
Deploy / deploy (push) Successful in 2m43s

This commit is contained in:
twotalesanimation
2026-07-16 22:15:58 +02:00
parent 3264abb432
commit 745634f1b6
10 changed files with 594 additions and 17 deletions
+45
View File
@@ -15,6 +15,7 @@ import {
PutObjectCommand,
DeleteObjectCommand,
GetObjectCommand,
ListObjectsV2Command,
} from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import fs from "fs";
@@ -277,6 +278,50 @@ export async function uploadToHetzner(
return { key };
}
/**
* List all object keys currently stored in the Hetzner bucket.
* Paginates automatically. Used by the migration tool.
*/
export async function listHetznerKeys(): Promise<Set<string>> {
const { client, bucket } = await buildHetznerClient();
const keys = new Set<string>();
let continuationToken: string | undefined;
do {
const resp = await client.send(
new ListObjectsV2Command({ Bucket: bucket, ContinuationToken: continuationToken })
);
for (const obj of resp.Contents ?? []) {
if (obj.Key) keys.add(obj.Key);
}
continuationToken = resp.NextContinuationToken;
} while (continuationToken);
return keys;
}
/**
* Upload a stream directly to Hetzner under an exact key (no UUID prefix).
* Used by the migration tool to preserve existing file paths.
*/
export async function uploadToHetznerWithKey(
body: NodeJS.ReadableStream,
key: string,
contentType: string,
contentLength: number
): Promise<void> {
const { client, bucket } = await buildHetznerClient();
await client.send(
new PutObjectCommand({
Bucket: bucket,
Key: key,
Body: body as unknown as Blob,
ContentType: contentType,
ContentLength: contentLength,
})
);
}
/**
* Generate a presigned URL for streaming a Hetzner object directly in the browser.
* No Content-Disposition header — suitable for <video src="..."> playback.