first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
# `memory.ts`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
In-memory `UploadSessionStore` adapter. Tracks both in-flight `UploadSession` state (sessions Map) and completed `UploadRecord` metadata (records Map) so `GET /uploads/{uploadId}` works against either an in-progress chunked upload OR a completed single-shot upload uniformly. Used as the default store when `createFileUploadPlugin` is invoked without an explicit `sessionStore` option.
## Features
- Idempotent `appendChunkIndex` via underlying `Set<number>` — calling twice with the same index is a no-op.
- `listExpired(now, ttlMs)` returns every session whose `createdAt + ttlMs <= now` so the plugin's cleanup loop has a single-call sweep API.
- Strict `create` (rejects duplicates) and strict `update` (rejects missing) so logic bugs in the service layer surface immediately rather than silently writing the wrong record.
- Records are stored separately from sessions so `complete` can swap session → record atomically without leaving an in-flight reference behind.
## Usage: Basic
```ts
import { MemoryUploadSessionStore } from "@suaveplan/api-plugin-file-upload/session-store/memory";
const store = new MemoryUploadSessionStore();
await store.create(session);
const fetched = await store.read(session.uploadId);
```
## Usage: Advanced
```ts
import { MemoryUploadSessionStore } from "@suaveplan/api-plugin-file-upload";
const store = new MemoryUploadSessionStore();
await store.create(session);
await store.appendChunkIndex(session.uploadId, 0);
await store.appendChunkIndex(session.uploadId, 0); // idempotent
const expired = await store.listExpired(Date.now() + 60_000, 1000);
for (const s of expired) await store.delete(s.uploadId);
```
## API Reference
- `class MemoryUploadSessionStore implements UploadSessionStore` — constructor takes no arguments.
- `create(session)` / `read(id)` / `update(session)` / `delete(id)` — standard CRUD.
- `appendChunkIndex(id, index): Promise<UploadSession>` — returns the updated session.
- `listExpired(now, ttlMs): Promise<readonly UploadSession[]>` — TTL sweep.
- `readRecord(id)` / `saveRecord(record)` / `deleteRecord(id)` — record-side CRUD.
## Implementation Notes
- The session and record maps are kept distinct because a single upload transitions session → record atomically; conflating them would force the caller to encode that transition with an enum field on a union type.
- `appendChunkIndex` always returns a fresh `UploadSession` value (shallow-copied with the new set) so consumers comparing references can detect updates without `===` foot-guns.
- `delete` is intentionally idempotent — abort routes call it without first checking existence.