Spaces:
Running
Running
assafvayner HF Staff
fix(storage): skip integration suite safely, tighten list contract, drop expand
d594446 Download src/lib/server/storage/store.ts from assafvayner/splitwise: direct link, hf CLI and curl.
- Browser
- Download file 2.09 kB
-
https://huggingface.co/spaces/assafvayner/splitwise/resolve/main/src/lib/server/storage/store.ts
- Command line
-
hf download hf://spaces/assafvayner/splitwise/src/lib/server/storage/store.ts
-
curl -L -o store.ts https://huggingface.co/spaces/assafvayner/splitwise/resolve/main/src/lib/server/storage/store.ts
2.09 kB
| export interface StoreEntry { | |
| path: string; | |
| size: number; | |
| uploadedAt?: Date; | |
| } | |
| /** | |
| * Minimal object-store abstraction. Paths are bucket-relative, use `/` separators, | |
| * and never start with `/`. | |
| */ | |
| export interface BucketStore { | |
| /** Resolves null when the object does not exist. */ | |
| get(path: string): Promise<Uint8Array | null>; | |
| /** Creates or overwrites. */ | |
| put(path: string, bytes: Uint8Array, contentType?: string): Promise<void>; | |
| /** | |
| * Appends bytes to an existing object, creating it if missing. Not atomic on every | |
| * backend: a crash mid-append may leave a truncated final line, so readers must | |
| * tolerate a trailing partial line. | |
| */ | |
| append(path: string, bytes: Uint8Array): Promise<void>; | |
| /** | |
| * Lists files whose path starts with `prefix`, sorted by path. The prefix must be `''` | |
| * (the whole store) or end with `/`, so it always matches within a directory. | |
| */ | |
| list(prefix: string): Promise<StoreEntry[]>; | |
| /** Deletes objects; missing ones are ignored. */ | |
| delete(paths: string[]): Promise<void>; | |
| /** Server-side copy. Rejects if `src` does not exist. */ | |
| copy(src: string, dst: string): Promise<void>; | |
| } | |
| const SEGMENT_RE = /^[A-Za-z0-9._-]+$/; | |
| export function assertValidPath(path: string): void { | |
| if (path.length === 0 || path.length > 512) throw new Error(`Invalid path: ${path}`); | |
| if (path.startsWith('/') || path.endsWith('/')) throw new Error(`Invalid path: ${path}`); | |
| if (path.endsWith('.tmp')) throw new Error(`Invalid path: ${path}`); | |
| for (const seg of path.split('/')) { | |
| if (seg === '' || seg === '.' || seg === '..' || !SEGMENT_RE.test(seg)) throw new Error(`Invalid path: ${path}`); | |
| } | |
| } | |
| /** Validates a `list` prefix: either `''` or a valid path followed by `/`. */ | |
| export function assertValidPrefix(prefix: string): void { | |
| if (prefix === '') return; | |
| if (!prefix.endsWith('/')) throw new Error(`Invalid prefix: ${prefix}`); | |
| assertValidPath(prefix.slice(0, -1)); | |
| } | |
| export const encodeText = (s: string): Uint8Array => new TextEncoder().encode(s); | |
| export const decodeText = (b: Uint8Array): string => new TextDecoder().decode(b); | |