/** * Structural surface @shade/files needs from a Shade instance. * * Defining this locally — instead of `import type { Shade } from '@shade/sdk'` * — breaks the @shade/sdk ↔ @shade/files dependency cycle. Without this * break, a consumer that installs @shade/sdk from a registry ends up with * two distinct `Shade` classes in `node_modules` (one from * `@shade/sdk/node_modules/@shade/files/.../Shade`, one from * `@shade/sdk/Shade`). TypeScript treats them as nominally different types, * raising `this is not assignable to Shade` from inside SDK methods that * pass `this` into `createFilesNamespace`. * * The Shade class structurally implements every member listed below, so * `createFilesNamespace(this)` from the SDK side compiles regardless of * how many copies of @shade/sdk a consumer's package manager installs. * * Member signatures match Shade's exactly so this is a structural * subtype, not a parallel API. */ import type { ShadeEnvelope } from '@shade/core'; import type { IncomingTransfer, TransferHandle, TransferOptions, } from '@shade/transfer'; import type { ObservabilityHook } from '@shade/observability'; export interface ShadeBridge { /** Address that names this Shade instance to peers. */ readonly myAddress: string; /** Encrypt + send `plaintext` to `peer`; returns the wire envelope. */ send(peer: string, plaintext: string): Promise; /** * Decrypt an inbound envelope from `peer` and return the plaintext. * Used by the request-response RPC route on the server side. */ receive(peer: string, envelope: ShadeEnvelope): Promise; /** * Subscribe to incoming ratchet plaintext. Returns an unsubscribe. * Handlers may be sync or async; async handlers are awaited in * registration order. */ onMessage( handler: (from: string, plaintext: string) => void | Promise, ): () => void; /** * Upload bytes via the SDK's transfer engine. Required when the bridge * is used with `streams` content I/O (read/write > 256 KiB). */ upload(opts: TransferOptions): Promise; /** Subscribe to incoming transfers initiated by a peer. */ onIncomingTransfer( handler: (incoming: IncomingTransfer) => void | Promise, ): Promise<() => void>; /** Fingerprint accessor for the trust-gate hooks. */ getFingerprintFor(peer: string): Promise; /** * Optional inheritable observability bus. Files inherits the bus when * the SDK passes one in via the namespace; otherwise files runs without * observability hooks. */ getObservability?(): ObservabilityHook | undefined; /** Optional control-envelope passthrough used by the WebRTC bridge. */ deliverControlEnvelope?(peer: string, envelope: ShadeEnvelope): Promise; /** * Hand a freshly-decoded wire envelope (control or chunk) to the * transfer engine. Required by the pull-mode HTTP client when it * drains queued events from the server: each polled chunk / control * envelope is dispatched here so the engine sees it just as if it * had arrived via an HTTP POST on `/v1/transfer/...`. */ acceptTransferEnvelope?(from: string, env: ShadeEnvelope | Uint8Array): Promise; /** * Configure the transfer stack. Called by the pull-mode HTTP client * to point the browser's outgoing chunks + control envelopes at the * server's transferQueueRoute mount. Optional because the * server-to-server path uses a separate, app-driven configuration. */ configureTransfers?(opts: { resolveBaseUrl?: (peerAddress: string) => Promise; transport?: unknown; envelopeTransport?: unknown; }): void; }