@powerhousedao/reactor-attachments 6.2.3-dev.5 → 6.2.3-dev.51

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,327 @@
1
+ import { C as AttachmentUploadResult, D as ReserveAttachmentOptions, E as Reservation, O as TransportFetchResult, _ as AttachmentResponse, a as IAttachmentTransport, c as IAttachmentUploadFactory, f as AttachmentDownloadOptions, h as AttachmentHeader, l as IReservationStore, m as AttachmentDownloadTargetOptions, n as IAttachmentReader, p as AttachmentDownloadTarget, r as IAttachmentService, s as IAttachmentUpload, t as IAttachmentBackend, v as AttachmentSendOptions, w as AttachmentUploadTarget, y as AttachmentStatOptions } from "./interfaces-jHW9JXv1.js";
2
+ import { AttachmentHash, AttachmentRef, JwtHandler } from "@powerhousedao/reactor";
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
+ /** The reserve metadata field that failed validation. */
23
+ type AttachmentMetadataField = "mimeType" | "fileName" | "extension";
24
+ /**
25
+ * Thrown when reserve metadata (MIME type, file name or extension) is not
26
+ * acceptable. Route handlers should map this to HTTP 400 Bad Request.
27
+ */
28
+ declare class InvalidAttachmentMetadata extends Error {
29
+ readonly field: AttachmentMetadataField;
30
+ constructor(field: AttachmentMetadataField);
31
+ }
32
+ /**
33
+ * Thrown when an upload exceeds the configured maximum byte cap.
34
+ * Route handlers should map this to HTTP 413 Payload Too Large.
35
+ */
36
+ declare class UploadTooLarge extends Error {
37
+ readonly maxBytes: number;
38
+ constructor(maxBytes: number);
39
+ }
40
+ /**
41
+ * Thrown by reserve() when the claimed hash is already available in the store.
42
+ * The caller should use err.ref directly and upload nothing -- this is the
43
+ * dedup fast path: duplicate content never leaves the client.
44
+ */
45
+ declare class AttachmentAlreadyExists extends Error {
46
+ readonly hash: AttachmentHash;
47
+ readonly ref: AttachmentRef;
48
+ constructor(hash: AttachmentHash, ref: AttachmentRef);
49
+ }
50
+ /**
51
+ * Thrown by send() when the server-computed hash of the uploaded bytes
52
+ * does not match the hash claimed at reservation time. Nothing is committed;
53
+ * the reservation is retained so the client can retry with correct bytes.
54
+ */
55
+ declare class HashMismatch extends Error {
56
+ readonly claimed: AttachmentHash;
57
+ readonly actual: AttachmentHash;
58
+ constructor(claimed: AttachmentHash, actual: AttachmentHash);
59
+ }
60
+ /**
61
+ * Thrown by send() when the uploaded byte count does not equal the
62
+ * sizeBytes declared at reservation time. The handle may reject
63
+ * mid-stream as soon as the count exceeds the declaration.
64
+ * Nothing is committed; the reservation is retained for retry.
65
+ *
66
+ * "actual" is the byte count received from the stream before aborting --
67
+ * it includes the chunk that crossed the declaration and can exceed bytes
68
+ * persisted. On mid-stream aborts the true total is unknown; at least
69
+ * "actual" bytes were sent.
70
+ */
71
+ declare class SizeMismatch extends Error {
72
+ readonly declared: number;
73
+ readonly actual: number;
74
+ constructor(declared: number, actual: number);
75
+ }
76
+ /**
77
+ * Thrown by get() when the hash is reserved by an in-flight upload and
78
+ * bytes are not yet available anywhere. Deliberately NOT a subclass of
79
+ * AttachmentNotFound -- callers must distinguish "retry later" from "unknown".
80
+ * After expiresAtUtc has passed the hash reads as not found.
81
+ *
82
+ * metadata is populated when the reservation is local and its fields are
83
+ * known (mimeType, fileName, sizeBytes). It is undefined when the pending
84
+ * state is learned from a remote transport that did not supply the full
85
+ * Attachment-Pending header (transport-pending / degraded wire case).
86
+ */
87
+ type AttachmentTransferStage = "download-target" | "switchboard-get" | "presigned-get" | "presigned-put";
88
+ /**
89
+ * Thrown when a remote transfer step fails. Identifies the stage only; it
90
+ * intentionally carries no URL, signature query, bucket key, or bearer
91
+ * material so it is always safe to log or surface.
92
+ */
93
+ declare class AttachmentTransferError extends Error {
94
+ readonly stage: AttachmentTransferStage;
95
+ readonly status: number | undefined;
96
+ constructor(stage: AttachmentTransferStage, status?: number);
97
+ }
98
+ declare class AttachmentPending extends Error {
99
+ readonly hash: AttachmentHash;
100
+ readonly expiresAtUtc: string;
101
+ readonly metadata: {
102
+ readonly mimeType: string;
103
+ readonly fileName: string;
104
+ readonly sizeBytes: number;
105
+ } | undefined;
106
+ constructor(hash: AttachmentHash, expiresAtUtc: string, meta?: {
107
+ mimeType: string;
108
+ fileName: string;
109
+ sizeBytes: number;
110
+ });
111
+ }
112
+ //#endregion
113
+ //#region src/targets.d.ts
114
+ declare function parseAttachmentUploadTarget(value: unknown): AttachmentUploadTarget;
115
+ declare function parseAttachmentDownloadTarget(value: unknown): AttachmentDownloadTarget;
116
+ //#endregion
117
+ //#region src/attachment-service.d.ts
118
+ declare class AttachmentService implements IAttachmentService {
119
+ private readonly store;
120
+ private readonly reservations;
121
+ private readonly uploadFactory;
122
+ private readonly backend?;
123
+ constructor(store: IAttachmentReader, reservations: IReservationStore, uploadFactory: IAttachmentUploadFactory, backend?: IAttachmentBackend | undefined);
124
+ reserve(options: ReserveAttachmentOptions): Promise<IAttachmentUpload>;
125
+ stat(ref: AttachmentRef, options?: AttachmentStatOptions): Promise<AttachmentHeader>;
126
+ get(ref: AttachmentRef, options?: AbortSignal | AttachmentDownloadOptions): Promise<AttachmentResponse>;
127
+ getDownloadTarget(ref: AttachmentRef, options: AttachmentDownloadTargetOptions): Promise<AttachmentDownloadTarget>;
128
+ private reserveHashFirst;
129
+ }
130
+ //#endregion
131
+ //#region src/ref.d.ts
132
+ type ParsedRef = {
133
+ version: number;
134
+ hash: AttachmentHash;
135
+ };
136
+ declare function parseRef(ref: AttachmentRef): ParsedRef;
137
+ declare function createRef(hash: AttachmentHash, version?: number): AttachmentRef;
138
+ //#endregion
139
+ //#region src/switchboard/switchboard-attachment-transport.d.ts
140
+ type SwitchboardTransportConfig = {
141
+ remoteUrl: string;
142
+ jwtHandler?: JwtHandler;
143
+ fetchFn?: typeof fetch;
144
+ };
145
+ declare class SwitchboardAttachmentTransport implements IAttachmentTransport {
146
+ private readonly remoteUrl;
147
+ private readonly jwtHandler?;
148
+ private readonly fetchFn;
149
+ constructor(config: SwitchboardTransportConfig);
150
+ fetch(hash: AttachmentHash, documentId: string, signal?: AbortSignal): Promise<TransportFetchResult>;
151
+ announce(_hash: AttachmentHash): Promise<void>;
152
+ push(hash: AttachmentHash, remote: string, data: ReadableStream<Uint8Array>): Promise<void>;
153
+ private parsePendingExpiry;
154
+ private parseMetadataHeaders;
155
+ }
156
+ //#endregion
157
+ //#region src/switchboard/upload-transport.d.ts
158
+ /**
159
+ * The seam every attachment upload PUT goes through.
160
+ *
161
+ * It exists because `fetch` cannot report upload-side progress: there is no
162
+ * event between "request issued" and "response received". Naming the transport
163
+ * lets an implementation that *can* count bytes (see
164
+ * `createXhrUploadTransport`) be substituted without the upload code knowing
165
+ * which one it holds — and it is also the right seam for a future multipart
166
+ * upload, which needs one request per part.
167
+ */
168
+ /**
169
+ * Headers are forwarded VERBATIM. A presigned target's headers are part of a
170
+ * signature: normalizing their casing, or adding so much as one header,
171
+ * invalidates it.
172
+ */
173
+ type AttachmentUploadRequest = {
174
+ url: string;
175
+ method: "PUT";
176
+ headers: Record<string, string>;
177
+ body: Blob;
178
+ /** Called with cumulative bytes handed to the socket, when observable. */
179
+ onProgress?: (loaded: number, total: number) => void;
180
+ signal?: AbortSignal;
181
+ };
182
+ /**
183
+ * The only response surface the upload code reads. A real `Response`
184
+ * satisfies this structurally, which is what lets the fetch transport be an
185
+ * identity pass-through rather than an adapter.
186
+ */
187
+ type AttachmentUploadResponse = {
188
+ readonly status: number;
189
+ readonly statusText: string;
190
+ readonly ok: boolean;
191
+ json(): Promise<unknown>;
192
+ };
193
+ type AttachmentUploadTransport = (request: AttachmentUploadRequest) => Promise<AttachmentUploadResponse>;
194
+ /**
195
+ * The default transport. Ignores `onProgress` — fetch has no upload-side
196
+ * progress event, and silence is how a transport reports that bytes are
197
+ * unobservable.
198
+ */
199
+ declare function createFetchUploadTransport(fetchFn: typeof fetch): AttachmentUploadTransport;
200
+ //#endregion
201
+ //#region src/switchboard/xhr-upload-transport.d.ts
202
+ type XhrUploadTransportOptions = {
203
+ /**
204
+ * Used where `XMLHttpRequest` does not exist (Node). Defaults to the global
205
+ * fetch, resolved at call time.
206
+ */
207
+ fetchFn?: typeof fetch;
208
+ };
209
+ /**
210
+ * Upload transport backed by `XMLHttpRequest`, the only browser API that
211
+ * reports upload-side byte progress (`xhr.upload.onprogress`). Everything else
212
+ * about the request is identical to the fetch path.
213
+ *
214
+ * Capability detection happens **inside** the returned function, never at
215
+ * module load: this module is reachable from the client entry, which is
216
+ * executed in Node by the entrypoint tests, and Node has no
217
+ * `XMLHttpRequest`. Detecting per call also means a test can install a fake on
218
+ * `globalThis` without any module-registry reset.
219
+ */
220
+ declare function createXhrUploadTransport(options?: XhrUploadTransportOptions): AttachmentUploadTransport;
221
+ //#endregion
222
+ //#region src/switchboard/remote-reservation-store.d.ts
223
+ type SwitchboardClientConfig = {
224
+ remoteUrl: string;
225
+ jwtHandler?: JwtHandler;
226
+ fetchFn?: typeof fetch;
227
+ /**
228
+ * Transport for upload PUTs only, so a browser host can opt into
229
+ * XMLHttpRequest and get real upload progress.
230
+ *
231
+ * An explicit `fetchFn` always wins over this. The precedence is
232
+ * one-directional on purpose: under this rule, adding `uploadTransport` to a
233
+ * config that already pins `fetchFn` is a provable no-op, whereas the
234
+ * reverse rule would let `{ ...config, uploadTransport }` silently route the
235
+ * largest request in the system around a test's mock and onto the network.
236
+ */
237
+ uploadTransport?: AttachmentUploadTransport;
238
+ };
239
+ declare class RemoteReservationStore implements IReservationStore {
240
+ private readonly remoteUrl;
241
+ private readonly jwtHandler?;
242
+ private readonly fetchFn;
243
+ constructor(config: SwitchboardClientConfig);
244
+ create(options: ReserveAttachmentOptions): Promise<Reservation>;
245
+ get(reservationId: string): Promise<Reservation>;
246
+ delete(reservationId: string): Promise<void>;
247
+ deleteExpired(): Promise<number>;
248
+ }
249
+ //#endregion
250
+ //#region src/switchboard/remote-attachment-upload.d.ts
251
+ declare class RemoteAttachmentUpload implements IAttachmentUpload {
252
+ readonly reservationId: string;
253
+ readonly ref: AttachmentRef | null;
254
+ readonly expiresAtUtc: string;
255
+ readonly uploadTarget?: AttachmentUploadTarget;
256
+ private readonly reservation;
257
+ private readonly remoteUrl;
258
+ private readonly jwtHandler?;
259
+ private readonly uploadTransport;
260
+ constructor(reservation: Reservation, config: SwitchboardClientConfig);
261
+ send(data: ReadableStream<Uint8Array>, options?: AttachmentSendOptions): Promise<AttachmentUploadResult>;
262
+ /**
263
+ * Direct provider upload: PUT the bytes to the presigned URL with exactly
264
+ * the returned headers — never the Switchboard JWT — and treat any 2xx as
265
+ * final success with no follow-up control request. The result is
266
+ * synthesized from the hash-first reservation, which is the only path that
267
+ * can produce a presigned target.
268
+ */
269
+ private sendPresigned;
270
+ }
271
+ //#endregion
272
+ //#region src/switchboard/remote-attachment-upload-factory.d.ts
273
+ declare class RemoteAttachmentUploadFactory implements IAttachmentUploadFactory {
274
+ private readonly config;
275
+ constructor(config: SwitchboardClientConfig);
276
+ createUpload(reservation: Reservation): IAttachmentUpload;
277
+ }
278
+ //#endregion
279
+ //#region src/switchboard/remote-attachment-store.d.ts
280
+ declare class RemoteAttachmentStore implements IAttachmentReader {
281
+ private readonly remoteUrl;
282
+ private readonly jwtHandler?;
283
+ private readonly fetchFn;
284
+ constructor(config: SwitchboardClientConfig);
285
+ /**
286
+ * Get attachment metadata. Normally returns a pending AttachmentHeader
287
+ * (status: 'pending') when the server responds 202 with a full
288
+ * Attachment-Pending header. When only expiresAtUtc is present in the
289
+ * header (degraded wire), throws AttachmentPending instead -- the
290
+ * AttachmentPending throw is the degraded-wire case.
291
+ */
292
+ stat(hash: AttachmentHash, documentId?: string): Promise<AttachmentHeader>;
293
+ get(hash: AttachmentHash, signal?: AbortSignal, documentId?: string): Promise<AttachmentResponse>;
294
+ /**
295
+ * Asks Switchboard for an authorized download target. The request carries
296
+ * the JWT; the response is runtime-validated before any byte transfer.
297
+ * Public so callers can mint direct URLs (previews, share links) without
298
+ * transferring bytes; `expiresIn` requests a caller-chosen lifetime.
299
+ */
300
+ getDownloadTarget(hash: AttachmentHash, options: AttachmentDownloadTargetOptions): Promise<AttachmentDownloadTarget>;
301
+ /**
302
+ * Executes a presigned GET with exactly the returned headers and no JWT.
303
+ * A provider 404 means the object is missing despite available metadata
304
+ * (the accepted abandoned-upload trade-off) and surfaces as the same typed
305
+ * not-found error callers already handle.
306
+ */
307
+ private fetchPresigned;
308
+ private fetchAttachment;
309
+ }
310
+ //#endregion
311
+ //#region src/switchboard/create-remote-attachment-service.d.ts
312
+ declare function createRemoteAttachmentService(config: SwitchboardClientConfig): IAttachmentService;
313
+ //#endregion
314
+ //#region src/null-attachment-transport.d.ts
315
+ /**
316
+ * No-op transport for deployments without remote sync.
317
+ * fetch() always returns not-found, announce() and push() are no-ops.
318
+ */
319
+ declare class NullAttachmentTransport implements IAttachmentTransport {
320
+ fetch(): Promise<TransportFetchResult>;
321
+ announce(): Promise<void>;
322
+ push(): Promise<void>;
323
+ }
324
+ //#endregion
325
+ export { InvalidAttachmentRef as A, AttachmentMetadataField as C, AttachmentTransferStage as D, AttachmentTransferError as E, SizeMismatch as M, UploadTooLarge as N, HashMismatch as O, AttachmentAlreadyExists as S, AttachmentPending as T, createRef as _, RemoteAttachmentUpload as a, parseAttachmentDownloadTarget as b, XhrUploadTransportOptions as c, AttachmentUploadResponse as d, AttachmentUploadTransport as f, ParsedRef as g, SwitchboardTransportConfig as h, RemoteAttachmentUploadFactory as i, ReservationNotFound as j, InvalidAttachmentMetadata as k, createXhrUploadTransport as l, SwitchboardAttachmentTransport as m, createRemoteAttachmentService as n, RemoteReservationStore as o, createFetchUploadTransport as p, RemoteAttachmentStore as r, SwitchboardClientConfig as s, NullAttachmentTransport as t, AttachmentUploadRequest as u, parseRef as v, AttachmentNotFound as w, parseAttachmentUploadTarget as x, AttachmentService as y };
326
+ export {};
327
+ //# sourceMappingURL=null-attachment-transport-dg7vi6F4.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"null-attachment-transport-dg7vi6F4.d.ts","names":[],"sources":["../src/errors.ts","../src/targets.ts","../src/attachment-service.ts","../src/ref.ts","../src/switchboard/switchboard-attachment-transport.ts","../src/switchboard/upload-transport.ts","../src/switchboard/xhr-upload-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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"}