@hediet/linkrpc 0.0.1
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.
- package/README.md +383 -0
- package/dist/chunks/_empty-crypto-Bi0tGx5K.js +8 -0
- package/dist/chunks/boundedTrafficSubscription-1L592xc7.js +1126 -0
- package/dist/chunks/boundedTrafficSubscription-1L592xc7.js.map +1 -0
- package/dist/chunks/hub.interfaces-BzWfsVT2.js +526 -0
- package/dist/chunks/hub.interfaces-BzWfsVT2.js.map +1 -0
- package/dist/chunks/hubAccess-DwTZPiI8.d.ts +79 -0
- package/dist/chunks/hubAccess-DwTZPiI8.d.ts.map +1 -0
- package/dist/chunks/hubFacade-CQflVkVC.js +85 -0
- package/dist/chunks/hubFacade-CQflVkVC.js.map +1 -0
- package/dist/chunks/hubFacade-Dkgw2pTi.d.ts +101 -0
- package/dist/chunks/hubFacade-Dkgw2pTi.d.ts.map +1 -0
- package/dist/chunks/linkRpcConnection-CtlQmetO.d.ts +3623 -0
- package/dist/chunks/linkRpcConnection-CtlQmetO.d.ts.map +1 -0
- package/dist/chunks/rolldown-runtime-4LSo1kEK.js +17 -0
- package/dist/chunks/src-D3NUIwyo.js +7795 -0
- package/dist/chunks/src-D3NUIwyo.js.map +1 -0
- package/dist/hub/client/index.d.ts +50 -0
- package/dist/hub/client/index.d.ts.map +1 -0
- package/dist/hub/client/index.js +97 -0
- package/dist/hub/client/index.js.map +1 -0
- package/dist/hub/common/index.d.ts +1189 -0
- package/dist/hub/common/index.d.ts.map +1 -0
- package/dist/hub/common/index.js +267 -0
- package/dist/hub/common/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/inspection/index.d.ts +66 -0
- package/dist/inspection/index.d.ts.map +1 -0
- package/dist/inspection/index.js +6 -0
- package/dist/node.d.ts +548 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +1087 -0
- package/dist/node.js.map +1 -0
- package/dist/web.d.ts +44 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +58 -0
- package/dist/web.js.map +1 -0
- package/package.json +59 -0
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","names":["crypto.generateX25519Keypair","err","crypto.generateKeypair"],"sources":["../src/node/ndjsonTransport.ts","../src/node/initialize.ts","../src/node/stdio.ts","../src/node/webSocketClientTransport.ts","../src/node/hubClient.ts","../src/node/hubReconnect.ts","../src/node/fileManagedIdentityStorage.ts","../src/node/principal.ts","../src/node/headerDelimitedTransport.ts"],"sourcesContent":["import type { JsonRpcMessage } from '../protocol/jsonRpc';\nimport type { IMessageTransport } from '../transport/messageTransport';\n\n/**\n * Newline-delimited JSON transport over a Node Readable/Writable pair.\n * One JSON value per line, both directions.\n *\n * Not LSP-style headers — those add no value for a private link between two\n * cooperating processes and require a length-prefixed framer.\n */\nexport class NdjsonTransport implements IMessageTransport {\n private _listener: ((m: JsonRpcMessage) => void) | undefined;\n private readonly _buffer: JsonRpcMessage[] = [];\n private _residual = '';\n private _closed = false;\n\n constructor(\n private readonly _input: NodeJS.ReadableStream,\n private readonly _output: NodeJS.WritableStream,\n private readonly _onClose?: () => void,\n ) {\n this._input.setEncoding?.('utf8');\n this._input.on('data', (chunk: string) => this._onData(chunk));\n this._input.on('end', () => this._onEnd());\n this._input.on('close', () => this._onEnd());\n this._input.on('error', () => this._onEnd());\n if (!Object.is(this._output, this._input)) {\n this._output.on('error', () => this._onEnd());\n }\n }\n\n public send(message: JsonRpcMessage): void {\n if (this._closed) return;\n this._output.write(JSON.stringify(message) + '\\n');\n }\n\n public setListener(listener: ((m: JsonRpcMessage) => void) | undefined): void {\n this._listener = listener;\n if (listener) {\n while (this._buffer.length > 0 && this._listener) {\n const m = this._buffer.shift()!;\n this._listener(m);\n }\n }\n }\n\n public dispose(): void {\n if (this._closed) return;\n this._closed = true;\n this._onClose?.();\n }\n\n private _onData(chunk: string): void {\n this._residual += chunk;\n let nl: number;\n while ((nl = this._residual.indexOf('\\n')) >= 0) {\n const line = this._residual.slice(0, nl).trim();\n this._residual = this._residual.slice(nl + 1);\n if (!line) continue;\n let parsed: JsonRpcMessage;\n try {\n parsed = JSON.parse(line) as JsonRpcMessage;\n } catch {\n continue;\n }\n this._deliver(parsed);\n }\n }\n\n private _onEnd(): void {\n if (!this._closed) {\n this._closed = true;\n this._onClose?.();\n }\n }\n\n private _deliver(m: JsonRpcMessage): void {\n if (this._listener) this._listener(m);\n else this._buffer.push(m);\n }\n}\n","import { ErrorCode, isRequest, type JsonRpcMessage } from '../protocol/jsonRpc';\nimport type { JsonValue } from '../protocol/jsonValue';\nimport {\n type IMessageTransport,\n type MessageTransportTrace,\n traceMessageTransport,\n} from '../transport/messageTransport';\nimport { NdjsonTransport } from './ndjsonTransport';\n\n/**\n * Reserved transport-handshake method. Sent as the very first message on a\n * connection that authenticates and/or negotiates transport details. It is\n * handled entirely by the transport layer (via {@link connectNdjson}) and is\n * never forwarded to the hub or any service — it is not a routed call.\n */\nexport const INITIALIZE_METHOD = 'hubrpc::initialize';\n/** Transitional alias accepted by servers created during the LinkRPC wire-name migration. */\nexport const LINKRPC_INITIALIZE_METHOD_ALIAS = 'linkrpc::initialize';\n\n/** Current transport protocol version. */\nexport const INITIALIZE_PROTOCOL_VERSION = 1;\n\n/** Default time (ms) to wait for the handshake message before giving up. */\nconst DEFAULT_HANDSHAKE_TIMEOUT_MS = 10_000;\n\n/** Fixed request id for the initiator's `hubrpc::initialize` request. */\nconst INITIALIZE_REQUEST_ID = 0;\n\nexport interface InitializeParams {\n readonly protocolVersion: number;\n /** Shared-secret auth token, when the transport requires one. */\n readonly token?: string;\n}\n\nexport interface InitializeResult {\n readonly protocolVersion: number;\n}\n\n/**\n * The handshake role for a connection:\n * - `client`: send `hubrpc::initialize` and await the reply (the dialing side).\n * - `server`: require `hubrpc::initialize` as the first message, validate the\n * token, and reply (the accepting side).\n */\nexport type InitializeRole =\n | { readonly kind: 'client'; readonly token?: string; }\n | {\n readonly kind: 'server';\n readonly isTokenAccepted: (token: string | undefined) => Promise<boolean>;\n };\n\nexport interface ConnectNdjsonOptions {\n readonly input: NodeJS.ReadableStream;\n readonly output: NodeJS.WritableStream;\n readonly onClose?: () => void;\n /**\n * Run a `hubrpc::initialize` handshake before the transport goes live. Omit\n * for trusted links that need neither auth nor negotiation (e.g. stdio).\n */\n readonly initialize?: InitializeRole;\n /** Observe all messages, including the initialize handshake. */\n readonly trace?: MessageTransportTrace;\n /** Override the handshake timeout (ms). */\n readonly handshakeTimeoutMs?: number;\n}\n\nexport interface ConnectedNdjson {\n /**\n * The connected transport, already past the handshake. Callers never see\n * the pre-handshake transport, so the \"initialize is the first message\"\n * invariant holds structurally and the wire setup stays free to evolve.\n */\n readonly transport: IMessageTransport;\n /** The token presented by the peer (server role); `undefined` otherwise. */\n readonly token?: string;\n}\n\n/**\n * The single supported way to build an ndjson transport. Constructs the\n * transport over `input`/`output` and, when {@link ConnectNdjsonOptions.initialize}\n * is set, runs the `hubrpc::initialize` handshake internally before resolving.\n *\n * Rejects (after disposing the transport) when the handshake fails — a bad or\n * missing token, a wrong/absent first message, or a timeout. The accepting side\n * should treat a rejection as \"drop this connection\".\n */\nexport async function connectNdjson(opts: ConnectNdjsonOptions): Promise<ConnectedNdjson> {\n const role = opts.initialize;\n let rejectClosedHandshake: ((error: Error) => void) | undefined;\n const closedDuringHandshake = role\n ? new Promise<never>((_resolve, reject) => {\n rejectClosedHandshake = reject;\n })\n : undefined;\n const baseTransport = new NdjsonTransport(opts.input, opts.output, () => {\n try {\n opts.onClose?.();\n } finally {\n rejectClosedHandshake?.(new Error('hubrpc::initialize: transport closed during handshake'));\n }\n });\n const transport = opts.trace === undefined\n ? baseTransport\n : traceMessageTransport(baseTransport, opts.trace);\n\n if (!role) {\n return { transport };\n }\n\n try {\n const { token } = await Promise.race([\n runInitializeHandshake(transport, role, {\n ...(opts.handshakeTimeoutMs !== undefined ? { handshakeTimeoutMs: opts.handshakeTimeoutMs } : {}),\n }),\n closedDuringHandshake!,\n ]);\n rejectClosedHandshake = undefined;\n return { transport, ...(token !== undefined ? { token } : {}) };\n } catch (err) {\n rejectClosedHandshake = undefined;\n transport.dispose();\n throw err;\n }\n}\n\nexport interface RunInitializeHandshakeOptions {\n /** Override the handshake timeout (ms). */\n readonly handshakeTimeoutMs?: number;\n}\n\n/**\n * Run the `hubrpc::initialize` handshake on an already-constructed transport.\n * Used for transports that the caller builds itself (e.g. WebSocket), where\n * {@link connectNdjson} does not apply. On failure it throws but does NOT\n * dispose the transport — the caller owns it and decides how to tear down.\n *\n * For ndjson links, prefer {@link connectNdjson}, which constructs the\n * transport and runs this handshake atomically.\n */\nexport async function runInitializeHandshake(\n transport: IMessageTransport,\n role: InitializeRole,\n options: RunInitializeHandshakeOptions = {},\n): Promise<{ readonly token?: string; }> {\n const timeoutMs = options.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS;\n if (role.kind === 'client') {\n await _runClientHandshake(transport, role.token, timeoutMs);\n return {};\n }\n const token = await _runServerHandshake(transport, role.isTokenAccepted, timeoutMs);\n return { token };\n}\n\nasync function _runClientHandshake(\n transport: IMessageTransport,\n token: string | undefined,\n timeoutMs: number,\n): Promise<void> {\n const reply = _nextMessage(transport, timeoutMs);\n const params: InitializeParams = {\n protocolVersion: INITIALIZE_PROTOCOL_VERSION,\n ...(token !== undefined ? { token } : {}),\n };\n void transport.send({\n jsonrpc: '2.0',\n id: INITIALIZE_REQUEST_ID,\n method: INITIALIZE_METHOD,\n params: params as unknown as JsonValue,\n });\n const message = await reply;\n if (isRequest(message) || !('id' in message) || message.id !== INITIALIZE_REQUEST_ID) {\n throw new Error('hubrpc::initialize: unexpected reply to handshake');\n }\n if ('error' in message) {\n throw new Error(`hubrpc::initialize rejected: ${message.error.message}`);\n }\n}\n\nasync function _runServerHandshake(\n transport: IMessageTransport,\n isTokenAccepted: (token: string | undefined) => Promise<boolean>,\n timeoutMs: number,\n): Promise<string | undefined> {\n const first = await _nextMessage(transport, timeoutMs);\n if (\n !isRequest(first)\n || (\n first.method !== INITIALIZE_METHOD\n && first.method !== LINKRPC_INITIALIZE_METHOD_ALIAS\n )\n ) {\n throw new Error('hubrpc::initialize: expected initialize as the first message');\n }\n const params = (first.params ?? {}) as Partial<InitializeParams>;\n if (!(await isTokenAccepted(params.token))) {\n void transport.send({\n jsonrpc: '2.0',\n id: first.id,\n error: { code: ErrorCode.invalidRequest, message: 'unauthenticated' },\n });\n throw new Error('hubrpc::initialize: unauthenticated');\n }\n const result: InitializeResult = { protocolVersion: INITIALIZE_PROTOCOL_VERSION };\n void transport.send({\n jsonrpc: '2.0',\n id: first.id,\n result: result as unknown as JsonValue,\n });\n return params.token;\n}\n\n/**\n * Consume exactly one incoming message, then detach. Relies on\n * {@link NdjsonTransport}'s buffering: setting the listener to `undefined` from\n * inside the callback stops the buffer drain, leaving any later messages queued\n * for the real listener the channel attaches afterwards.\n */\nfunction _nextMessage(transport: IMessageTransport, timeoutMs: number): Promise<JsonRpcMessage> {\n return new Promise<JsonRpcMessage>((resolve, reject) => {\n const timer = setTimeout(() => {\n transport.setListener(undefined);\n reject(new Error('hubrpc::initialize: handshake timed out'));\n }, timeoutMs);\n transport.setListener((message) => {\n clearTimeout(timer);\n transport.setListener(undefined);\n resolve(message);\n });\n });\n}\n","import { type ChildProcess, spawn } from 'node:child_process';\nimport { connectNdjson } from './initialize';\nimport type { Channel } from '../connection/channel';\nimport type { IDisposable } from '../disposable';\nimport { LinkRpcConnection } from '../connection/linkRpcConnection';\nimport { JsonRpcChannel } from '../connection/jsonRpcChannel';\n\n/**\n * Spawn a child process and connect to its stdio as a linkrpc connection.\n *\n * Pass a single command line (split on whitespace) or an array `[cmd, ...args]`.\n * The child's stderr is piped to the parent's stderr so logs surface naturally.\n *\n * @example\n * const c = await connectToCmdStdio(\"node ./ghConnector.js\");\n * const gh = c.get(ghInterface);\n * await gh.createIssue({ title: \"...\" });\n */\nexport async function connectToCmdStdio(cmd: string | readonly string[]): Promise<LinkRpcConnection> {\n const parts = typeof cmd === 'string' ? cmd.split(/\\s+/).filter(Boolean) : [...cmd];\n if (parts.length === 0) throw new Error('connectToCmdStdio: empty command');\n const [bin, ...args] = parts;\n const child: ChildProcess = spawn(bin, args, {\n stdio: ['pipe', 'pipe', 'inherit'],\n });\n if (!child.stdin || !child.stdout) {\n throw new Error('connectToCmdStdio: child has no stdio');\n }\n const { transport } = await connectNdjson({\n input: child.stdout,\n output: child.stdin,\n onClose: () => {\n if (!child.killed) child.kill();\n },\n });\n return LinkRpcConnection.fromTransport(transport);\n}\n\n/**\n * For the child side: a linkrpc connection over this process's stdin/stdout.\n * The child MUST NOT write user output to stdout — only RPC messages — or\n * the parent's parser will choke.\n */\nexport async function serveOnStdio(): Promise<LinkRpcConnection> {\n const { transport } = await connectNdjson({ input: process.stdin, output: process.stdout });\n return LinkRpcConnection.fromTransport(transport);\n}\n\n/**\n * A raw, unsigned channel over this process's stdin/stdout — the stdio\n * counterpart to `openHubChannel`. It *is* a {@link Channel} (so it plugs\n * straight into {@link SigningSender.wrapChannel} / `new LinkRpcConnection`),\n * augmented with a close signal for stdin end. Use {@link serveOnStdio}\n * instead when no signing is needed.\n */\nexport type StdioChannel = Channel<undefined, unknown> & {\n /** Fires once when stdin ends/closes. Returns a disposable to unsubscribe. */\n onClose(listener: () => void): IDisposable;\n};\n\nexport async function openStdioChannel(): Promise<StdioChannel> {\n const { transport } = await connectNdjson({ input: process.stdin, output: process.stdout });\n const channel = JsonRpcChannel.create(transport);\n\n const closeListeners = new Set<() => void>();\n let closed = false;\n const fireClose = () => {\n if (closed) return;\n closed = true;\n for (const l of closeListeners) {\n try {\n l();\n } catch { /* ignore */ }\n }\n closeListeners.clear();\n };\n process.stdin.on('end', fireClose);\n process.stdin.on('close', fireClose);\n\n return Object.assign(channel, {\n onClose: (listener: () => void) => {\n if (closed) {\n queueMicrotask(listener);\n return { dispose: () => { } };\n }\n closeListeners.add(listener);\n return { dispose: () => closeListeners.delete(listener) };\n },\n });\n}\n","import type { JsonRpcMessage } from '../protocol/jsonRpc';\nimport type { IMessageTransport } from '../transport/messageTransport';\n\n/**\n * Client-side WebSocket transport: one JSON-RPC message per text frame.\n * Mirror of the hub's server-side `WebSocketTransport`, kept here so the\n * core node entry can reach a `ws://` / `wss://` hub without depending on\n * `@hediet/linkrpc-hub`.\n *\n * Uses the platform-global `WebSocket` (Node 22+, browsers), so no `ws`\n * package dependency is required on the client side.\n *\n * Takes ownership of the socket: {@link dispose} closes it, and a peer\n * close / error fires `onClose` exactly once.\n */\nexport class WebSocketTransport implements IMessageTransport<JsonRpcMessage, JsonRpcMessage> {\n private _listener: ((m: JsonRpcMessage) => void) | undefined;\n private readonly _buffer: JsonRpcMessage[] = [];\n private _closed = false;\n\n constructor(\n private readonly _ws: WebSocket,\n private readonly _onClose?: () => void,\n ) {\n _ws.binaryType = 'arraybuffer';\n _ws.addEventListener('message', (event: MessageEvent) => {\n const data = event.data;\n const text = typeof data === 'string' ?\n data :\n data instanceof ArrayBuffer ?\n new TextDecoder().decode(data) :\n ArrayBuffer.isView(data) ?\n new TextDecoder().decode(data as ArrayBufferView) :\n String(data);\n for (const line of text.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n let parsed: JsonRpcMessage;\n try {\n parsed = JSON.parse(trimmed) as JsonRpcMessage;\n } catch {\n continue;\n }\n this._deliver(parsed);\n }\n });\n const onEnd = () => {\n if (this._closed) return;\n this._closed = true;\n this._onClose?.();\n };\n _ws.addEventListener('close', onEnd);\n _ws.addEventListener('error', onEnd);\n }\n\n public send(message: JsonRpcMessage): void {\n if (this._closed) return;\n if (this._ws.readyState !== WebSocket.OPEN) return;\n this._ws.send(JSON.stringify(message));\n }\n\n public setListener(listener: ((m: JsonRpcMessage) => void) | undefined): void {\n this._listener = listener;\n if (listener) {\n while (this._buffer.length > 0 && this._listener) {\n const m = this._buffer.shift()!;\n this._listener(m);\n }\n }\n }\n\n public dispose(): void {\n if (this._closed) return;\n this._closed = true;\n try {\n this._ws.close();\n } catch { /* ignore */ }\n this._onClose?.();\n }\n\n private _deliver(m: JsonRpcMessage): void {\n if (this._listener) this._listener(m);\n else this._buffer.push(m);\n }\n}\n\n/** Options for {@link openWebSocket}. */\nexport interface OpenWebSocketOptions {\n /** Extra request headers to send on the upgrade. */\n readonly headers?: Record<string, string>;\n}\n\n/**\n * Open a WebSocket to `url` and resolve once it is connected. Rejects if the\n * socket errors before open.\n *\n * Authentication is NOT done here: the hub's WebSocket server authenticates\n * over the in-band `hubrpc::initialize` handshake (so browsers, which cannot\n * set request headers on the `WebSocket` constructor, work too). Run\n * {@link runInitializeHandshake} on the resulting {@link WebSocketTransport}.\n *\n * Headers ride on the upgrade request via the non-standard `headers` option\n * supported by Node's global `WebSocket` (undici); browsers ignore it.\n */\nexport function openWebSocket(\n url: string,\n opts: OpenWebSocketOptions = {},\n): Promise<WebSocket> {\n const headers: Record<string, string> = { ...opts.headers };\n return new Promise<WebSocket>((resolve, reject) => {\n // `headers` is a non-standard undici extension to the WHATWG\n // constructor (second arg is normally `protocols`); cast through.\n const ws = new WebSocket(url, { headers } as unknown as string[]);\n const onOpen = () => {\n ws.removeEventListener('error', onError);\n resolve(ws);\n };\n const onError = (event: Event) => {\n ws.removeEventListener('open', onOpen);\n const message = (event as { message?: string; }).message;\n reject(new Error(message ? `WebSocket error: ${message}` : 'WebSocket connection failed'));\n };\n ws.addEventListener('open', onOpen, { once: true });\n ws.addEventListener('error', onError, { once: true });\n });\n}\n","import * as fs from 'node:fs/promises';\nimport * as net from 'node:net';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { Channel } from '../connection/channel';\nimport { LinkRpcConnection } from '../connection/linkRpcConnection';\nimport { JsonRpcChannel } from '../connection/jsonRpcChannel';\nimport {\n OneShotCapStaging,\n Principal, SigningSender,\n type SigningCallCtx,\n type SigningSenderConfig\n} from '../identity/signingSender';\nimport type { SignedCapability } from '../identity/capability';\nimport {\n base64UrlToBytes,\n bytesToBase64Url,\n type Keypair,\n type PrincipalId,\n principalForPublicKey,\n type X25519Keypair,\n} from '../crypto/cryptoProvider';\nimport * as crypto from '../crypto/crypto';\nimport { signParams } from '../identity/metaEnvelope';\nimport { KeypairSigningIdentity } from '../identity/identity';\nimport type { JsonValue } from '../protocol/jsonValue';\nimport type { JsonRpcMessage } from '../protocol/jsonRpc';\nimport { sha256 } from '../crypto/sha256';\nimport type { IMessageTransport } from '../transport/messageTransport';\nimport { connectNdjson, runInitializeHandshake } from './initialize';\nimport { openWebSocket, WebSocketTransport } from './webSocketClientTransport';\nimport { IDisposable } from '../disposable';\nimport { Hub, hubFromConnection } from '../hub/client/hubFacade';\n\n/** Env var the hub publishes for its endpoint (named pipe / UDS path). */\nexport const LINKRPC_ENDPOINT_VAR = 'LINKRPC_ENDPOINT';\n/** Env var the hub publishes for its shared attribution token. */\nexport const LINKRPC_TOKEN_VAR = 'LINKRPC_TOKEN';\n\nexport interface ConnectToHubOptions {\n /** Defaults to `process.env.LINKRPC_ENDPOINT`. */\n readonly endpoint?: string;\n /** Defaults to `process.env.LINKRPC_TOKEN`. */\n readonly token?: string;\n /**\n * Initial {@link Principal} (identity + persistent caps) for outbound\n * calls. Stored on the returned handle's {@link HubClientHandle.signing}\n * config; mutate that later to install or swap. `undefined` leaves the\n * connection unsigned (plain JSON-RPC) until a principal is installed.\n */\n readonly principal?: Principal;\n /**\n * Initial one-shot capability staging policy. Same lifecycle as\n * {@link principal}; drained per outbound signed call.\n */\n readonly oneShotCaps?: OneShotCapStaging;\n}\n\n/**\n * Mutable signing config consulted per-call by the {@link SigningSender}\n * wrapping a {@link HubClientHandle.connection}. Mutating either field\n * takes effect on the next outbound call. No setter on the sender\n * itself — it is a plain caller-owned {@link SigningSenderConfig}.\n */\nexport type HubSigningHolder = {\n principal?: Principal;\n capProvider?: SigningSenderConfig['capProvider'];\n oneShotCaps?: OneShotCapStaging;\n};\n\nexport interface HubClientHandle {\n /** Full linkrpc connection wrapping the same transport. */\n readonly connection: LinkRpcConnection<undefined, SigningCallCtx>;\n /**\n * Façade over the hub's own serviceId-routed services (`hubGrantedServiceId`,\n * `hubAccess`, …) on this {@link connection}. Use it to read connection\n * facts ({@link Hub.getConnectionInfo}) or claim this connection's granted\n * serviceId namespace ({@link Hub.claimGrantedServiceIdNamespace}) without\n * hand-routing the interface clients.\n */\n readonly hub: Hub;\n /** Configured endpoint + token (in case the caller defaulted from env). */\n readonly endpoint: string;\n readonly token: string;\n /**\n * Mutable signing config. Starts empty (every call goes out\n * unsigned). `installManagedIdentitySigner` and `setupHubSigning`\n * populate this; user code can also drive it directly.\n */\n readonly signing: HubSigningHolder;\n /**\n * Register a callback that fires when the underlying socket closes\n * (peer end, error, or explicit {@link close}). Fires at most once.\n * Returns an unsubscribe function.\n */\n onClose(listener: () => void): IDisposable;\n /** Close the underlying socket and tear everything down. */\n close(): void;\n}\n\n/**\n * Open a connection to a running linkrpc hub. Reads `LINKRPC_ENDPOINT` and\n * `LINKRPC_TOKEN` from the environment unless overridden. Sends the single-\n * line `{\"hello\":1,\"token\":\"...\"}` preamble that the hub's socket server\n * requires, then wraps the socket in an `LinkRpcConnection`.\n *\n * Throws if env vars are missing, if the socket cannot be opened, or if the\n * hub refuses the preamble (the socket simply closes — callers should treat\n * an immediate close of the channel as an auth failure).\n */\nexport async function connectToHub(options: ConnectToHubOptions = {}): Promise<HubClientHandle> {\n const hubChannel = await openHubChannel(options);\n const signing: HubSigningHolder = {\n principal: options.principal,\n oneShotCaps: options.oneShotCaps,\n };\n const channel = SigningSender.wrapChannel(hubChannel, signing);\n const connection = new LinkRpcConnection(channel);\n return {\n connection,\n hub: hubFromConnection(connection),\n endpoint: hubChannel.endpoint,\n token: hubChannel.token,\n signing,\n onClose: hubChannel.onClose,\n close: () => {\n connection.close();\n hubChannel.close();\n },\n };\n}\n\n/** Options for {@link openHubChannel}. Subset of {@link ConnectToHubOptions}. */\nexport interface OpenHubChannelOptions {\n /** Defaults to `process.env.LINKRPC_ENDPOINT`. */\n readonly endpoint?: string;\n /**\n * Defaults to `process.env.LINKRPC_TOKEN`, or `''` when unset. The token\n * is sent in the hello preamble; provenance-authenticated hubs (hubv2)\n * ignore it, so an empty token is valid there.\n */\n readonly token?: string;\n}\n\n/**\n * A raw, unsigned hub channel: the socket transport wrapped only in a\n * {@link JsonRpcChannel}, with no signing applied. It *is* a {@link Channel}\n * (so it plugs straight into {@link SigningSender.wrapChannel} /\n * `new LinkRpcConnection`), augmented with the hub endpoint/token and the\n * socket lifecycle. Identity/signing is composed on top by the caller;\n * {@link connectToHub} is the batteries-included version that adds a\n * mutable signing holder.\n */\nexport type HubChannel = Channel<undefined, unknown> & {\n readonly endpoint: string;\n readonly token: string;\n /**\n * Register a callback that fires when the socket closes. Fires at most\n * once. Returns an unsubscribe function.\n */\n onClose(listener: () => void): IDisposable;\n /** Close the underlying socket. */\n close(): void;\n};\n\n/**\n * Open the hub socket and send the preamble, returning the raw\n * {@link HubChannel} without any signing. Use this when you want to\n * compose identity yourself; otherwise prefer {@link connectToHub}.\n */\nexport async function openHubChannel(\n options: OpenHubChannelOptions = {},\n): Promise<HubChannel> {\n const endpoint = options.endpoint ?? process.env[LINKRPC_ENDPOINT_VAR];\n const token = options.token ?? process.env[LINKRPC_TOKEN_VAR] ?? '';\n if (!endpoint) {\n throw new Error(`${LINKRPC_ENDPOINT_VAR} is not set; cannot connect to linkrpc hub.`);\n }\n\n const closeListeners = new Set<() => void>();\n let closed = false;\n let closeChannel: (() => void) | undefined;\n const fireClose = () => {\n if (closed) return;\n closed = true;\n closeChannel?.();\n for (const l of closeListeners) {\n try {\n l();\n } catch { /* ignore */ }\n }\n closeListeners.clear();\n };\n\n const { transport, destroy } = await _openHubTransport(endpoint, token, fireClose);\n const rpc = JsonRpcChannel.createWithClose(transport);\n closeChannel = rpc.close;\n if (closed) rpc.close();\n return Object.assign(rpc.channel, {\n endpoint,\n token,\n onClose: (listener: () => void) => {\n if (closed) {\n queueMicrotask(listener);\n return { dispose: () => { } };\n }\n closeListeners.add(listener);\n return { dispose: () => closeListeners.delete(listener) };\n },\n close: () => {\n destroy();\n fireClose();\n },\n });\n}\n\n/** True for `ws://` / `wss://` endpoints (case-insensitive). */\nfunction _isWebSocketEndpoint(endpoint: string): boolean {\n return /^wss?:\\/\\//i.test(endpoint);\n}\n\n/**\n * Open the underlying transport for {@link openHubChannel}, picking the\n * scheme from the endpoint:\n * - `ws://` / `wss://` → WebSocket; the token is presented via the\n * `hubrpc::initialize` handshake (browsers cannot set request headers).\n * - anything else → named pipe / UDS; the token is presented via the\n * `hubrpc::initialize` handshake the socket server requires.\n *\n * `onClose` fires once when the peer ends the transport.\n */\nasync function _openHubTransport(\n endpoint: string,\n token: string,\n onClose: () => void,\n): Promise<{ transport: IMessageTransport<JsonRpcMessage, JsonRpcMessage>; destroy: () => void; }> {\n if (_isWebSocketEndpoint(endpoint)) {\n const ws = await openWebSocket(endpoint);\n const transport = new WebSocketTransport(ws, onClose);\n const destroy = () => {\n try {\n ws.close();\n } catch { /* ignore */ }\n };\n try {\n await runInitializeHandshake(transport, { kind: 'client', token });\n } catch (err) {\n transport.dispose();\n destroy();\n throw err;\n }\n return { transport, destroy };\n }\n const socket = await _openSocket(endpoint);\n const { transport } = await connectNdjson({\n input: socket,\n output: socket,\n onClose: () => {\n socket.destroy();\n onClose();\n },\n initialize: { kind: 'client', token },\n });\n return { transport, destroy: () => socket.destroy() };\n}\n\n/**\n * Send the `linkrpc.hub::hubServiceIdRegistry::registerServiceId` call on an open\n * hub connection. In `openMode` the hub accepts the unsigned call directly —\n * pass no `identity`. Outside `openMode` the caller must sign the params\n * with their `identity` keypair (via `signParams`) and present a\n * capability that authorizes the claim — unless the signer is already an\n * admin on the hub, in which case `capabilities` may be omitted.\n *\n * Resolves once the hub has registered the prefix; rejects on denial.\n */\nexport interface RegisterHubPrefixOptions {\n readonly handle: HubClientHandle;\n readonly prefix: string;\n /**\n * Caller's signing identity. Required when the hub is not in openMode.\n * The `principal` must encode the `publicKey` (round-tripped through\n * `principalForPublicKey`). Bound to this transport on first successful\n * `register` — subsequent calls on the same socket may not switch\n * identity.\n */\n readonly identity?: { readonly principal: PrincipalId; readonly keypair: Keypair; };\n /**\n * Capabilities to present. Each must be issued (directly or\n * transitively) by an admin and permit\n * `<prefix>::hubServiceIdRegistry::registerServiceId`. Omit when the signer\n * is already an admin.\n */\n readonly capabilities?: readonly SignedCapability[];\n}\n\nexport async function registerHubPrefix(\n opts: RegisterHubPrefixOptions,\n): Promise<void> {\n let params: Record<string, unknown>;\n if (opts.identity) {\n const signer = new KeypairSigningIdentity(\n opts.identity.principal,\n opts.identity.keypair.privateKey,\n );\n params = await signParams({\n method: 'hubServiceIdRegistry::registerServiceId',\n params: { requestedPrefix: opts.prefix },\n signingIdentity: signer,\n ...(opts.capabilities && opts.capabilities.length > 0 ?\n { capabilities: [...opts.capabilities] } :\n {}),\n });\n } else {\n if (opts.capabilities && opts.capabilities.length > 0) {\n throw new Error('registerHubPrefix: capabilities require identity to be set');\n }\n params = { requestedPrefix: opts.prefix };\n }\n await opts.handle.connection.channel.sendRequest(\n 'hubServiceIdRegistry::registerServiceId',\n params as JsonValue,\n );\n}\n\n// ---- Identity persistence -----------------------------------------------\n\nexport interface LoadOrCreateIdentityOptions {\n /**\n * Stable string that identifies this identity slot. Typically the calling\n * module's `import.meta.filename` — each service then automatically gets\n * its own slot.\n */\n readonly id: string;\n /** Override the storage directory (defaults to a per-user folder). */\n readonly storeDir?: string;\n /**\n * Use this exact on-disk path for the keypair file instead of deriving one\n * from `id` (and `storeDir`). Takes precedence over `storeDir`; the parent\n * directory is created if missing.\n */\n readonly file?: string;\n}\n\nexport interface PersistedIdentity {\n readonly principal: PrincipalId;\n readonly keypair: Keypair;\n /** Long-lived X25519 keypair used for HPKE wrap/unwrap. */\n readonly wrapKeypair: X25519Keypair;\n /** Absolute path of the on-disk file. */\n readonly file: string;\n}\n\n/**\n * Load the Ed25519 + X25519 keypairs for `id` from disk, or\n * generate-and-persist them on first call. The slot is keyed by SHA-256 of\n * `id` so callers can pass any stable string (e.g. `import.meta.filename`)\n * without worrying about filesystem-safe characters.\n *\n * Identity files written before wrapping support carried only the Ed25519\n * keypair; on load they are transparently migrated — the Ed25519 keypair\n * (and therefore the `nodeId`) is preserved and a fresh X25519 wrap keypair\n * is generated and written back.\n *\n * NOTE: keys are stored unencrypted. Only suitable for local development\n * identities — not for anything that must resist file-system attackers.\n */\nexport async function loadOrCreateIdentity(\n opts: LoadOrCreateIdentityOptions,\n): Promise<PersistedIdentity> {\n const file = opts.file ??\n path.join(opts.storeDir ?? _defaultStoreDir(), `${_slotName(opts.id)}.json`);\n await fs.mkdir(path.dirname(file), { recursive: true });\n try {\n const raw = await fs.readFile(file, 'utf8');\n const parsed = JSON.parse(raw) as {\n privateKey?: string;\n publicKey?: string;\n wrapPrivateKey?: string;\n wrapPublicKey?: string;\n };\n if (typeof parsed.privateKey !== 'string' || typeof parsed.publicKey !== 'string') {\n throw new Error('malformed identity file');\n }\n const privateKey = base64UrlToBytes(parsed.privateKey);\n const publicKey = base64UrlToBytes(parsed.publicKey);\n const keypair: Keypair = { privateKey, publicKey };\n let wrapKeypair: X25519Keypair;\n if (typeof parsed.wrapPrivateKey === 'string' && typeof parsed.wrapPublicKey === 'string') {\n wrapKeypair = {\n privateKey: base64UrlToBytes(parsed.wrapPrivateKey),\n publicKey: base64UrlToBytes(parsed.wrapPublicKey),\n };\n } else {\n // Pre-wrapping identity file: keep the Ed25519 keypair (stable\n // principal) and add a fresh X25519 wrap keypair, written back.\n wrapKeypair = await crypto.generateX25519Keypair();\n await _writeIdentityFile(file, keypair, wrapKeypair, opts.id);\n }\n return { keypair, wrapKeypair, principal: principalForPublicKey(publicKey), file };\n } catch (e: unknown) {\n const err = e as NodeJS.ErrnoException;\n if (err.code !== 'ENOENT') throw e;\n }\n const keypair = await crypto.generateKeypair();\n const wrapKeypair = await crypto.generateX25519Keypair();\n await _writeIdentityFile(file, keypair, wrapKeypair, opts.id);\n return { keypair, wrapKeypair, principal: principalForPublicKey(keypair.publicKey), file };\n}\n\nasync function _writeIdentityFile(\n file: string,\n keypair: Keypair,\n wrapKeypair: X25519Keypair,\n id: string,\n): Promise<void> {\n const payload = {\n privateKey: bytesToBase64Url(keypair.privateKey),\n publicKey: bytesToBase64Url(keypair.publicKey),\n wrapPrivateKey: bytesToBase64Url(wrapKeypair.privateKey),\n wrapPublicKey: bytesToBase64Url(wrapKeypair.publicKey),\n id,\n };\n await fs.writeFile(file, JSON.stringify(payload, null, 2), { mode: 0o600 });\n}\n\nfunction _defaultStoreDir(): string {\n const home = os.homedir();\n if (process.platform === 'win32') {\n const appdata = process.env.APPDATA;\n if (appdata) return path.join(appdata, 'hubrpc', 'identities');\n return path.join(home, 'AppData', 'Roaming', 'hubrpc', 'identities');\n }\n if (process.platform === 'darwin') {\n return path.join(home, 'Library', 'Application Support', 'hubrpc', 'identities');\n }\n const xdg = process.env.XDG_CONFIG_HOME;\n if (xdg) return path.join(xdg, 'hubrpc', 'identities');\n return path.join(home, '.config', 'hubrpc', 'identities');\n}\n\nfunction _slotName(id: string): string {\n const digest = sha256(new TextEncoder().encode(id));\n let out = '';\n for (let i = 0; i < 16; i++) {\n out += digest[i].toString(16).padStart(2, '0');\n }\n return out;\n}\n\n// ---- Capability persistence ---------------------------------------------\n\n/**\n * On-disk capability cache, keyed by `(identity slot, prefix)`. Lives next\n * to the identity files so the lifecycle is the same: lose the dir, get a\n * fresh prompt next time. Caps are not secret; the cache is read/write\n * mode 0o600 anyway for consistency.\n */\nexport interface PersistedRegisterCap {\n readonly capability: SignedCapability;\n /** Absolute path of the on-disk file. */\n readonly file: string;\n}\n\nexport async function loadPersistedRegisterCap(args: {\n readonly identityId: string;\n readonly prefix: string;\n readonly storeDir?: string;\n}): Promise<PersistedRegisterCap | undefined> {\n const file = _capFilePath(args.identityId, args.prefix, args.storeDir);\n try {\n const raw = await fs.readFile(file, 'utf8');\n const parsed = JSON.parse(raw) as { capability?: SignedCapability; };\n if (!parsed.capability) return undefined;\n // Drop the cap if it expired so the caller re-acquires.\n if (\n parsed.capability.expiresAtMs !== undefined &&\n parsed.capability.expiresAtMs < Date.now()\n ) {\n return undefined;\n }\n return { capability: parsed.capability, file };\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e;\n return undefined;\n }\n}\n\nexport async function persistRegisterCap(args: {\n readonly identityId: string;\n readonly prefix: string;\n readonly capability: SignedCapability;\n readonly storeDir?: string;\n}): Promise<string> {\n const file = _capFilePath(args.identityId, args.prefix, args.storeDir);\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(\n file,\n JSON.stringify({ capability: args.capability }, null, 2),\n { mode: 0o600 },\n );\n return file;\n}\n\nfunction _capFilePath(\n identityId: string,\n prefix: string,\n storeDir: string | undefined,\n): string {\n const dir = storeDir ?? _defaultStoreDir();\n const slot = _slotName(identityId);\n return path.join(dir, `${slot}-cap-${_slotName(prefix)}.json`);\n}\n\nfunction _openSocket(endpoint: string): Promise<net.Socket> {\n return new Promise((resolve, reject) => {\n const socket = net.createConnection(endpoint);\n const onError = (err: Error) => {\n socket.removeListener('connect', onConnect);\n reject(err);\n };\n const onConnect = () => {\n socket.removeListener('error', onError);\n resolve(socket);\n };\n socket.once('error', onError);\n socket.once('connect', onConnect);\n });\n}\n","import type { LinkRpcConnection } from '../connection/linkRpcConnection';\nimport type { SignedCapability } from '../identity/capability';\nimport type { SigningCallCtx } from '../identity/signingSender';\nimport type { Keypair, PrincipalId } from '../crypto/cryptoProvider';\nimport { signParams } from '../identity/metaEnvelope';\nimport { KeypairSigningIdentity } from '../identity/identity';\nimport { ErrorCode } from '../protocol/jsonRpc';\nimport {\n connectToHub,\n type HubClientHandle,\n loadOrCreateIdentity,\n loadPersistedRegisterCap,\n persistRegisterCap,\n registerHubPrefix,\n} from './hubClient';\n\nexport interface ServeOverHubIdentityOptions {\n /**\n * Stable slot id for the on-disk keypair. Typically the caller's\n * `import.meta.filename`. Same id always loads the same keypair, so\n * persistent capabilities keep working across runs.\n */\n readonly slot: string;\n\n /**\n * Override the on-disk identity / capability store directory (defaults\n * to a per-user folder, see `loadOrCreateIdentity`).\n */\n readonly storeDir?: string;\n /**\n * Override the form-3 method the helper uses to request a register\n * capability when the hub rejects an unsigned / un-capped register.\n * Defaults to\n * `hub-admin::hub-admin.capabilities::issueRegisterCap`. Setting this\n * to `null` disables the fallback (the helper just propagates the\n * `permissionRequired` error).\n */\n readonly issuerMethod?: string | null;\n /**\n * Optional human-friendly purpose string passed to the issuer service.\n * Surfaced in the user-facing approval prompt.\n */\n readonly purpose?: string;\n}\n\nexport interface ServeOverHubOptions {\n /** Service prefix to register with the hub. */\n readonly prefix: string;\n /**\n * Wires handlers onto the connection (registers interfaces, enables\n * reflection, etc). Called once per successful connection attempt,\n * after the prefix has been registered. Must not retain references to\n * the connection across calls — a fresh connection is passed every\n * reconnect.\n */\n readonly setup: (connection: LinkRpcConnection<undefined, SigningCallCtx>) => void | Promise<void>;\n /**\n * Optional human-readable name used in log lines (defaults to `prefix`).\n */\n readonly name?: string;\n /** When set, prints connect/disconnect/retry lines to this sink. */\n readonly log?: ((line: string) => void) | true;\n /**\n * Initial retry delay in ms (capped doubling on each consecutive\n * failure). Defaults to 200 ms.\n */\n readonly initialBackoffMs?: number;\n /** Cap on backoff in ms. Defaults to 5000 ms. */\n readonly maxBackoffMs?: number;\n /**\n * Abort the loop. When the signal is aborted, the current handle is\n * closed and the loop exits. The returned promise resolves once the\n * loop has finished.\n */\n readonly signal?: AbortSignal;\n /**\n * When set, registration is performed against a secure-mode hub: the\n * caller's `$hubrpc`-signed `hubServiceIdRegistry::registerServiceId` carries a\n * presented capability. The first attempt loads any cached cap from\n * disk; on `permissionRequired` the helper calls the hub-admin issuer\n * service to obtain a fresh cap, persists it, and retries. Subsequent\n * reconnects reuse the cached cap. Omit to use the legacy unsigned\n * path (only works against an openMode hub).\n */\n readonly identity?: ServeOverHubIdentityOptions;\n}\n\nexport interface ServeOverHubController {\n /** Stops the loop and closes the current handle, if any. */\n stop(): void;\n /**\n * Resolves when the loop exits (signal aborted or `stop()` called).\n * Rejects only on programmer errors thrown by `setup`.\n */\n readonly done: Promise<void>;\n}\n\n/**\n * Connect to the hub, register `prefix`, run `setup`, and keep the\n * connection alive across hub restarts. When the socket closes, retries\n * with exponential backoff (re-reading `LINKRPC_ENDPOINT` / `LINKRPC_TOKEN`\n * from `process.env` on each attempt so rotated tokens published by the\n * hub host get picked up if the parent shell re-exports them).\n *\n * The hub keeps recently-rotated tokens accepted for a grace window, so\n * even processes that captured the env at spawn time can usually reconnect\n * after a host reload without the parent re-exporting anything.\n */\nexport function serveOverHubWithReconnect(\n options: ServeOverHubOptions,\n): ServeOverHubController {\n const log = _makeLog(options.log, options.name ?? options.prefix);\n const initial = options.initialBackoffMs ?? 200;\n const max = options.maxBackoffMs ?? 5000;\n let stopped = false;\n let current: HubClientHandle | undefined;\n\n const stop = () => {\n if (stopped) return;\n stopped = true;\n current?.close();\n current = undefined;\n };\n options.signal?.addEventListener('abort', stop, { once: true });\n\n const claimer = options.identity ?\n createHubPrefixClaimer({ prefix: options.prefix, identity: options.identity, log }) :\n undefined;\n\n const done = (async () => {\n let attempt = 0;\n let backoff = initial;\n while (!stopped) {\n try {\n if (attempt > 0) log(`reconnecting (attempt ${attempt + 1})…`);\n const handle = await connectToHub();\n current = handle;\n if (claimer) {\n await claimer.claim(handle);\n } else {\n await registerHubPrefix({ handle, prefix: options.prefix });\n }\n await options.setup(handle.connection);\n log(\n attempt === 0 ?\n `connected to hub at ${handle.endpoint} (prefix \"${options.prefix}\")` :\n `reconnected to hub (prefix \"${options.prefix}\")`,\n );\n attempt = 0;\n backoff = initial;\n await new Promise<void>((resolve) => {\n handle.onClose(() => resolve());\n });\n if (stopped) break;\n log(`disconnected from hub`);\n current = undefined;\n } catch (err) {\n if (stopped) break;\n current?.close();\n current = undefined;\n const msg = err instanceof Error ? err.message : String(err);\n log(`connect failed: ${msg}; retrying in ${backoff} ms`);\n await _delay(backoff, options.signal);\n attempt++;\n backoff = Math.min(max, backoff * 2);\n }\n }\n })();\n\n return { stop, done };\n}\n\nexport interface HubPrefixClaimerOptions {\n /** Service prefix to register with the hub. */\n readonly prefix: string;\n /** Identity + capability-issuance options (see {@link ServeOverHubIdentityOptions}). */\n readonly identity: ServeOverHubIdentityOptions;\n /** When set, prints register/capability lines to this sink. */\n readonly log?: (line: string) => void;\n}\n\nexport interface HubPrefixClaimer {\n /**\n * Register the configured prefix on `handle`'s hub, performing the\n * `$hubrpc`-signed register plus capability dance: presents the cached\n * cap, and on `permissionRequired` mints a fresh one via the hub-admin\n * issuer, persists it, and retries. Call once per (re)connect, before\n * serving handlers. The loaded identity and cap are cached across calls.\n */\n claim(handle: HubClientHandle): Promise<void>;\n}\n\n/**\n * Build a reusable, stateful claimer for the signed register + capability\n * flow. Use this with {@link connectService}'s `reconnecting` connector to\n * claim a prefix on each (re)connect:\n *\n * ```ts\n * const claimer = createHubPrefixClaimer({ prefix, identity: { slot } });\n * connectService({\n * connector: reconnecting(async () => {\n * const handle = await connectToHub();\n * try { await claimer.claim(handle); } catch (e) { handle.close(); throw e; }\n * return handle;\n * }),\n * onConnect: ({ connection }) => registerService(connection),\n * });\n * ```\n */\nexport function createHubPrefixClaimer(opts: HubPrefixClaimerOptions): HubPrefixClaimer {\n const log = opts.log ?? (() => { });\n let identity: { principal: PrincipalId; keypair: Keypair; } | undefined;\n let cachedCap: SignedCapability | undefined;\n let capLoaded = false;\n return {\n async claim(handle) {\n if (!identity) {\n const loaded = await loadOrCreateIdentity({\n id: opts.identity.slot,\n ...(opts.identity.storeDir !== undefined ?\n { storeDir: opts.identity.storeDir } :\n {}),\n });\n identity = { principal: loaded.principal, keypair: loaded.keypair };\n }\n if (!capLoaded) {\n const persisted = await loadPersistedRegisterCap({\n identityId: opts.identity.slot,\n prefix: opts.prefix,\n ...(opts.identity.storeDir !== undefined ?\n { storeDir: opts.identity.storeDir } :\n {}),\n });\n cachedCap = persisted?.capability;\n capLoaded = true;\n }\n cachedCap = await _registerSigned(\n handle,\n opts.prefix,\n identity,\n cachedCap,\n opts.identity,\n log,\n );\n },\n };\n}\n\nconst DEFAULT_ISSUER_METHOD = 'hub-admin::hub-admin.capabilities::issueRegisterCap';\n\n/**\n * Try `registerHubPrefix` with `cachedCap`. On `permissionRequired`, call\n * the hub-admin issuer to mint a fresh cap, persist it, retry. Returns the\n * cap that actually worked (caller stores it for the next reconnect).\n */\nasync function _registerSigned(\n handle: HubClientHandle,\n prefix: string,\n identity: { principal: PrincipalId; keypair: Keypair; },\n cachedCap: SignedCapability | undefined,\n identityOpts: ServeOverHubIdentityOptions,\n log: (line: string) => void,\n): Promise<SignedCapability | undefined> {\n try {\n await registerHubPrefix({\n handle,\n prefix,\n identity,\n ...(cachedCap ? { capabilities: [cachedCap] } : {}),\n });\n return cachedCap;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n if (!_isPermissionRequired(e) || identityOpts.issuerMethod === null) {\n throw e;\n }\n log(`register denied (${msg}); requesting capability from hub-admin issuer…`);\n }\n\n const issuerMethod = identityOpts.issuerMethod ?? DEFAULT_ISSUER_METHOD;\n const signer = new KeypairSigningIdentity(\n identity.principal,\n identity.keypair.privateKey,\n );\n const signedIssueParams = await signParams({\n method: issuerMethod,\n params: {\n audience: identity.principal,\n prefix,\n ...(identityOpts.purpose !== undefined ? { purpose: identityOpts.purpose } : {}),\n },\n signingIdentity: signer,\n });\n const issueRespRaw = await handle.connection.channel.sendRequest(\n issuerMethod,\n signedIssueParams,\n );\n const issueResp = issueRespRaw as unknown as { capability?: SignedCapability; };\n if (!issueResp?.capability) {\n throw new Error('hub-admin issuer returned no capability');\n }\n const fresh = issueResp.capability;\n await persistRegisterCap({\n identityId: identityOpts.slot,\n prefix,\n capability: fresh,\n ...(identityOpts.storeDir !== undefined ? { storeDir: identityOpts.storeDir } : {}),\n });\n\n await registerHubPrefix({\n handle,\n prefix,\n identity,\n capabilities: [fresh],\n });\n return fresh;\n}\n\nfunction _isPermissionRequired(e: unknown): boolean {\n if (e === null || typeof e !== 'object') return false;\n const rec = e as { code?: unknown; };\n if (typeof rec.code === 'number') return rec.code === ErrorCode.permissionRequired;\n const msg = (e as Error).message ?? '';\n return /permission required/i.test(msg);\n}\n\nfunction _makeLog(\n sink: ((line: string) => void) | true | undefined,\n name: string,\n): (line: string) => void {\n if (!sink) return () => { };\n const write = sink === true ?\n (line: string) => {\n process.stderr.write(line + '\\n');\n } :\n sink;\n return (line) => write(`[linkrpc:${name}] ${line}`);\n}\n\nfunction _delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const t = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(t);\n resolve();\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { ManagedIdentityStorage } from '../identity/managedIdentity';\n\n/**\n * A {@link ManagedIdentityStorage} backed by a single JSON file (one object\n * keyed by the storage keys). Suitable for self-managed identities that\n * persist their capability bag locally — e.g. pass it to `CapBag.load`.\n *\n * The file is created (mode 0o600) on first write; reads of a missing file\n * yield an empty store. Not concurrency-safe across processes.\n */\nexport function fileManagedIdentityStorage(file: string): ManagedIdentityStorage {\n const read = async (): Promise<Record<string, unknown>> => {\n try {\n return JSON.parse(await readFile(file, 'utf8')) as Record<string, unknown>;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ENOENT') return {};\n throw e;\n }\n };\n const write = async (data: Record<string, unknown>): Promise<void> => {\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, JSON.stringify(data, null, 2), { mode: 0o600 });\n };\n return {\n get: async <T = unknown>(key: string) => (await read())[key] as T | undefined,\n set: async (key, value) => {\n const data = await read();\n data[key] = value;\n await write(data);\n },\n delete: async (key) => {\n const data = await read();\n const existed = key in data;\n delete data[key];\n await write(data);\n return existed;\n },\n list: async (prefix = '') => Object.keys(await read()).filter((k) => k.startsWith(prefix)),\n };\n}\n","import { Principal } from '../identity/signingSender';\nimport { CapBag } from '../identity/capBag';\nimport { KeypairIdentity } from '../identity/identity';\nimport { loadOrCreateIdentity } from './hubClient';\nimport { fileManagedIdentityStorage } from './fileManagedIdentityStorage';\n\n/**\n * Self-managed principal: a local Ed25519 + X25519 keypair (created/loaded on\n * disk) signs and wraps/unwraps for outbound calls, and granted caps are\n * cached in a sibling file. Purely local — no transport needed — and\n * cheap/idempotent, so it can be re-derived on each reconnect. Used with\n * `--use-non-managed-identity`.\n */\nexport async function createSelfManagedPrincipal(identityKey: string): Promise<Principal> {\n return _selfManagedPrincipal({ id: identityKey });\n}\n\n/**\n * Self-managed principal whose keypair lives at an explicit file path (rather\n * than a slot derived from an id). Caps are cached in a sibling `.caps.json`.\n * Used by callers that want to pin the identity to a specific file, e.g. the\n * CLI's `--principal file:<path>`.\n */\nexport async function createSelfManagedPrincipalFromFile(file: string): Promise<Principal> {\n return _selfManagedPrincipal({ id: `file:${file}`, file });\n}\n\nasync function _selfManagedPrincipal(opts: { id: string; file?: string; }): Promise<Principal> {\n const id = await loadOrCreateIdentity({ id: opts.id, file: opts.file });\n const capsFile = id.file.endsWith('.json') ?\n id.file.replace(/\\.json$/, '.caps.json') :\n `${id.file}.caps.json`;\n const capBag = await CapBag.load({ storage: fileManagedIdentityStorage(capsFile) });\n const identity = new KeypairIdentity(id.principal, id.keypair.privateKey, id.wrapKeypair);\n return new Principal(identity, capBag);\n}\n","import type { JsonRpcMessage } from '../protocol/jsonRpc';\nimport type { IMessageTransport } from '../transport/messageTransport';\n\nconst HEADER_SEPARATOR = Buffer.from('\\r\\n\\r\\n');\nconst DEFAULT_MAX_HEADER_BYTES = 64 * 1024;\nconst DEFAULT_MAX_CONTENT_LENGTH = 64 * 1024 * 1024;\nconst DEFAULT_MAX_PENDING_MESSAGES = 1_024;\n\nexport interface HeaderDelimitedTransportOptions {\n readonly maxHeaderBytes?: number;\n readonly maxContentLength?: number;\n readonly maxPendingMessages?: number;\n}\n\n/**\n * LSP \"base protocol\" framing over a Node Readable/Writable pair.\n *\n * The streams remain owned by the caller: close/dispose detach listeners but\n * never end, destroy, or otherwise take ownership of either stream.\n */\nexport class HeaderDelimitedTransport implements IMessageTransport {\n private _listener: ((message: JsonRpcMessage) => void) | undefined;\n private readonly _pending: JsonRpcMessage[] = [];\n private _residual = Buffer.alloc(0);\n private _expectedLength: number | undefined;\n private _closed = false;\n private _closeReason: string | undefined;\n private readonly _maxHeaderBytes: number;\n private readonly _maxContentLength: number;\n private readonly _maxPendingMessages: number;\n\n private readonly _onDataListener = (chunk: Buffer | string): void => this._onData(chunk);\n private readonly _onEndListener = (): void => this._onEnd();\n private readonly _onInputErrorListener = (error: Error): void =>\n this.close(`Header-delimited input error: ${error.message}`);\n private readonly _onOutputErrorListener = (error: Error): void =>\n this.close(`Header-delimited output error: ${error.message}`);\n\n public constructor(\n private readonly _input: NodeJS.ReadableStream,\n private readonly _output: NodeJS.WritableStream,\n private readonly _onClose?: (reason?: string) => void,\n options: HeaderDelimitedTransportOptions = {},\n ) {\n this._maxHeaderBytes = positiveLimit(\n options.maxHeaderBytes, DEFAULT_MAX_HEADER_BYTES, 'maxHeaderBytes',\n );\n this._maxContentLength = positiveLimit(\n options.maxContentLength, DEFAULT_MAX_CONTENT_LENGTH, 'maxContentLength',\n );\n this._maxPendingMessages = positiveLimit(\n options.maxPendingMessages, DEFAULT_MAX_PENDING_MESSAGES, 'maxPendingMessages',\n );\n _input.on('data', this._onDataListener);\n _input.on('end', this._onEndListener);\n _input.on('close', this._onEndListener);\n _input.on('error', this._onInputErrorListener);\n _output.on('error', this._onOutputErrorListener);\n }\n\n public get closed(): boolean {\n return this._closed;\n }\n\n public get closeReason(): string | undefined {\n return this._closeReason;\n }\n\n public send(message: JsonRpcMessage): Promise<void> {\n if (this._closed) {\n return Promise.reject(new Error(this._closeReason ?? 'Header-delimited transport is closed'));\n }\n const body = Buffer.from(JSON.stringify(message), 'utf8');\n if (body.length > this._maxContentLength) {\n return Promise.reject(new Error(\n `Header-delimited payload exceeds ${this._maxContentLength} bytes`,\n ));\n }\n const wire = Buffer.concat([\n Buffer.from(`Content-Length: ${body.length}\\r\\n\\r\\n`, 'ascii'),\n body,\n ]);\n return new Promise<void>((resolve, reject) => {\n this._output.write(wire, (error?: Error | null) => {\n if (error) reject(error);\n else resolve();\n });\n });\n }\n\n public setListener(listener: ((message: JsonRpcMessage) => void) | undefined): void {\n this._listener = listener;\n while (this._listener && this._pending.length > 0) {\n this._listener(this._pending.shift()!);\n }\n }\n\n public dispose(): void {\n this.close('Header-delimited transport disposed');\n }\n\n public close(reason = 'Header-delimited transport closed'): void {\n if (this._closed) return;\n this._closed = true;\n this._closeReason = reason;\n this._input.off('data', this._onDataListener);\n this._input.off('end', this._onEndListener);\n this._input.off('close', this._onEndListener);\n this._input.off('error', this._onInputErrorListener);\n this._output.off('error', this._onOutputErrorListener);\n this._onClose?.(reason);\n }\n\n private _onData(chunk: Buffer | string): void {\n if (this._closed) return;\n const bytes = typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : chunk;\n this._residual = this._residual.length === 0\n ? Buffer.from(bytes)\n : Buffer.concat([this._residual, bytes]);\n\n while (!this._closed) {\n if (this._expectedLength === undefined) {\n const headerEnd = this._residual.indexOf(HEADER_SEPARATOR);\n if (headerEnd < 0) {\n if (this._residual.length > this._maxHeaderBytes) {\n this.close(`Invalid header-delimited frame: header exceeds ${this._maxHeaderBytes} bytes`);\n }\n return;\n }\n if (headerEnd + HEADER_SEPARATOR.length > this._maxHeaderBytes) {\n this.close(`Invalid header-delimited frame: header exceeds ${this._maxHeaderBytes} bytes`);\n return;\n }\n try {\n this._expectedLength = parseHeaders(\n this._residual.subarray(0, headerEnd),\n this._maxContentLength,\n );\n } catch (error) {\n this.close(`Invalid header-delimited frame: ${\n error instanceof Error ? error.message : String(error)\n }`);\n return;\n }\n this._residual = this._residual.subarray(headerEnd + HEADER_SEPARATOR.length);\n }\n\n if (this._residual.length < this._expectedLength) return;\n const body = this._residual.subarray(0, this._expectedLength);\n this._residual = this._residual.subarray(this._expectedLength);\n this._expectedLength = undefined;\n let parsed: JsonRpcMessage;\n try {\n parsed = JSON.parse(body.toString('utf8')) as JsonRpcMessage;\n } catch (error) {\n this.close(`Invalid header-delimited JSON payload: ${\n error instanceof Error ? error.message : String(error)\n }`);\n return;\n }\n this._deliver(parsed);\n }\n }\n\n private _onEnd(): void {\n if (this._closed) return;\n this.close(this._expectedLength !== undefined || this._residual.length > 0\n ? 'Truncated header-delimited frame'\n : 'Header-delimited input closed');\n }\n\n private _deliver(message: JsonRpcMessage): void {\n if (this._listener) {\n this._listener(message);\n return;\n }\n if (this._pending.length >= this._maxPendingMessages) {\n this.close(`Header-delimited pending message limit ${this._maxPendingMessages} exceeded`);\n return;\n }\n this._pending.push(message);\n }\n}\n\nfunction parseHeaders(headerBytes: Buffer, maxContentLength: number): number {\n const values = new Map<string, string>();\n for (const line of headerBytes.toString('ascii').split('\\r\\n')) {\n const colon = line.indexOf(':');\n if (colon <= 0) throw new Error(`malformed header ${JSON.stringify(line)}`);\n const name = line.slice(0, colon).trim().toLowerCase();\n const value = line.slice(colon + 1).trim();\n if (values.has(name)) throw new Error(`duplicate ${name} header`);\n values.set(name, value);\n }\n const rawLength = values.get('content-length');\n if (rawLength === undefined || !/^(0|[1-9]\\d*)$/.test(rawLength)) {\n throw new Error('missing or invalid Content-Length header');\n }\n const length = Number(rawLength);\n if (!Number.isSafeInteger(length) || length > maxContentLength) {\n throw new Error(`Content-Length exceeds ${maxContentLength} bytes`);\n }\n const contentType = values.get('content-type');\n if (contentType !== undefined && !isSupportedContentType(contentType)) {\n throw new Error(`unsupported Content-Type ${JSON.stringify(contentType)}`);\n }\n return length;\n}\n\nfunction isSupportedContentType(value: string): boolean {\n const parts = value.split(';').map((part) => part.trim().toLowerCase());\n return parts[0] === 'application/vscode-jsonrpc'\n && parts.slice(1).every((part) => /^charset\\s*=\\s*\"?utf-?8\"?$/.test(part));\n}\n\nfunction positiveLimit(value: number | undefined, fallback: number, name: string): number {\n const result = value ?? fallback;\n if (!Number.isSafeInteger(result) || result <= 0) {\n throw new Error(`${name} must be a positive integer`);\n }\n return result;\n}\n"],"mappings":"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"}
|
package/dist/web.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { $ as ManagedIdentityStorageBackend, $i as DiscriminatorSchema, $n as signedHash, $r as zTopologyLinkEndpoint, $t as Result, A as VerifyRpcCallResult, Ai as InterfaceMemberRefMap, An as Capability, Ar as nodeInterface, B as OneShotCapStaging, Bi as RequestType, Bn as permissionPermits, Br as TopologyTransportInfo, Bt as ExpBackoffOptions, C as VerifyCallOptions, Ca as JsonValue, Ci as computeInterfaceHash, Cn as ParsedMethodName, Cr as StreamControlReason, Ct as CmdEnvEndpoint, D as SignRpcCallOptions, Di as InterfaceHandlers, Dn as Call, Dr as streamInterface, Dt as ResolvedEndpoint, E as verifyCall, Ei as InterfaceDefinitionOpts, En as Ability, Er as StreamSendParams, Et as FormatEndpointOptions, F as identityStorageInterface, Fi as defineInterface, Fn as TargetPattern, Fr as TopologyLink, Ft as DEFAULT_RPC_TIMEOUT_MS, G as createManagedPrincipal, Gi as zodToSvcJsonSchema, Gn as LINKRPC_META_KEY, Gr as TrafficWatchResult, Gt as Channel, H as SigningSender, Hi as ZodToSvcJsonSchemaOptions, Hn as HUBRPC_META_KEY, Hr as TrafficOverflowEvent, Ht as OnChannelConnect, I as crypto_d_exports, Ii as interfaceFromSchema, In as capabilityPermits, Ir as TopologyLinkEndpoint, It as withRpcTimeout, J as CapBagOptions, Ji as MemberAnnotations, Jn as SignDomain, Jr as zParticipantDescriptor, Jt as IRequestSender, K as Principal, Ki as ErrorSchema, Kn as LINKRPC_SIGNATURE_KEY, Kr as topologyInterface, Kt as ChannelTransport, L as CapProvider, Li as MemberDocs, Ln as hasSignedCapabilityShape, Lr as TopologyNode, Lt as JsonRpcChannel, M as signRpcCall, Mi as StreamApi, Mn as Pattern, Mr as ParticipantDescriptorSource, Mt as isHubEndpoint, N as verifyRpcCall, Ni as StreamCallOptions, Nn as Permission, Nr as RouteClaim, Nt as parseEndpointUri, O as SignedRpcCall, Oi as InterfaceInfo, On as CallBind, Or as NodeInfo, Ot as SocketEndpoint, P as identityInterface, Pi as StreamingCall, Pn as SignedCapability, Pr as TopologyGraph, Pt as CancellableRequest, Q as ManagedIdentityStorage, Qi as ConstSchema, Qn as readSignature, Qr as zTopologyLink, Qt as RawStreamingCall, R as CapProviderResult, Ri as MemberType, Rn as matchParams, Rr as TopologyPort, Rt as ChannelConnector, S as SignParamsOptions, Sa as isResponse, Si as EXTENSION_PREFIX, Sn as stripLinkRpcWireMeta, Sr as STREAM_METHOD, St as WrappingIdentity, T as signParams, Ti as InterfaceDefinition, Tn as parseMethodName, Tr as StreamDir, Tt as EndpointCommand, U as SigningSenderConfig, Ui as notificationType, Un as HUBRPC_SIGNATURE_KEY, Ur as TrafficTransitEndpoint, Ut as BareInterfaceTarget, V as SigningCallCtx, Vi as Schema, Vn as Base64Sha256, Vr as TrafficEvent, Vt as KeepConnectedHandle, W as PrincipalWithStore, Wi as requestType, Wn as HUBRPC_UNSIGNED_KEY, Wr as TrafficTransitEvent, Wt as bareInterfaceTarget, X as InMemoryManagedIdentityStorage, Xi as ArraySchema, Xn as Signatures, Xr as zRouteClaim, Xt as IncomingStream, Y as InMemoryManagedIdentity, Yi as MethodSchema, Yn as SignatureEnvelope, Yr as zParticipantDescriptorSource, Yt as IncomingCall, Z as ManagedIdentity, Zi as BooleanSchema, Zn as getKeyId, Zr as zTopologyGraph, Zt as MessageWithCtx, _ as SeededPrincipalOptions, _a as JsonRpcResponse, _i as componentSchemaName, _n as LinkRpcJsonRpcRequest, _r as principalForPublicKey, _t as KeypairSigningIdentity, a as LinkRpcConnection, aa as ObjectSchema, ai as zTrafficOverflowEvent, an as IMessageTransport, ar as Keypair, at as ParamMatcherFor, b as createSeededSigningIdentity, ba as isNotification, bi as isAssignable, bn as LinkRpcWireParams, br as jcsCanonicalize, bt as SerializedKeypairSigningIdentity, c as ServiceHandle, ca as SchemaBase, ci as zTrafficWatchResult, cn as MessageTransportWithContext, cr as PrivateKey, ct as capBagFreshAt, d as ServiceIdPattern, da as UnionSchema, di as SchemaToZodContext, dn as connectTransports, dr as Signature, dt as issueCapability, ea as EnumSchema, ei as zTopologyNode, en as RpcError, er as signingDomainValue, et as createManagedIdentity, f as defaultsInterface, fa as ErrorCode, fi as createSchemaToZod, fn as traceMessageTransport, fr as X25519Keypair, ft as permits, g as zServiceIdPattern, ga as JsonRpcRequest, gi as assertSchemaReferences, gn as LinkRpcJsonRpcNotification, gr as keyIdForPublicKey, gt as KeypairIdentity, h as schemasInterface, ha as JsonRpcNotification, hi as materializeJsonSchema, hn as LinkRpcJsonRpcMessage, hr as keyIdForPrincipal, ht as Identity, i as InterfaceRegistration, ia as NumberSchema, ii as zTrafficEvent, in as MuxEnvelope, ir as KeyId, it as IssueCapabilityOptions, j as attachCapabilities, ji as MemberMap, jn as ParamMatcher, jr as ParticipantDescriptor, jt as formatEndpointUri, k as VerifyRpcCallOptions, ki as InterfaceMemberRef, kn as CallTarget, kr as TopologyIdGenerator, kt as WsEndpoint, l as RootPrincipalReq, la as StringSchema, li as GenerateInterfaceOptions, ln as MessageWithContext, lr as PublicKey, lt as capabilityFreshAt, m as directoryWatchNever, ma as JsonRpcMessage, mi as MaterializedJsonSchema, mn as CallMeta, mr as bytesToBase64Url, mt as signCapability, n as GetOptions, na as LinkRpcJsonSchema, ni as zTopologyTransportEndpoint, nn as StreamSendOpts, nr as withSignature, nt as registerLazyIdentityOnOverlay, o as LinkRpcConnectionOptions, oa as OneOfSchema, oi as zTrafficTransitEndpoint, on as MessageTransportDirection, or as PRINCIPAL_PREFIX, ot as ParamMatchers, p as directoryInterface, pa as JsonRpcError, pi as schemaToZod, pr as base64UrlToBytes, pt as prefix, q as CapBag, qi as LinkRpcInterfaceSchema, qn as LINKRPC_UNSIGNED_KEY, qr as trafficInterface, qt as IRequestHandler, r as InspectionRegistration, ra as NullSchema, ri as zTopologyTransportInfo, rn as MultiplexedTransport, rr as KEY_ID_PREFIX, rt as AcceptedRootIssuer, s as RegisterOptions, sa as RefSchema, si as zTrafficTransitEvent, sn as MessageTransportTrace, sr as PrincipalId, st as PermitResult, t as BareGetOptions, ta as IntegerSchema, ti as zTopologyPort, tn as SendOpts, tr as signingInput, tt as registerIdentityOnOverlay, u as RootPrincipalSet, ua as TupleSchema, ui as generateTsInterface, un as TransportPair, ur as ResolveSigningKeyArgs, ut as invoke, v as createMemoryPrincipal, va as JsonRpcSuccess, vi as componentSchemaRef, vn as LinkRpcUnsigned, vr as publicKeyForKeyId, vt as PublicSigningIdentity, w as VerifyResult, wi as InterfaceClient, wn as methodNameToTarget, wr as StreamControlType, wt as CmdStdioEndpoint, x as JsonObject, xa as isRequest, xi as normalizeJsonSchema, xn as requireObjectParams, xr as jcsCanonicalizeBytes, xt as SigningIdentity, y as createSeededMemoryPrincipal, ya as RequestId, yi as Components, yn as LinkRpcWireMeta, yr as resolveSigningKey, yt as PublicWrappingIdentity, z as ManagedSigningChannel, zi as NotificationType, zn as permissionMatchesTarget, zr as TopologyTransportEndpoint, zt as ConnectableChannel } from "./chunks/linkRpcConnection-CtlQmetO.js";
|
|
6
|
+
//#region src/transport/windowMessageTransport.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Minimal shape of `window` we need. Kept as a structural type so this module
|
|
9
|
+
* works in any environment that provides postMessage / message events.
|
|
10
|
+
*/
|
|
11
|
+
interface MessageEndpoint {
|
|
12
|
+
postMessage(message: unknown, targetOrigin?: string): void;
|
|
13
|
+
addEventListener(type: 'message', listener: (event: MessageLikeEvent) => void): void;
|
|
14
|
+
removeEventListener(type: 'message', listener: (event: MessageLikeEvent) => void): void;
|
|
15
|
+
}
|
|
16
|
+
interface MessageLikeEvent {
|
|
17
|
+
data: unknown;
|
|
18
|
+
source?: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* IMessageTransport for two `window`-like endpoints exchanging JSON-RPC
|
|
22
|
+
* messages via `postMessage`. Outgoing messages go to `their`; incoming
|
|
23
|
+
* `message` events are filtered to those whose `source` is `their`.
|
|
24
|
+
*
|
|
25
|
+
* Typical pairings:
|
|
26
|
+
* - Editor in iframe: `new WindowMessageTransport(window, window.parent)`
|
|
27
|
+
* - Host wrapping an iframe: `new WindowMessageTransport(window, iframe.contentWindow)`
|
|
28
|
+
*/
|
|
29
|
+
declare class WindowMessageTransport implements IMessageTransport {
|
|
30
|
+
private readonly _our;
|
|
31
|
+
private readonly _their;
|
|
32
|
+
private readonly _filterSource;
|
|
33
|
+
private _listener;
|
|
34
|
+
private readonly _buffer;
|
|
35
|
+
private _closed;
|
|
36
|
+
private readonly _handler;
|
|
37
|
+
constructor(_our: MessageEndpoint, _their: MessageEndpoint, _filterSource?: boolean);
|
|
38
|
+
send(message: JsonRpcMessage): void;
|
|
39
|
+
setListener(listener: ((message: JsonRpcMessage) => void) | undefined): void;
|
|
40
|
+
dispose(): void;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { Ability, type AcceptedRootIssuer, ArraySchema, BareGetOptions, type BareInterfaceTarget, Base64Sha256, BooleanSchema, Call, CallBind, CallMeta, CallTarget, type CancellableRequest, CapBag, CapBagOptions, type CapProvider, type CapProviderResult, Capability, Channel, ChannelConnector, type ChannelTransport, type CmdEnvEndpoint, type CmdStdioEndpoint, Components, type ConnectableChannel, ConstSchema, DEFAULT_RPC_TIMEOUT_MS, DiscriminatorSchema, EXTENSION_PREFIX, type EndpointCommand, EnumSchema, ErrorCode, ErrorSchema, type ExpBackoffOptions, type FormatEndpointOptions, GenerateInterfaceOptions, GetOptions, HUBRPC_META_KEY, HUBRPC_SIGNATURE_KEY, HUBRPC_UNSIGNED_KEY, IMessageTransport, type IRequestHandler, type IRequestSender, Identity, InMemoryManagedIdentity, InMemoryManagedIdentityStorage, type IncomingCall, type IncomingStream, InspectionRegistration, IntegerSchema, InterfaceClient, InterfaceDefinition, InterfaceDefinitionOpts, InterfaceHandlers, InterfaceInfo, InterfaceMemberRef, InterfaceMemberRefMap, InterfaceRegistration, type IssueCapabilityOptions, JsonObject, JsonRpcChannel, JsonRpcError, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, JsonRpcSuccess, JsonValue, KEY_ID_PREFIX, type KeepConnectedHandle, KeyId, Keypair, KeypairIdentity, KeypairSigningIdentity, LINKRPC_META_KEY, LINKRPC_SIGNATURE_KEY, LINKRPC_UNSIGNED_KEY, LinkRpcConnection, LinkRpcConnectionOptions, LinkRpcInterfaceSchema, LinkRpcJsonRpcMessage, LinkRpcJsonRpcNotification, LinkRpcJsonRpcRequest, LinkRpcJsonSchema, LinkRpcUnsigned, LinkRpcWireMeta, LinkRpcWireParams, ManagedIdentity, ManagedIdentityStorage, ManagedIdentityStorageBackend, type ManagedSigningChannel, MaterializedJsonSchema, MemberAnnotations, MemberDocs, MemberMap, MemberType, type MessageEndpoint, type MessageLikeEvent, MessageTransportDirection, MessageTransportTrace, MessageTransportWithContext, MessageWithContext, type MessageWithCtx, MethodSchema, MultiplexedTransport, MuxEnvelope, NodeInfo, NotificationType, NullSchema, NumberSchema, ObjectSchema, type OnChannelConnect, OneOfSchema, OneShotCapStaging, PRINCIPAL_PREFIX, ParamMatcher, type ParamMatcherFor, type ParamMatchers, ParsedMethodName, ParticipantDescriptor, ParticipantDescriptorSource, Pattern, Permission, type PermitResult, Principal, PrincipalId, PrincipalWithStore, PrivateKey, PublicKey, PublicSigningIdentity, PublicWrappingIdentity, type RawStreamingCall, RefSchema, RegisterOptions, RequestId, RequestType, ResolveSigningKeyArgs, type ResolvedEndpoint, type Result, RootPrincipalReq, RootPrincipalSet, RouteClaim, RpcError, STREAM_METHOD, Schema, SchemaBase, SchemaToZodContext, SeededPrincipalOptions, type SendOpts, SerializedKeypairSigningIdentity, ServiceHandle, ServiceIdPattern, SignDomain, SignParamsOptions, SignRpcCallOptions, Signature, SignatureEnvelope, Signatures, SignedCapability, SignedRpcCall, type SigningCallCtx, SigningIdentity, SigningSender, type SigningSenderConfig, type SocketEndpoint, StreamApi, StreamCallOptions, StreamControlReason, StreamControlType, StreamDir, type StreamSendOpts, StreamSendParams, StreamingCall, StringSchema, TargetPattern, TopologyGraph, TopologyIdGenerator, TopologyLink, TopologyLinkEndpoint, TopologyNode, TopologyPort, TopologyTransportEndpoint, TopologyTransportInfo, TrafficEvent, TrafficOverflowEvent, TrafficTransitEndpoint, TrafficTransitEvent, TrafficWatchResult, TransportPair, TupleSchema, UnionSchema, VerifyCallOptions, VerifyResult, VerifyRpcCallOptions, VerifyRpcCallResult, WindowMessageTransport, WrappingIdentity, type WsEndpoint, X25519Keypair, ZodToSvcJsonSchemaOptions, assertSchemaReferences, attachCapabilities, bareInterfaceTarget, base64UrlToBytes, bytesToBase64Url, capBagFreshAt, capabilityFreshAt, capabilityPermits, componentSchemaName, componentSchemaRef, computeInterfaceHash, connectTransports, createManagedIdentity, createManagedPrincipal, createMemoryPrincipal, createSchemaToZod, createSeededMemoryPrincipal, createSeededSigningIdentity, crypto_d_exports as crypto, defaultsInterface, defineInterface, directoryInterface, directoryWatchNever, formatEndpointUri, generateTsInterface, getKeyId, hasSignedCapabilityShape, identityInterface, identityStorageInterface, interfaceFromSchema, invoke, isAssignable, isHubEndpoint, isNotification, isRequest, isResponse, issueCapability, jcsCanonicalize, jcsCanonicalizeBytes, keyIdForPrincipal, keyIdForPublicKey, matchParams, materializeJsonSchema, methodNameToTarget, nodeInterface, normalizeJsonSchema, notificationType, parseEndpointUri, parseMethodName, permissionMatchesTarget, permissionPermits, permits, prefix, principalForPublicKey, publicKeyForKeyId, readSignature, registerIdentityOnOverlay, registerLazyIdentityOnOverlay, requestType, requireObjectParams, resolveSigningKey, schemaToZod, schemasInterface, signCapability, signParams, signRpcCall, signedHash, signingDomainValue, signingInput, streamInterface, stripLinkRpcWireMeta, topologyInterface, traceMessageTransport, trafficInterface, verifyCall, verifyRpcCall, withRpcTimeout, withSignature, zParticipantDescriptor, zParticipantDescriptorSource, zRouteClaim, zServiceIdPattern, zTopologyGraph, zTopologyLink, zTopologyLinkEndpoint, zTopologyNode, zTopologyPort, zTopologyTransportEndpoint, zTopologyTransportInfo, zTrafficEvent, zTrafficOverflowEvent, zTrafficTransitEndpoint, zTrafficTransitEvent, zTrafficWatchResult, zodToSvcJsonSchema };
|
|
44
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","names":[],"sources":["../src/transport/windowMessageTransport.ts"],"mappings":";;;;;;;;;;UAOiB;EACb,YAAY,kBAAkB;EAC9B,iBAAiB,iBAAiB,WAAW,OAAO;EACpD,oBAAoB,iBAAiB,WAAW,OAAO;;UAG1C;EACb;EACA;;;;;;;;;;;cAYS,kCAAkC;mBAatB;mBACA;mBACA;UAdb;mBACS;UACT;mBACS;EASI,YAAA,MAAM,iBACN,QAAQ,iBACR;EAMrB,KAAK,SAAS;EAKd,YAAY,YAAY,SAAS;EASjC"}
|
package/dist/web.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { A as NotificationType, C as defineInterface, E as computeInterfaceHash, F as normalizeJsonSchema, M as notificationType, N as requestType, O as jcsCanonicalize, P as zodToSvcJsonSchema, S as InterfaceDefinition, T as EXTENSION_PREFIX, _ as zTrafficEvent, a as topologyInterface, b as zTrafficTransitEvent, c as zParticipantDescriptorSource, d as zTopologyLink, f as zTopologyLinkEndpoint, g as zTopologyTransportInfo, h as zTopologyTransportEndpoint, i as nodeInterface, j as RequestType, k as jcsCanonicalizeBytes, l as zRouteClaim, m as zTopologyPort, o as trafficInterface, p as zTopologyNode, s as zParticipantDescriptor, u as zTopologyGraph, v as zTrafficOverflowEvent, w as interfaceFromSchema, x as zTrafficWatchResult, y as zTrafficTransitEndpoint } from "./chunks/boundedTrafficSubscription-1L592xc7.js";
|
|
6
|
+
import { $t as bareInterfaceTarget, A as attachCapabilities, At as PRINCIPAL_PREFIX, B as LinkRpcConnection, Bt as isRequest, C as identityStorageInterface, Ct as getKeyId, D as PublicWrappingIdentity, Dt as signingInput, E as PublicSigningIdentity, Et as signingDomainValue, Ft as principalForPublicKey, Gt as StreamDir, H as JsonRpcChannel, Ht as STREAM_METHOD, I as formatEndpointUri, It as publicKeyForKeyId, Jt as directoryInterface, Kt as streamInterface, L as isHubEndpoint, Lt as resolveSigningKey, M as verifyRpcCall, Mt as bytesToBase64Url, N as crypto_exports, Nt as keyIdForPrincipal, O as Principal, Ot as withSignature, Pt as keyIdForPublicKey, Qt as generateTsInterface, R as parseEndpointUri, Rt as ErrorCode, S as identityInterface, St as LINKRPC_UNSIGNED_KEY, T as KeypairSigningIdentity, Tt as signedHash, Ut as StreamControlReason, V as ServiceHandle, Vt as isResponse, Wt as StreamControlType, Xt as schemasInterface, Yt as directoryWatchNever, Zt as zServiceIdPattern, _ as InMemoryManagedIdentity, _t as HUBRPC_META_KEY, a as verifyCall, an as componentSchemaRef, at as TransportPair, b as registerIdentityOnOverlay, bt as LINKRPC_META_KEY, c as invoke, ct as requireObjectParams, d as prefix, dt as parseMethodName, en as createSchemaToZod, et as DEFAULT_RPC_TIMEOUT_MS, f as signCapability, ft as capabilityPermits, g as createManagedPrincipal, gt as permissionPermits, h as PrincipalWithStore, ht as permissionMatchesTarget, i as signParams, in as componentSchemaName, it as MultiplexedTransport, j as signRpcCall, jt as base64UrlToBytes, k as CapBag, kt as KEY_ID_PREFIX, l as issueCapability, lt as stripLinkRpcWireMeta, m as SigningSender, mt as matchParams, n as createSeededMemoryPrincipal, nn as materializeJsonSchema, nt as Channel, o as capBagFreshAt, on as isAssignable, ot as connectTransports, p as OneShotCapStaging, pt as hasSignedCapabilityShape, qt as defaultsInterface, r as createSeededSigningIdentity, rn as assertSchemaReferences, rt as RpcError, s as capabilityFreshAt, st as traceMessageTransport, t as createMemoryPrincipal, tn as schemaToZod, tt as withRpcTimeout, u as permits, ut as methodNameToTarget, v as InMemoryManagedIdentityStorage, vt as HUBRPC_SIGNATURE_KEY, w as KeypairIdentity, wt as readSignature, x as registerLazyIdentityOnOverlay, xt as LINKRPC_SIGNATURE_KEY, y as createManagedIdentity, yt as HUBRPC_UNSIGNED_KEY, z as ChannelConnector, zt as isNotification } from "./chunks/src-D3NUIwyo.js";
|
|
7
|
+
//#region src/transport/windowMessageTransport.ts
|
|
8
|
+
/**
|
|
9
|
+
* IMessageTransport for two `window`-like endpoints exchanging JSON-RPC
|
|
10
|
+
* messages via `postMessage`. Outgoing messages go to `their`; incoming
|
|
11
|
+
* `message` events are filtered to those whose `source` is `their`.
|
|
12
|
+
*
|
|
13
|
+
* Typical pairings:
|
|
14
|
+
* - Editor in iframe: `new WindowMessageTransport(window, window.parent)`
|
|
15
|
+
* - Host wrapping an iframe: `new WindowMessageTransport(window, iframe.contentWindow)`
|
|
16
|
+
*/
|
|
17
|
+
var WindowMessageTransport = class {
|
|
18
|
+
_our;
|
|
19
|
+
_their;
|
|
20
|
+
_filterSource;
|
|
21
|
+
_listener;
|
|
22
|
+
_buffer = [];
|
|
23
|
+
_closed = false;
|
|
24
|
+
_handler = (event) => {
|
|
25
|
+
if (this._filterSource && event.source !== this._their) return;
|
|
26
|
+
const data = event.data;
|
|
27
|
+
if (!isJsonRpcMessage(data)) return;
|
|
28
|
+
if (this._listener) this._listener(data);
|
|
29
|
+
else this._buffer.push(data);
|
|
30
|
+
};
|
|
31
|
+
constructor(_our, _their, _filterSource = true) {
|
|
32
|
+
this._our = _our;
|
|
33
|
+
this._their = _their;
|
|
34
|
+
this._filterSource = _filterSource;
|
|
35
|
+
if (_our === _their) throw new Error("WindowMessageTransport: cannot connect to self");
|
|
36
|
+
_our.addEventListener("message", this._handler);
|
|
37
|
+
}
|
|
38
|
+
send(message) {
|
|
39
|
+
if (this._closed) return;
|
|
40
|
+
this._their.postMessage(message, "*");
|
|
41
|
+
}
|
|
42
|
+
setListener(listener) {
|
|
43
|
+
this._listener = listener;
|
|
44
|
+
if (listener) while (this._buffer.length > 0 && this._listener) listener(this._buffer.shift());
|
|
45
|
+
}
|
|
46
|
+
dispose() {
|
|
47
|
+
if (this._closed) return;
|
|
48
|
+
this._closed = true;
|
|
49
|
+
this._our.removeEventListener("message", this._handler);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
function isJsonRpcMessage(value) {
|
|
53
|
+
return typeof value === "object" && value !== null && value.jsonrpc === "2.0";
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { CapBag, Channel, ChannelConnector, DEFAULT_RPC_TIMEOUT_MS, EXTENSION_PREFIX, ErrorCode, HUBRPC_META_KEY, HUBRPC_SIGNATURE_KEY, HUBRPC_UNSIGNED_KEY, InMemoryManagedIdentity, InMemoryManagedIdentityStorage, InterfaceDefinition, JsonRpcChannel, KEY_ID_PREFIX, KeypairIdentity, KeypairSigningIdentity, LINKRPC_META_KEY, LINKRPC_SIGNATURE_KEY, LINKRPC_UNSIGNED_KEY, LinkRpcConnection, MultiplexedTransport, NotificationType, OneShotCapStaging, PRINCIPAL_PREFIX, Principal, PrincipalWithStore, PublicSigningIdentity, PublicWrappingIdentity, RequestType, RpcError, STREAM_METHOD, ServiceHandle, SigningSender, StreamControlReason, StreamControlType, StreamDir, TransportPair, WindowMessageTransport, assertSchemaReferences, attachCapabilities, bareInterfaceTarget, base64UrlToBytes, bytesToBase64Url, capBagFreshAt, capabilityFreshAt, capabilityPermits, componentSchemaName, componentSchemaRef, computeInterfaceHash, connectTransports, createManagedIdentity, createManagedPrincipal, createMemoryPrincipal, createSchemaToZod, createSeededMemoryPrincipal, createSeededSigningIdentity, crypto_exports as crypto, defaultsInterface, defineInterface, directoryInterface, directoryWatchNever, formatEndpointUri, generateTsInterface, getKeyId, hasSignedCapabilityShape, identityInterface, identityStorageInterface, interfaceFromSchema, invoke, isAssignable, isHubEndpoint, isNotification, isRequest, isResponse, issueCapability, jcsCanonicalize, jcsCanonicalizeBytes, keyIdForPrincipal, keyIdForPublicKey, matchParams, materializeJsonSchema, methodNameToTarget, nodeInterface, normalizeJsonSchema, notificationType, parseEndpointUri, parseMethodName, permissionMatchesTarget, permissionPermits, permits, prefix, principalForPublicKey, publicKeyForKeyId, readSignature, registerIdentityOnOverlay, registerLazyIdentityOnOverlay, requestType, requireObjectParams, resolveSigningKey, schemaToZod, schemasInterface, signCapability, signParams, signRpcCall, signedHash, signingDomainValue, signingInput, streamInterface, stripLinkRpcWireMeta, topologyInterface, traceMessageTransport, trafficInterface, verifyCall, verifyRpcCall, withRpcTimeout, withSignature, zParticipantDescriptor, zParticipantDescriptorSource, zRouteClaim, zServiceIdPattern, zTopologyGraph, zTopologyLink, zTopologyLinkEndpoint, zTopologyNode, zTopologyPort, zTopologyTransportEndpoint, zTopologyTransportInfo, zTrafficEvent, zTrafficOverflowEvent, zTrafficTransitEndpoint, zTrafficTransitEvent, zTrafficWatchResult, zodToSvcJsonSchema };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=web.js.map
|
package/dist/web.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","names":[],"sources":["../src/transport/windowMessageTransport.ts"],"sourcesContent":["import type { JsonRpcMessage } from '../protocol/jsonRpc';\nimport type { IMessageTransport } from './messageTransport';\n\n/**\n * Minimal shape of `window` we need. Kept as a structural type so this module\n * works in any environment that provides postMessage / message events.\n */\nexport interface MessageEndpoint {\n postMessage(message: unknown, targetOrigin?: string): void;\n addEventListener(type: 'message', listener: (event: MessageLikeEvent) => void): void;\n removeEventListener(type: 'message', listener: (event: MessageLikeEvent) => void): void;\n}\n\nexport interface MessageLikeEvent {\n data: unknown;\n source?: unknown;\n}\n\n/**\n * IMessageTransport for two `window`-like endpoints exchanging JSON-RPC\n * messages via `postMessage`. Outgoing messages go to `their`; incoming\n * `message` events are filtered to those whose `source` is `their`.\n *\n * Typical pairings:\n * - Editor in iframe: `new WindowMessageTransport(window, window.parent)`\n * - Host wrapping an iframe: `new WindowMessageTransport(window, iframe.contentWindow)`\n */\nexport class WindowMessageTransport implements IMessageTransport {\n private _listener: ((m: JsonRpcMessage) => void) | undefined;\n private readonly _buffer: JsonRpcMessage[] = [];\n private _closed = false;\n private readonly _handler = (event: MessageLikeEvent): void => {\n if (this._filterSource && event.source !== this._their) return;\n const data = event.data;\n if (!isJsonRpcMessage(data)) return;\n if (this._listener) this._listener(data);\n else this._buffer.push(data);\n };\n\n constructor(\n private readonly _our: MessageEndpoint,\n private readonly _their: MessageEndpoint,\n private readonly _filterSource = true,\n ) {\n if (_our === _their) throw new Error('WindowMessageTransport: cannot connect to self');\n _our.addEventListener('message', this._handler);\n }\n\n send(message: JsonRpcMessage): void {\n if (this._closed) return;\n this._their.postMessage(message, '*');\n }\n\n setListener(listener: ((message: JsonRpcMessage) => void) | undefined): void {\n this._listener = listener;\n if (listener) {\n while (this._buffer.length > 0 && this._listener) {\n listener(this._buffer.shift()!);\n }\n }\n }\n\n dispose(): void {\n if (this._closed) return;\n this._closed = true;\n this._our.removeEventListener('message', this._handler);\n }\n}\n\nfunction isJsonRpcMessage(value: unknown): value is JsonRpcMessage {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { jsonrpc?: unknown; }).jsonrpc === '2.0'\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA2BA,IAAa,yBAAb,MAAiE;CAaxC;CACA;CACA;CAdrB;CACA,UAA6C,CAAC;CAC9C,UAAkB;CAClB,YAA6B,UAAkC;EAC3D,IAAI,KAAK,iBAAiB,MAAM,WAAW,KAAK,QAAQ;EACxD,MAAM,OAAO,MAAM;EACnB,IAAI,CAAC,iBAAiB,IAAI,GAAG;EAC7B,IAAI,KAAK,WAAW,KAAK,UAAU,IAAI;OAClC,KAAK,QAAQ,KAAK,IAAI;CAC/B;CAEA,YACI,MACA,QACA,gBAAiC,MACnC;EAHmB,KAAA,OAAA;EACA,KAAA,SAAA;EACA,KAAA,gBAAA;EAEjB,IAAI,SAAS,QAAQ,MAAM,IAAI,MAAM,gDAAgD;EACrF,KAAK,iBAAiB,WAAW,KAAK,QAAQ;CAClD;CAEA,KAAK,SAA+B;EAChC,IAAI,KAAK,SAAS;EAClB,KAAK,OAAO,YAAY,SAAS,GAAG;CACxC;CAEA,YAAY,UAAiE;EACzE,KAAK,YAAY;EACjB,IAAI,UACA,OAAO,KAAK,QAAQ,SAAS,KAAK,KAAK,WACnC,SAAS,KAAK,QAAQ,MAAM,CAAE;CAG1C;CAEA,UAAgB;EACZ,IAAI,KAAK,SAAS;EAClB,KAAK,UAAU;EACf,KAAK,KAAK,oBAAoB,WAAW,KAAK,QAAQ;CAC1D;AACJ;AAEA,SAAS,iBAAiB,OAAyC;CAC/D,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAiC,YAAY;AAEtD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hediet/linkrpc",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/hediet/linkrpc.git",
|
|
9
|
+
"directory": "typescript/packages/linkrpc"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/hediet/linkrpc/tree/main/typescript/packages/linkrpc",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/hediet/linkrpc/issues"
|
|
14
|
+
},
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.js",
|
|
18
|
+
"./hub/client": "./dist/hub/client/index.js",
|
|
19
|
+
"./hub/common": "./dist/hub/common/index.js",
|
|
20
|
+
"./inspection": "./dist/inspection/index.js",
|
|
21
|
+
"./node": "./dist/node.js",
|
|
22
|
+
"./web": "./dist/web.js",
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist/"
|
|
27
|
+
],
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"zod": "^4.4.3"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@hpke/core": "^1.9.0",
|
|
34
|
+
"ws": "^8.18.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
38
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
39
|
+
"@types/node": "^20.0.0",
|
|
40
|
+
"@types/ws": "^8.5.13",
|
|
41
|
+
"rollup": "^4.34.2",
|
|
42
|
+
"tslib": "^2.8.1",
|
|
43
|
+
"tsdown": "^0.22.3",
|
|
44
|
+
"typescript": "^6.0.3",
|
|
45
|
+
"vitest": "^3.0.0",
|
|
46
|
+
"zod": "^4.4.3"
|
|
47
|
+
},
|
|
48
|
+
"inlinedDependencies": {
|
|
49
|
+
"@hpke/common": "1.10.1",
|
|
50
|
+
"@hpke/core": "1.9.0"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsdown",
|
|
54
|
+
"dev": "tsdown --watch",
|
|
55
|
+
"pack": "pnpm build && pnpm pack",
|
|
56
|
+
"test": "vitest --run",
|
|
57
|
+
"test:watch": "vitest"
|
|
58
|
+
}
|
|
59
|
+
}
|