mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-20 11:36:25 +08:00
feat(server): lightweight s3 client (#14348)
#### PR Dependency Tree * **PR #14348** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a dedicated S3-compatible client package and expanded S3-compatible storage config (endpoint, region, forcePathStyle, requestTimeoutMs, minPartSize, presign options, sessionToken). * Document sync now broadcasts batched/compressed doc updates for more efficient real-time syncing. * **Tests** * New unit and benchmark tests for base64 utilities and S3 multipart listing; updated storage-related tests to match new formats. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -30,6 +30,15 @@ interface ServerEvents {
|
||||
timestamp: number;
|
||||
editor: string;
|
||||
};
|
||||
'space:broadcast-doc-updates': {
|
||||
spaceType: string;
|
||||
spaceId: string;
|
||||
docId: string;
|
||||
updates: string[];
|
||||
timestamp: number;
|
||||
editor?: string;
|
||||
compressed?: boolean;
|
||||
};
|
||||
|
||||
'space:collect-awareness': {
|
||||
spaceType: string;
|
||||
@@ -124,33 +133,42 @@ export type ClientEventsMap = {
|
||||
|
||||
export type Socket = SocketIO<ServerEventsMap, ClientEventsMap>;
|
||||
|
||||
export function uint8ArrayToBase64(array: Uint8Array): Promise<string> {
|
||||
return new Promise<string>(resolve => {
|
||||
// Create a blob from the Uint8Array
|
||||
const blob = new Blob([array]);
|
||||
type BufferConstructorLike = {
|
||||
from(
|
||||
data: Uint8Array | string,
|
||||
encoding?: string
|
||||
): Uint8Array & {
|
||||
toString(encoding: string): string;
|
||||
};
|
||||
};
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
const dataUrl = reader.result as string | null;
|
||||
if (!dataUrl) {
|
||||
resolve('');
|
||||
return;
|
||||
}
|
||||
// The result includes the `data:` URL prefix and the MIME type. We only want the Base64 data
|
||||
const base64 = dataUrl.split(',')[1];
|
||||
resolve(base64);
|
||||
};
|
||||
const BufferCtor = (globalThis as { Buffer?: BufferConstructorLike }).Buffer;
|
||||
const CHUNK_SIZE = 0x8000;
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
export async function uint8ArrayToBase64(array: Uint8Array): Promise<string> {
|
||||
if (BufferCtor) {
|
||||
return BufferCtor.from(array).toString('base64');
|
||||
}
|
||||
|
||||
let binary = '';
|
||||
for (let i = 0; i < array.length; i += CHUNK_SIZE) {
|
||||
const chunk = array.subarray(i, i + CHUNK_SIZE);
|
||||
binary += String.fromCharCode(...chunk);
|
||||
}
|
||||
return btoa(binary);
|
||||
}
|
||||
|
||||
export function base64ToUint8Array(base64: string) {
|
||||
if (BufferCtor) {
|
||||
return new Uint8Array(BufferCtor.from(base64, 'base64'));
|
||||
}
|
||||
|
||||
const binaryString = atob(base64);
|
||||
const binaryArray = [...binaryString].map(function (char) {
|
||||
return char.charCodeAt(0);
|
||||
});
|
||||
return new Uint8Array(binaryArray);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
for (let i = 0; i < binaryString.length; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
let authMethod:
|
||||
|
||||
Reference in New Issue
Block a user