@powerhousedao/reactor-attachments 6.1.0-staging.0 → 6.2.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,617 @@
1
+ import { AttachmentHash, AttachmentRef, JwtHandler } from "@powerhousedao/reactor";
2
+
3
+ //#region src/errors.d.ts
4
+ /**
5
+ * Thrown when an attachment ref or hash is not known to the store.
6
+ */
7
+ declare class AttachmentNotFound extends Error {
8
+ constructor(identifier: string);
9
+ }
10
+ /**
11
+ * Thrown when a reservation ID is not found in the reservation store.
12
+ */
13
+ declare class ReservationNotFound extends Error {
14
+ constructor(reservationId: string);
15
+ }
16
+ /**
17
+ * Thrown when an attachment ref string does not match the expected format.
18
+ */
19
+ declare class InvalidAttachmentRef extends Error {
20
+ constructor(ref: string);
21
+ }
22
+ /**
23
+ * Thrown when an upload exceeds the configured maximum byte cap.
24
+ * Route handlers should map this to HTTP 413 Payload Too Large.
25
+ */
26
+ declare class UploadTooLarge extends Error {
27
+ readonly maxBytes: number;
28
+ constructor(maxBytes: number);
29
+ }
30
+ /**
31
+ * Thrown by reserve() when the claimed hash is already available in the store.
32
+ * The caller should use err.ref directly and upload nothing -- this is the
33
+ * dedup fast path: duplicate content never leaves the client.
34
+ */
35
+ declare class AttachmentAlreadyExists extends Error {
36
+ readonly hash: AttachmentHash;
37
+ readonly ref: AttachmentRef;
38
+ constructor(hash: AttachmentHash, ref: AttachmentRef);
39
+ }
40
+ /**
41
+ * Thrown by send() when the server-computed hash of the uploaded bytes
42
+ * does not match the hash claimed at reservation time. Nothing is committed;
43
+ * the reservation is retained so the client can retry with correct bytes.
44
+ */
45
+ declare class HashMismatch extends Error {
46
+ readonly claimed: AttachmentHash;
47
+ readonly actual: AttachmentHash;
48
+ constructor(claimed: AttachmentHash, actual: AttachmentHash);
49
+ }
50
+ /**
51
+ * Thrown by send() when the uploaded byte count does not equal the
52
+ * sizeBytes declared at reservation time. The handle may reject
53
+ * mid-stream as soon as the count exceeds the declaration.
54
+ * Nothing is committed; the reservation is retained for retry.
55
+ *
56
+ * "actual" is the byte count received from the stream before aborting --
57
+ * it includes the chunk that crossed the declaration and can exceed bytes
58
+ * persisted. On mid-stream aborts the true total is unknown; at least
59
+ * "actual" bytes were sent.
60
+ */
61
+ declare class SizeMismatch extends Error {
62
+ readonly declared: number;
63
+ readonly actual: number;
64
+ constructor(declared: number, actual: number);
65
+ }
66
+ /**
67
+ * Thrown by get() when the hash is reserved by an in-flight upload and
68
+ * bytes are not yet available anywhere. Deliberately NOT a subclass of
69
+ * AttachmentNotFound -- callers must distinguish "retry later" from "unknown".
70
+ * After expiresAtUtc has passed the hash reads as not found.
71
+ *
72
+ * metadata is populated when the reservation is local and its fields are
73
+ * known (mimeType, fileName, sizeBytes). It is undefined when the pending
74
+ * state is learned from a remote transport that did not supply the full
75
+ * Attachment-Pending header (transport-pending / degraded wire case).
76
+ */
77
+ declare class AttachmentPending extends Error {
78
+ readonly hash: AttachmentHash;
79
+ readonly expiresAtUtc: string;
80
+ readonly metadata: {
81
+ readonly mimeType: string;
82
+ readonly fileName: string;
83
+ readonly sizeBytes: number;
84
+ } | undefined;
85
+ constructor(hash: AttachmentHash, expiresAtUtc: string, meta?: {
86
+ mimeType: string;
87
+ fileName: string;
88
+ sizeBytes: number;
89
+ });
90
+ }
91
+ //#endregion
92
+ //#region src/types.d.ts
93
+ /**
94
+ * Status of attachment data in the local store.
95
+ * 'pending' is a virtual status synthesized at query time from live,
96
+ * hash-bearing reservations -- it never appears in the attachment table.
97
+ */
98
+ type AttachmentStatus = "available" | "evicted" | "pending";
99
+ /**
100
+ * Metadata about an attachment. For committed attachments (available/evicted),
101
+ * expiresAtUtc is null. For pending attachments synthesized from a live
102
+ * reservation, expiresAtUtc carries the reservation expiry so callers can
103
+ * emit Retry-After or bound polling loops.
104
+ */
105
+ type AttachmentHeader = {
106
+ hash: AttachmentHash;
107
+ mimeType: string;
108
+ fileName: string;
109
+ sizeBytes: number;
110
+ extension: string | null;
111
+ status: AttachmentStatus;
112
+ source: "local" | "sync";
113
+ createdAtUtc: string;
114
+ lastAccessedAtUtc: string;
115
+ expiresAtUtc: string | null;
116
+ };
117
+ /**
118
+ * Metadata provided alongside attachment data during sync, and returned
119
+ * via the switchboard's `Attachment-Metadata` header on GET/HEAD.
120
+ * `createdAtUtc` is the original upload time, propagated from the source
121
+ * so that the receiving store preserves it instead of synthesizing the
122
+ * fetch time. `lastAccessedAtUtc` is the source reactor's most recent
123
+ * access time; it is optional because not every producer (e.g. a fresh
124
+ * `put` from a transport) tracks access yet. Receiving stores that
125
+ * persist locally (LRU concerns) reset it on every read regardless.
126
+ *
127
+ * Reliability note: `lastAccessedAtUtc` arriving over the wire is
128
+ * best-effort. When the producer omits it, the consumer (see
129
+ * `RemoteAttachmentStore` / `SwitchboardAttachmentTransport`) coalesces
130
+ * with `createdAtUtc`, so the field can silently equal `createdAtUtc`
131
+ * even on a server that has never been read. Do NOT use the wire value
132
+ * for LRU eviction or staleness decisions on remote data; always read
133
+ * the field from the local store after persistence, where the receiving
134
+ * store is the authority.
135
+ */
136
+ type AttachmentMetadata = {
137
+ mimeType: string;
138
+ fileName: string;
139
+ sizeBytes: number;
140
+ extension: string | null;
141
+ createdAtUtc: string;
142
+ lastAccessedAtUtc?: string;
143
+ };
144
+ /**
145
+ * Upload-first reservation. clientHash and sizeBytes are absent;
146
+ * the ref is only known after send() completes.
147
+ */
148
+ type UploadFirstReserveAttachmentOptions = {
149
+ mimeType: string;
150
+ fileName: string;
151
+ extension?: string | null;
152
+ clientHash?: undefined;
153
+ sizeBytes?: undefined;
154
+ };
155
+ /**
156
+ * Hash-first reservation. clientHash is present and sizeBytes is required.
157
+ * The ref is known at reservation time; send() verifies the uploaded bytes
158
+ * against the claimed hash and declared size. The explicit "?: undefined"
159
+ * on UploadFirstReserveAttachmentOptions makes clientHash a narrowing discriminant:
160
+ * checking options.clientHash !== undefined narrows sizeBytes to number.
161
+ */
162
+ type HashFirstReserveAttachmentOptions = {
163
+ mimeType: string;
164
+ fileName: string;
165
+ extension?: string | null;
166
+ /**
167
+ * Content hash claimed by the client (lowercase SHA-256 hex).
168
+ */
169
+ clientHash: AttachmentHash;
170
+ /**
171
+ * Declared size in bytes. Required when clientHash is present.
172
+ * Reported by stat() during the pending window and enforced on
173
+ * ingest: an upload whose actual byte count differs is rejected.
174
+ */
175
+ sizeBytes: number;
176
+ };
177
+ /**
178
+ * Options provided when reserving an attachment slot.
179
+ *
180
+ * Use HashFirstReserveAttachmentOptions when clientHash is known up front;
181
+ * the service then operates in hash-first mode: reserve() rejects if the
182
+ * content is already available, and send() verifies the uploaded bytes.
183
+ *
184
+ * Use UploadFirstReserveAttachmentOptions (or omit clientHash) for the
185
+ * upload-first flow where the ref is only known after send() completes.
186
+ */
187
+ type ReserveAttachmentOptions = UploadFirstReserveAttachmentOptions | HashFirstReserveAttachmentOptions;
188
+ /**
189
+ * Result of uploading attachment data through a handle.
190
+ */
191
+ type AttachmentUploadResult = {
192
+ hash: AttachmentHash;
193
+ ref: AttachmentRef;
194
+ header: AttachmentHeader;
195
+ };
196
+ /**
197
+ * Response when retrieving attachment data from the local store.
198
+ */
199
+ type AttachmentResponse = {
200
+ header: AttachmentHeader;
201
+ body: ReadableStream<Uint8Array>;
202
+ };
203
+ /**
204
+ * Response when fetching attachment data from a remote transport.
205
+ * Lighter than AttachmentResponse -- a remote peer cannot meaningfully
206
+ * populate status or source, which are local reactor concerns.
207
+ * The store assigns those fields when it calls put() on receipt.
208
+ */
209
+ type TransportResponse = {
210
+ hash: AttachmentHash;
211
+ metadata: AttachmentMetadata;
212
+ body: ReadableStream<Uint8Array>;
213
+ };
214
+ /**
215
+ * Three-way result from IAttachmentTransport.fetch(). Replaces
216
+ * TransportResponse | null to make the pending state explicit, so
217
+ * peers receiving a synced operation whose attachment is in-flight can
218
+ * distinguish "retry later" from "permanently unknown".
219
+ */
220
+ type TransportFetchResult = {
221
+ kind: "data";
222
+ response: TransportResponse;
223
+ } | {
224
+ kind: "pending";
225
+ hash: AttachmentHash;
226
+ expiresAtUtc: string;
227
+ retryAfterMs: number;
228
+ } | {
229
+ kind: "not-found";
230
+ };
231
+ /**
232
+ * Configuration for creating an attachment transport instance.
233
+ */
234
+ type AttachmentTransportConfig = {
235
+ type: string;
236
+ parameters: Record<string, unknown>;
237
+ };
238
+ /**
239
+ * A reservation for an in-progress attachment upload.
240
+ * Created by reserve(), deleted when upload.send() completes or
241
+ * once expiresAtUtc has passed and a sweep runs.
242
+ * clientHash and sizeBytes are set in hash-first mode and null in
243
+ * upload-first mode.
244
+ */
245
+ type Reservation = {
246
+ reservationId: string;
247
+ mimeType: string;
248
+ fileName: string;
249
+ extension: string | null;
250
+ createdAtUtc: string;
251
+ expiresAtUtc: string;
252
+ clientHash: string | null;
253
+ sizeBytes: number | null;
254
+ };
255
+ //#endregion
256
+ //#region src/interfaces.d.ts
257
+ /**
258
+ * Client-facing interface for uploading, querying, and retrieving attachments.
259
+ * This is what applications (editors, Connect, CLI tools) interact with.
260
+ */
261
+ interface IAttachmentService {
262
+ /**
263
+ * Reserve a new attachment slot and return an upload handle.
264
+ *
265
+ * When options.clientHash is provided (hash-first mode):
266
+ * - @throws AttachmentAlreadyExists if data for that hash is currently
267
+ * available. The error carries the canonical ref; the caller uses it
268
+ * directly and uploads nothing (dedup fast path).
269
+ * - If the hash is evicted, the reservation is created: the client holds
270
+ * the bytes and the upload restores them.
271
+ * - If the hash is pending (another in-flight reservation), the
272
+ * reservation is created: concurrent reservations are deliberately
273
+ * permitted (see design doc -- no uniqueness race).
274
+ * - The returned handle's ref field is set immediately to the computed ref.
275
+ *
276
+ * When options.clientHash is absent (upload-first mode):
277
+ * - No pre-check against the store.
278
+ * - The returned handle's ref field is null until send() completes.
279
+ */
280
+ reserve(options: ReserveAttachmentOptions): Promise<IAttachmentUpload>;
281
+ /**
282
+ * Get attachment metadata by ref.
283
+ *
284
+ * @throws AttachmentNotFound if the ref is unknown.
285
+ * Returns an AttachmentHeader with status='pending' and expiresAtUtc set if
286
+ * the hash has an active reservation but no committed bytes. Callers must
287
+ * check header.status to distinguish pending from available.
288
+ */
289
+ stat(ref: AttachmentRef): Promise<AttachmentHeader>;
290
+ /**
291
+ * Retrieve attachment data.
292
+ *
293
+ * Always succeeds for any known, available ref. The underlying store
294
+ * handles re-fetching evicted data from the transport transparently.
295
+ *
296
+ * @throws AttachmentPending if the hash is reserved but bytes not yet
297
+ * available. There is no store-level wait; polling across the
298
+ * pending window is the caller's loop, bounded by the error's
299
+ * expiresAtUtc. A wait inside get() would hold request handlers
300
+ * open across multi-second windows and hide retry policy where
301
+ * callers cannot tune it.
302
+ */
303
+ get(ref: AttachmentRef, signal?: AbortSignal): Promise<AttachmentResponse>;
304
+ }
305
+ /**
306
+ * Upload handle returned by reserve(). Encapsulates all transport-specific
307
+ * concerns (URLs, credentials, streaming protocols) behind a single send() method.
308
+ */
309
+ interface IAttachmentUpload {
310
+ /**
311
+ * Unique identifier for this reservation.
312
+ */
313
+ reservationId: string;
314
+ /**
315
+ * The ref this upload will produce. Set immediately when the
316
+ * reservation carries a client hash (hash-first mode); null in the
317
+ * upload-first flow, where the ref is only known after send() completes.
318
+ */
319
+ ref: AttachmentRef | null;
320
+ /**
321
+ * Reservation TTL contract, from the server in remote mode.
322
+ * ISO 8601 UTC string indicating when the reservation expires.
323
+ * Clients use this to bound retry windows and populate the pending-upload queue.
324
+ */
325
+ readonly expiresAtUtc: string;
326
+ /**
327
+ * Stream attachment data through this handle.
328
+ *
329
+ * The handle manages the full upload lifecycle internally:
330
+ * writing bytes to the backing store, computing or verifying
331
+ * the content hash, creating the attachment record, and
332
+ * cleaning up the reservation.
333
+ *
334
+ * Dedup: if an attachment with the same content hash already
335
+ * exists, send() returns the existing ref. Content-addressed
336
+ * storage means identical uploads converge on the same hash.
337
+ *
338
+ * When the reservation carries a client hash, the handle verifies
339
+ * the received bytes against the claims:
340
+ * - @throws SizeMismatch if the byte count differs from the declared
341
+ * sizeBytes. The handle may reject mid-stream as soon as the count
342
+ * exceeds the declaration, without consuming the rest.
343
+ * - @throws HashMismatch if the server-computed hash differs from the
344
+ * claimed hash. Nothing is committed; the reservation is retained
345
+ * so the client can retry with the correct bytes.
346
+ *
347
+ * @returns The content hash, ref, and header for the uploaded attachment.
348
+ */
349
+ send(data: ReadableStream<Uint8Array>): Promise<AttachmentUploadResult>;
350
+ }
351
+ /**
352
+ * Read-only subset of IAttachmentStore.
353
+ *
354
+ * Adapters that cannot safely support the local-only write/GC surface
355
+ * (remote stores, forwarding caches) implement this narrow interface
356
+ * instead of stub-rejecting unsupported methods. Consumers that only
357
+ * need to query metadata or stream attachment bytes can take this type
358
+ * to make their dependency requirements explicit.
359
+ */
360
+ interface IAttachmentReader {
361
+ /**
362
+ * Get attachment metadata without streaming body data.
363
+ * Does NOT update lastAccessedAtUtc -- this is a metadata check,
364
+ * not a data access.
365
+ *
366
+ * @throws AttachmentNotFound if the hash is unknown.
367
+ * Returns an AttachmentHeader with status='pending' and expiresAtUtc set if
368
+ * the hash has an active reservation but no committed bytes. Callers must
369
+ * check header.status to distinguish pending from available.
370
+ */
371
+ stat(hash: AttachmentHash): Promise<AttachmentHeader>;
372
+ /**
373
+ * Retrieve attachment header and data stream by hash.
374
+ * Updates lastAccessedAtUtc on access.
375
+ *
376
+ * If the data has been evicted, re-fetches it from the transport,
377
+ * restores it locally via put(), and returns the data. This makes
378
+ * eviction transparent to callers -- get() always succeeds for
379
+ * any known, available hash.
380
+ *
381
+ * @throws AttachmentNotFound if the hash is unknown (no metadata
382
+ * record exists and no pending reservation).
383
+ * @throws AttachmentPending if the hash is reserved by an in-flight
384
+ * upload; bytes are not yet available. There is no store-level
385
+ * wait -- polling is the caller's responsibility.
386
+ */
387
+ get(hash: AttachmentHash, signal?: AbortSignal): Promise<AttachmentResponse>;
388
+ }
389
+ /**
390
+ * Reactor-facing interface for managing local attachment data.
391
+ * The IAttachmentTransport calls put when it receives data from a remote.
392
+ * The store notifies its configured transport when new data arrives,
393
+ * forming a bidirectional store-transport pair.
394
+ */
395
+ interface IAttachmentStore extends IAttachmentReader {
396
+ /**
397
+ * Check whether attachment data is available locally.
398
+ * Returns true if the bytes can be served from this reactor's store
399
+ * without a transport round-trip. Does not trigger a remote fetch.
400
+ * Returns false for pending and evicted hashes.
401
+ */
402
+ has(hash: AttachmentHash): Promise<boolean>;
403
+ /**
404
+ * Store attachment data received from a remote (during sync or re-fetch).
405
+ * Called by IAttachmentTransport implementations during sync, and
406
+ * internally by get() when restoring evicted data.
407
+ *
408
+ * Behavior depends on existing state:
409
+ * - No existing row: INSERT with source='sync', status='available'.
410
+ * - Existing row with status='evicted': restore data, set status
411
+ * to 'available'.
412
+ * - Existing row with status='available': no-op (dedup).
413
+ */
414
+ put(hash: AttachmentHash, metadata: AttachmentMetadata, data: ReadableStream<Uint8Array>): Promise<void>;
415
+ /**
416
+ * Evict attachment data to reclaim storage.
417
+ *
418
+ * Removes the local bytes and sets status to 'evicted'. The
419
+ * metadata record is retained so the hash is still known. If the
420
+ * data is needed again, the service fetches it via the transport.
421
+ *
422
+ * Eviction must not destroy data while a get() stream is in
423
+ * flight. Implementations must skip hashes with active readers
424
+ * (e.g. via a refcount or lease) and revisit them on the next
425
+ * GC pass.
426
+ *
427
+ * On immutable backends, this unpins/stops serving rather
428
+ * than deleting.
429
+ */
430
+ evict(hash: AttachmentHash): Promise<void>;
431
+ /**
432
+ * Get the total storage used by locally available attachment data.
433
+ * Used by the GC policy to decide when to evict.
434
+ */
435
+ storageUsed(): Promise<number>;
436
+ }
437
+ /**
438
+ * Transport for moving attachment data between reactors.
439
+ *
440
+ * Forms a bidirectional pair with IAttachmentStore. The store calls
441
+ * announce/push when new data arrives locally. The transport calls
442
+ * store.put() when data arrives from a remote.
443
+ */
444
+ interface IAttachmentTransport {
445
+ /**
446
+ * Fetch attachment data by hash from a remote source.
447
+ *
448
+ * Returns a three-way discriminated union so callers can distinguish
449
+ * "data available", "upload in flight -- retry after expiry", and
450
+ * "not found -- possibly permanently". Conflating the last two would
451
+ * cause callers to apply long backoff to transient pending state,
452
+ * or to retry indefinitely on a permanently missing hash.
453
+ *
454
+ * @param hash - Content hash of the attachment
455
+ * @param signal - Abort signal for cancellation
456
+ */
457
+ fetch(hash: AttachmentHash, signal?: AbortSignal): Promise<TransportFetchResult>;
458
+ /**
459
+ * Announce that this reactor has attachment data available.
460
+ *
461
+ * For server-centric transports, this may be a no-op (the server
462
+ * already has the data after upload).
463
+ */
464
+ announce(hash: AttachmentHash): Promise<void>;
465
+ /**
466
+ * Push attachment data to a specific remote.
467
+ *
468
+ * Used for eager replication strategies where the source reactor
469
+ * pushes data to known peers rather than waiting for pull requests.
470
+ *
471
+ * @param hash - Content hash of the attachment
472
+ * @param remote - Target remote identifier
473
+ * @param data - The attachment data stream
474
+ */
475
+ push(hash: AttachmentHash, remote: string, data: ReadableStream<Uint8Array>): Promise<void>;
476
+ }
477
+ /**
478
+ * Factory for creating attachment transport instances.
479
+ * Mirrors IChannelFactory for operation sync.
480
+ */
481
+ interface IAttachmentTransportFactory {
482
+ instance(config: AttachmentTransportConfig): IAttachmentTransport;
483
+ }
484
+ /**
485
+ * Store for managing attachment reservations.
486
+ * Reservations are transient records tracking in-progress uploads.
487
+ */
488
+ interface IReservationStore {
489
+ create(options: ReserveAttachmentOptions): Promise<Reservation>;
490
+ get(reservationId: string): Promise<Reservation>;
491
+ delete(reservationId: string): Promise<void>;
492
+ /**
493
+ * Delete reservations whose expires_at_utc is at or before `now`.
494
+ * Returns the number of rows deleted.
495
+ *
496
+ * Reservations are not auto-swept; consumers should call this on a
497
+ * cron / interval to clean up rows left behind by aborted uploads.
498
+ */
499
+ deleteExpired(now?: Date): Promise<number>;
500
+ }
501
+ /**
502
+ * Factory for creating transport-specific upload handles.
503
+ * The service calls this during reserve() to create a handle
504
+ * that knows how to stream bytes to the appropriate backend.
505
+ */
506
+ interface IAttachmentUploadFactory {
507
+ createUpload(reservation: Reservation): IAttachmentUpload;
508
+ }
509
+ //#endregion
510
+ //#region src/attachment-service.d.ts
511
+ declare class AttachmentService implements IAttachmentService {
512
+ private readonly store;
513
+ private readonly reservations;
514
+ private readonly uploadFactory;
515
+ constructor(store: IAttachmentReader, reservations: IReservationStore, uploadFactory: IAttachmentUploadFactory);
516
+ reserve(options: ReserveAttachmentOptions): Promise<IAttachmentUpload>;
517
+ stat(ref: AttachmentRef): Promise<AttachmentHeader>;
518
+ get(ref: AttachmentRef, signal?: AbortSignal): Promise<AttachmentResponse>;
519
+ private reserveHashFirst;
520
+ }
521
+ //#endregion
522
+ //#region src/ref.d.ts
523
+ type ParsedRef = {
524
+ version: number;
525
+ hash: AttachmentHash;
526
+ };
527
+ declare function parseRef(ref: AttachmentRef): ParsedRef;
528
+ declare function createRef(hash: AttachmentHash, version?: number): AttachmentRef;
529
+ //#endregion
530
+ //#region src/switchboard/switchboard-attachment-transport.d.ts
531
+ type SwitchboardTransportConfig = {
532
+ remoteUrl: string;
533
+ jwtHandler?: JwtHandler;
534
+ fetchFn?: typeof fetch;
535
+ };
536
+ declare class SwitchboardAttachmentTransport implements IAttachmentTransport {
537
+ private readonly remoteUrl;
538
+ private readonly jwtHandler?;
539
+ private readonly fetchFn;
540
+ constructor(config: SwitchboardTransportConfig);
541
+ fetch(hash: AttachmentHash, signal?: AbortSignal): Promise<TransportFetchResult>;
542
+ announce(_hash: AttachmentHash): Promise<void>;
543
+ push(hash: AttachmentHash, remote: string, data: ReadableStream<Uint8Array>): Promise<void>;
544
+ private parsePendingExpiry;
545
+ private parseMetadataHeaders;
546
+ }
547
+ //#endregion
548
+ //#region src/switchboard/remote-reservation-store.d.ts
549
+ type SwitchboardClientConfig = {
550
+ remoteUrl: string;
551
+ jwtHandler?: JwtHandler;
552
+ fetchFn?: typeof fetch;
553
+ };
554
+ declare class RemoteReservationStore implements IReservationStore {
555
+ private readonly remoteUrl;
556
+ private readonly jwtHandler?;
557
+ private readonly fetchFn;
558
+ constructor(config: SwitchboardClientConfig);
559
+ create(options: ReserveAttachmentOptions): Promise<Reservation>;
560
+ get(reservationId: string): Promise<Reservation>;
561
+ delete(reservationId: string): Promise<void>;
562
+ deleteExpired(): Promise<number>;
563
+ }
564
+ //#endregion
565
+ //#region src/switchboard/remote-attachment-upload.d.ts
566
+ declare class RemoteAttachmentUpload implements IAttachmentUpload {
567
+ readonly reservationId: string;
568
+ readonly ref: AttachmentRef | null;
569
+ readonly expiresAtUtc: string;
570
+ private readonly remoteUrl;
571
+ private readonly jwtHandler?;
572
+ private readonly fetchFn;
573
+ constructor(reservation: Reservation, config: SwitchboardClientConfig);
574
+ send(data: ReadableStream<Uint8Array>): Promise<AttachmentUploadResult>;
575
+ }
576
+ //#endregion
577
+ //#region src/switchboard/remote-attachment-upload-factory.d.ts
578
+ declare class RemoteAttachmentUploadFactory implements IAttachmentUploadFactory {
579
+ private readonly config;
580
+ constructor(config: SwitchboardClientConfig);
581
+ createUpload(reservation: Reservation): IAttachmentUpload;
582
+ }
583
+ //#endregion
584
+ //#region src/switchboard/remote-attachment-store.d.ts
585
+ declare class RemoteAttachmentStore implements IAttachmentReader {
586
+ private readonly remoteUrl;
587
+ private readonly jwtHandler?;
588
+ private readonly fetchFn;
589
+ constructor(config: SwitchboardClientConfig);
590
+ /**
591
+ * Get attachment metadata. Normally returns a pending AttachmentHeader
592
+ * (status: 'pending') when the server responds 202 with a full
593
+ * Attachment-Pending header. When only expiresAtUtc is present in the
594
+ * header (degraded wire), throws AttachmentPending instead -- the
595
+ * AttachmentPending throw is the degraded-wire case.
596
+ */
597
+ stat(hash: AttachmentHash): Promise<AttachmentHeader>;
598
+ get(hash: AttachmentHash, signal?: AbortSignal): Promise<AttachmentResponse>;
599
+ private fetchAttachment;
600
+ }
601
+ //#endregion
602
+ //#region src/switchboard/create-remote-attachment-service.d.ts
603
+ declare function createRemoteAttachmentService(config: SwitchboardClientConfig): IAttachmentService;
604
+ //#endregion
605
+ //#region src/null-attachment-transport.d.ts
606
+ /**
607
+ * No-op transport for deployments without remote sync.
608
+ * fetch() always returns not-found, announce() and push() are no-ops.
609
+ */
610
+ declare class NullAttachmentTransport implements IAttachmentTransport {
611
+ fetch(): Promise<TransportFetchResult>;
612
+ announce(): Promise<void>;
613
+ push(): Promise<void>;
614
+ }
615
+ //#endregion
616
+ export { ReserveAttachmentOptions as A, SizeMismatch as B, AttachmentMetadata as C, AttachmentUploadResult as D, AttachmentTransportConfig as E, AttachmentNotFound as F, AttachmentPending as I, HashMismatch as L, TransportResponse as M, UploadFirstReserveAttachmentOptions as N, HashFirstReserveAttachmentOptions as O, AttachmentAlreadyExists as P, InvalidAttachmentRef as R, AttachmentHeader as S, AttachmentStatus as T, UploadTooLarge as V, IAttachmentTransport as _, RemoteAttachmentUpload as a, IAttachmentUploadFactory as b, SwitchboardAttachmentTransport as c, createRef as d, parseRef as f, IAttachmentStore as g, IAttachmentService as h, RemoteAttachmentUploadFactory as i, TransportFetchResult as j, Reservation as k, SwitchboardTransportConfig as l, IAttachmentReader as m, createRemoteAttachmentService as n, RemoteReservationStore as o, AttachmentService as p, RemoteAttachmentStore as r, SwitchboardClientConfig as s, NullAttachmentTransport as t, ParsedRef as u, IAttachmentTransportFactory as v, AttachmentResponse as w, IReservationStore as x, IAttachmentUpload as y, ReservationNotFound as z };
617
+ //# sourceMappingURL=null-attachment-transport-BBhQIk5A.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"null-attachment-transport-BBhQIk5A.d.ts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/interfaces.ts","../src/attachment-service.ts","../src/ref.ts","../src/switchboard/switchboard-attachment-transport.ts","../src/switchboard/remote-reservation-store.ts","../src/switchboard/remote-attachment-upload.ts","../src/switchboard/remote-attachment-upload-factory.ts","../src/switchboard/remote-attachment-store.ts","../src/switchboard/create-remote-attachment-service.ts","../src/null-attachment-transport.ts"],"mappings":"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"}