@dxos/edge-client 0.8.4-main.f9ba587 → 0.8.4-main.fd6878d

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.
Files changed (33) hide show
  1. package/dist/lib/browser/{chunk-LMP5TVOP.mjs → chunk-SUXH7FH6.mjs} +8 -1
  2. package/dist/lib/browser/{chunk-LMP5TVOP.mjs.map → chunk-SUXH7FH6.mjs.map} +3 -3
  3. package/dist/lib/browser/edge-ws-muxer.mjs +1 -1
  4. package/dist/lib/browser/index.mjs +72 -37
  5. package/dist/lib/browser/index.mjs.map +3 -3
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/testing/index.mjs +1 -1
  8. package/dist/lib/browser/testing/index.mjs.map +2 -2
  9. package/dist/lib/node-esm/{chunk-X7J46ISZ.mjs → chunk-R6K4IIBW.mjs} +8 -1
  10. package/dist/lib/node-esm/{chunk-X7J46ISZ.mjs.map → chunk-R6K4IIBW.mjs.map} +3 -3
  11. package/dist/lib/node-esm/edge-ws-muxer.mjs +1 -1
  12. package/dist/lib/node-esm/index.mjs +72 -37
  13. package/dist/lib/node-esm/index.mjs.map +3 -3
  14. package/dist/lib/node-esm/meta.json +1 -1
  15. package/dist/lib/node-esm/testing/index.mjs +1 -1
  16. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  17. package/dist/types/src/edge-client.d.ts +1 -1
  18. package/dist/types/src/edge-client.d.ts.map +1 -1
  19. package/dist/types/src/edge-http-client.d.ts +2 -1
  20. package/dist/types/src/edge-http-client.d.ts.map +1 -1
  21. package/dist/types/src/edge-ws-connection.d.ts +1 -0
  22. package/dist/types/src/edge-ws-connection.d.ts.map +1 -1
  23. package/dist/types/src/edge-ws-muxer.d.ts.map +1 -1
  24. package/dist/types/src/testing/test-utils.d.ts.map +1 -1
  25. package/dist/types/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +18 -15
  27. package/src/edge-client.ts +2 -2
  28. package/src/edge-http-client.ts +10 -6
  29. package/src/edge-ws-connection.ts +11 -3
  30. package/src/edge-ws-muxer.ts +1 -1
  31. package/src/http-client.test.ts +0 -1
  32. package/src/testing/test-utils.ts +1 -1
  33. package/src/websocket.test.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/edge-ws-muxer.ts", "../../../src/defs.ts", "../../../src/protocol.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\n\n/**\n * 0000 0001 - message contains a part of segmented message chunk sequence.\n * The next byte defines a channel id and the rest of the message contains a part of Message proto binary.\n * Messages from different channels might interleave.\n * When the flag is NOT set the rest of the message should be interpreted as the valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ = 1;\n/**\n * 0000 0010 - message terminates a segmented message chunk sequence.\n * All the chunks accumulated for the channel specified by the second byte can be concatenated\n * and interpreted as a valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ_TERMINATED = 1 << 1;\n\n/**\n * https://developers.cloudflare.com/durable-objects/platform/limits/\n */\nexport const CLOUDFLARE_MESSAGE_MAX_BYTES = 1000 * 1000; // 1MB\nexport const CLOUDFLARE_RPC_MAX_BYTES = 32 * 1000 * 1000; // 32MB\n\nconst MAX_CHUNK_LENGTH = 16384;\nconst MAX_BUFFERED_AMOUNT = CLOUDFLARE_MESSAGE_MAX_BYTES;\nconst BUFFER_FULL_BACKOFF_TIMEOUT = 100;\n\nexport class WebSocketMuxer {\n private readonly _inMessageAccumulator = new Map<number, Buffer[]>();\n private readonly _outMessageChunks = new Map<number, MessageChunk[]>();\n private readonly _outMessageChannelByService = new Map<string, number>();\n\n private _sendTimeout: any | undefined;\n\n private readonly _maxChunkLength: number;\n\n constructor(\n private readonly _ws: WebSocketCompat,\n config?: { maxChunkLength: number },\n ) {\n this._maxChunkLength = config?.maxChunkLength ?? MAX_CHUNK_LENGTH;\n }\n\n /**\n * Resolves when all the message chunks get enqueued for sending.\n */\n public async send(message: Message): Promise<void> {\n const binary = buf.toBinary(MessageSchema, message);\n const channelId = this._resolveChannel(message);\n if (\n (channelId == null && binary.byteLength > CLOUDFLARE_MESSAGE_MAX_BYTES) ||\n binary.byteLength > CLOUDFLARE_RPC_MAX_BYTES\n ) {\n log.error('Large message dropped', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n channelId,\n });\n return;\n }\n\n if (channelId == null || binary.length < this._maxChunkLength) {\n const flags = Buffer.from([0]);\n this._ws.send(Buffer.concat([flags, binary]));\n return;\n }\n\n const terminatorSentTrigger = new Trigger();\n const messageChunks: MessageChunk[] = [];\n for (let i = 0; i < binary.length; i += this._maxChunkLength) {\n const chunk = binary.slice(i, i + this._maxChunkLength);\n const isLastChunk = i + this._maxChunkLength >= binary.length;\n if (isLastChunk) {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ | FLAG_SEGMENT_SEQ_TERMINATED, channelId]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]), trigger: terminatorSentTrigger });\n } else {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ, channelId]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]) });\n }\n }\n\n const queuedMessages = this._outMessageChunks.get(channelId);\n if (queuedMessages) {\n queuedMessages.push(...messageChunks);\n } else {\n this._outMessageChunks.set(channelId, messageChunks);\n }\n\n this._sendChunkedMessages();\n\n return terminatorSentTrigger.wait();\n }\n\n public receiveData(data: Uint8Array): Message | undefined {\n if ((data[0] & FLAG_SEGMENT_SEQ) === 0) {\n return buf.fromBinary(MessageSchema, data.slice(1));\n }\n\n const [flags, channelId, ...payload] = data;\n let chunkAccumulator = this._inMessageAccumulator.get(channelId);\n if (chunkAccumulator) {\n chunkAccumulator.push(Buffer.from(payload));\n } else {\n chunkAccumulator = [Buffer.from(payload)];\n this._inMessageAccumulator.set(channelId, chunkAccumulator);\n }\n\n if ((flags & FLAG_SEGMENT_SEQ_TERMINATED) === 0) {\n return undefined;\n }\n\n const message = buf.fromBinary(MessageSchema, Buffer.concat(chunkAccumulator));\n this._inMessageAccumulator.delete(channelId);\n return message;\n }\n\n public destroy(): void {\n if (this._sendTimeout) {\n clearTimeout(this._sendTimeout);\n this._sendTimeout = undefined;\n }\n for (const channelChunks of this._outMessageChunks.values()) {\n channelChunks.forEach((chunk) => chunk.trigger?.wake());\n }\n this._outMessageChunks.clear();\n this._inMessageAccumulator.clear();\n this._outMessageChannelByService.clear();\n }\n\n private _sendChunkedMessages(): void {\n if (this._sendTimeout) {\n return;\n }\n\n const send = () => {\n if (this._ws.readyState === WebSocket.CLOSING || this._ws.readyState === WebSocket.CLOSED) {\n log.warn('send called for closed websocket');\n this._sendTimeout = undefined;\n return;\n }\n\n let timeout = 0;\n const emptyChannels: number[] = [];\n for (const [channelId, messages] of this._outMessageChunks.entries()) {\n if (this._ws.bufferedAmount != null) {\n if (this._ws.bufferedAmount + MAX_CHUNK_LENGTH > MAX_BUFFERED_AMOUNT) {\n timeout = BUFFER_FULL_BACKOFF_TIMEOUT;\n break;\n }\n }\n\n const nextMessage = messages.shift();\n if (nextMessage) {\n this._ws.send(nextMessage.payload);\n nextMessage.trigger?.wake();\n } else {\n emptyChannels.push(channelId);\n }\n }\n\n emptyChannels.forEach((channelId) => this._outMessageChunks.delete(channelId));\n\n if (this._outMessageChunks.size > 0) {\n this._sendTimeout = setTimeout(send, timeout);\n } else {\n this._sendTimeout = undefined;\n }\n };\n this._sendTimeout = setTimeout(send);\n }\n\n private _resolveChannel(message: Message): number | undefined {\n if (!message.serviceId) {\n return undefined;\n }\n let id = this._outMessageChannelByService.get(message.serviceId);\n if (!id) {\n id = this._outMessageChannelByService.size + 1;\n this._outMessageChannelByService.set(message.serviceId, id);\n }\n return id;\n }\n}\n\ntype WebSocketCompat = {\n readonly readyState: number;\n /**\n * Not available in workerd.\n */\n bufferedAmount?: number;\n send(message: (ArrayBuffer | ArrayBufferView) | string): void;\n};\n\ntype MessageChunk = {\n payload: Buffer;\n /**\n * Wakes when the payload is enqueued by WebSocket.\n */\n trigger?: Trigger;\n};\n\n/**\n * To avoid using isomorphic-ws on edge.\n */\nenum WebSocket {\n CLOSING = 2,\n CLOSED = 3,\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { bufWkt } from '@dxos/protocols/buf';\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = buf.MessageInitShape<typeof PeerSchema>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ): Message {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n"],
5
- "mappings": ";;;AAIA,SAASA,eAAe;AACxB,SAASC,WAAW;AACpB,SAASC,OAAAA,YAAW;AACpB,SAASC,iBAAAA,sBAAmC;;;ACH5C,SAASC,UAAAA,eAAc;AACvB,SAASC,oBAAoBC,qBAAqBC,yBAAyB;;;ACD3E,SAASC,iBAAiB;AAC1B,SAASC,KAAKC,cAAc;AAC5B,SAAuBC,qBAAsC;AAC7D,SAASC,qBAAqB;;AAIvB,IAAMC,cAAc,CAACC,aAAqB,uBAAuBA,QAAAA;AAKjE,IAAMC,WAAN,MAAMA;EAGX,YAAYC,OAA0B;AACpC,SAAKC,gBAAgBR,IAAIS,eAAc,GAAIF,KAAAA;EAC7C;EAEA,IAAIG,eAA6B;AAC/B,WAAO,KAAKF;EACd;EAEAG,OAAOC,SAAuB;AAC5B,QAAI;AACF,aAAOZ,IAAIW,OAAOT,eAAeU,SAAS;QAAEC,UAAU,KAAKH;MAAa,CAAA;IAC1E,SAASI,KAAK;AACZ,aAAO;QAAEC,MAAM,KAAKC,eAAeJ,OAAAA;MAAS;IAC9C;EACF;;;;EAKAK,WAAyCL,SAAkBG,MAAoC;AAC7FhB,cAAUa,QAAQM,SAAO,QAAA;;;;;;;;;AACzB,UAAMC,kBAAkB,KAAKH,eAAeJ,OAAAA;AAC5C,QAAIG,QAAQA,KAAKV,aAAac,iBAAiB;AAC7C,YAAM,IAAIC,MAAM,4BAA4BD,eAAAA,cAA6BJ,KAAKV,QAAQ,EAAE;IAC1F;AAEAN,cAAUE,OAAOoB,MAAMT,QAAQM,SAASH,IAAAA,GAAO,4BAA4BI,eAAAA,KAAkB;;;;;;;;;AAC7F,UAAMD,UAAUjB,OAAOqB,UAAUV,QAAQM,SAAS,KAAKR,YAAY;AACnEX,cAAUmB,SAAS,kBAAkBC,eAAAA,KAAkB;;;;;;;;;AACvD,WAAOD;EACT;;;;EAKAF,eAAeJ,SAAsC;AACnD,QAAI,CAACA,QAAQM,SAAS;AACpB,aAAOK;IACT;AAEA,UAAM,CAAA,EAAGR,IAAAA,IAAQH,QAAQM,QAAQM,QAAQC,MAAM,GAAA;AAC/C,WAAOV;EACT;;;;EAKAW,cACEX,MACA,EACEY,QACAC,QACAV,SACAW,UAAS,GAOF;AACT,WAAO7B,IAAI8B,OAAO5B,eAAe;MAC/B6B,YAAW,oBAAIC,KAAAA,GAAOC,YAAW;MACjCN;MACAC;MACAC;MACAX,SAASA,UAAUjB,OAAOiC,QAAQnB,MAAMf,IAAI8B,OAAOf,MAAMG,OAAAA,CAAAA,IAAYK;IACvE,CAAA;EACF;AACF;AAKO,IAAMY,eAAe,OAAOC,SAAAA;AAEjC,MAAIA,gBAAgBC,QAAQ;AAC1B,WAAOlC,cAAciC,IAAAA;EACvB;AAGA,MAAIA,gBAAgBE,MAAM;AACxB,WAAO,IAAIC,WAAW,MAAOH,KAAcI,YAAW,CAAA;EACxD;AAEA,QAAM,IAAIpB,MAAM,wBAAwBgB,IAAAA,EAAM;AAChD;;;ADhGO,IAAMK,WAAW,IAAIC,SAAS;EAACC;EAAoBC;EAAqBC;EAAmBC,QAAOC;CAAU;;;;ADQnH,IAAMC,mBAAmB;AAMzB,IAAMC,8BAA8B,KAAK;AAKlC,IAAMC,+BAA+B,MAAO;AAC5C,IAAMC,2BAA2B,KAAK,MAAO;AAEpD,IAAMC,mBAAmB;AACzB,IAAMC,sBAAsBH;AAC5B,IAAMI,8BAA8B;AAE7B,IAAMC,iBAAN,MAAMA;EASX,YACmBC,KACjBC,QACA;SAFiBD,MAAAA;SATFE,wBAAwB,oBAAIC,IAAAA;SAC5BC,oBAAoB,oBAAID,IAAAA;SACxBE,8BAA8B,oBAAIF,IAAAA;AAUjD,SAAKG,kBAAkBL,QAAQM,kBAAkBX;EACnD;;;;EAKA,MAAaY,KAAKC,SAAiC;AACjD,UAAMC,SAASC,KAAIC,SAASC,gBAAeJ,OAAAA;AAC3C,UAAMK,YAAY,KAAKC,gBAAgBN,OAAAA;AACvC,QACGK,aAAa,QAAQJ,OAAOM,aAAatB,gCAC1CgB,OAAOM,aAAarB,0BACpB;AACAsB,UAAIC,MAAM,yBAAyB;QACjCF,YAAYN,OAAOM;QACnBG,WAAWV,QAAQU;QACnBC,SAASC,SAASC,eAAeb,OAAAA;QACjCK;MACF,GAAA;;;;;;AACA;IACF;AAEA,QAAIA,aAAa,QAAQJ,OAAOa,SAAS,KAAKjB,iBAAiB;AAC7D,YAAMkB,QAAQC,OAAOC,KAAK;QAAC;OAAE;AAC7B,WAAK1B,IAAIQ,KAAKiB,OAAOE,OAAO;QAACH;QAAOd;OAAO,CAAA;AAC3C;IACF;AAEA,UAAMkB,wBAAwB,IAAIC,QAAAA;AAClC,UAAMC,gBAAgC,CAAA;AACtC,aAASC,IAAI,GAAGA,IAAIrB,OAAOa,QAAQQ,KAAK,KAAKzB,iBAAiB;AAC5D,YAAM0B,QAAQtB,OAAOuB,MAAMF,GAAGA,IAAI,KAAKzB,eAAe;AACtD,YAAM4B,cAAcH,IAAI,KAAKzB,mBAAmBI,OAAOa;AACvD,UAAIW,aAAa;AACf,cAAMV,QAAQC,OAAOC,KAAK;UAAClC,mBAAmBC;UAA6BqB;SAAU;AACrFgB,sBAAcK,KAAK;UAAEf,SAASK,OAAOE,OAAO;YAACH;YAAOQ;WAAM;UAAGI,SAASR;QAAsB,CAAA;MAC9F,OAAO;AACL,cAAMJ,QAAQC,OAAOC,KAAK;UAAClC;UAAkBsB;SAAU;AACvDgB,sBAAcK,KAAK;UAAEf,SAASK,OAAOE,OAAO;YAACH;YAAOQ;WAAM;QAAE,CAAA;MAC9D;IACF;AAEA,UAAMK,iBAAiB,KAAKjC,kBAAkBkC,IAAIxB,SAAAA;AAClD,QAAIuB,gBAAgB;AAClBA,qBAAeF,KAAI,GAAIL,aAAAA;IACzB,OAAO;AACL,WAAK1B,kBAAkBmC,IAAIzB,WAAWgB,aAAAA;IACxC;AAEA,SAAKU,qBAAoB;AAEzB,WAAOZ,sBAAsBa,KAAI;EACnC;EAEOC,YAAYC,MAAuC;AACxD,SAAKA,KAAK,CAAA,IAAKnD,sBAAsB,GAAG;AACtC,aAAOmB,KAAIiC,WAAW/B,gBAAe8B,KAAKV,MAAM,CAAA,CAAA;IAClD;AAEA,UAAM,CAACT,OAAOV,WAAW,GAAGM,OAAAA,IAAWuB;AACvC,QAAIE,mBAAmB,KAAK3C,sBAAsBoC,IAAIxB,SAAAA;AACtD,QAAI+B,kBAAkB;AACpBA,uBAAiBV,KAAKV,OAAOC,KAAKN,OAAAA,CAAAA;IACpC,OAAO;AACLyB,yBAAmB;QAACpB,OAAOC,KAAKN,OAAAA;;AAChC,WAAKlB,sBAAsBqC,IAAIzB,WAAW+B,gBAAAA;IAC5C;AAEA,SAAKrB,QAAQ/B,iCAAiC,GAAG;AAC/C,aAAOqD;IACT;AAEA,UAAMrC,UAAUE,KAAIiC,WAAW/B,gBAAeY,OAAOE,OAAOkB,gBAAAA,CAAAA;AAC5D,SAAK3C,sBAAsB6C,OAAOjC,SAAAA;AAClC,WAAOL;EACT;EAEOuC,UAAgB;AACrB,QAAI,KAAKC,cAAc;AACrBC,mBAAa,KAAKD,YAAY;AAC9B,WAAKA,eAAeH;IACtB;AACA,eAAWK,iBAAiB,KAAK/C,kBAAkBgD,OAAM,GAAI;AAC3DD,oBAAcE,QAAQ,CAACrB,UAAUA,MAAMI,SAASkB,KAAAA,CAAAA;IAClD;AACA,SAAKlD,kBAAkBmD,MAAK;AAC5B,SAAKrD,sBAAsBqD,MAAK;AAChC,SAAKlD,4BAA4BkD,MAAK;EACxC;EAEQf,uBAA6B;AACnC,QAAI,KAAKS,cAAc;AACrB;IACF;AAEA,UAAMzC,OAAO,MAAA;AACX,UAAI,KAAKR,IAAIwD,eAAU,KAA0B,KAAKxD,IAAIwD,eAAU,GAAuB;AACzFvC,YAAIwC,KAAK,oCAAA,QAAA;;;;;;AACT,aAAKR,eAAeH;AACpB;MACF;AAEA,UAAIY,UAAU;AACd,YAAMC,gBAA0B,CAAA;AAChC,iBAAW,CAAC7C,WAAW8C,QAAAA,KAAa,KAAKxD,kBAAkByD,QAAO,GAAI;AACpE,YAAI,KAAK7D,IAAI8D,kBAAkB,MAAM;AACnC,cAAI,KAAK9D,IAAI8D,iBAAiBlE,mBAAmBC,qBAAqB;AACpE6D,sBAAU5D;AACV;UACF;QACF;AAEA,cAAMiE,cAAcH,SAASI,MAAK;AAClC,YAAID,aAAa;AACf,eAAK/D,IAAIQ,KAAKuD,YAAY3C,OAAO;AACjC2C,sBAAY3B,SAASkB,KAAAA;QACvB,OAAO;AACLK,wBAAcxB,KAAKrB,SAAAA;QACrB;MACF;AAEA6C,oBAAcN,QAAQ,CAACvC,cAAc,KAAKV,kBAAkB2C,OAAOjC,SAAAA,CAAAA;AAEnE,UAAI,KAAKV,kBAAkB6D,OAAO,GAAG;AACnC,aAAKhB,eAAeiB,WAAW1D,MAAMkD,OAAAA;MACvC,OAAO;AACL,aAAKT,eAAeH;MACtB;IACF;AACA,SAAKG,eAAeiB,WAAW1D,IAAAA;EACjC;EAEQO,gBAAgBN,SAAsC;AAC5D,QAAI,CAACA,QAAQU,WAAW;AACtB,aAAO2B;IACT;AACA,QAAIqB,KAAK,KAAK9D,4BAA4BiC,IAAI7B,QAAQU,SAAS;AAC/D,QAAI,CAACgD,IAAI;AACPA,WAAK,KAAK9D,4BAA4B4D,OAAO;AAC7C,WAAK5D,4BAA4BkC,IAAI9B,QAAQU,WAAWgD,EAAAA;IAC1D;AACA,WAAOA;EACT;AACF;",
6
- "names": ["Trigger", "log", "buf", "MessageSchema", "bufWkt", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "invariant", "buf", "bufWkt", "MessageSchema", "bufferToArray", "getTypename", "typeName", "Protocol", "types", "_typeRegistry", "createRegistry", "typeRegistry", "toJson", "message", "registry", "err", "type", "getPayloadType", "getPayload", "payload", "payloadTypename", "Error", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "Blob", "Uint8Array", "arrayBuffer", "protocol", "Protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "bufWkt", "AnySchema", "FLAG_SEGMENT_SEQ", "FLAG_SEGMENT_SEQ_TERMINATED", "CLOUDFLARE_MESSAGE_MAX_BYTES", "CLOUDFLARE_RPC_MAX_BYTES", "MAX_CHUNK_LENGTH", "MAX_BUFFERED_AMOUNT", "BUFFER_FULL_BACKOFF_TIMEOUT", "WebSocketMuxer", "_ws", "config", "_inMessageAccumulator", "Map", "_outMessageChunks", "_outMessageChannelByService", "_maxChunkLength", "maxChunkLength", "send", "message", "binary", "buf", "toBinary", "MessageSchema", "channelId", "_resolveChannel", "byteLength", "log", "error", "serviceId", "payload", "protocol", "getPayloadType", "length", "flags", "Buffer", "from", "concat", "terminatorSentTrigger", "Trigger", "messageChunks", "i", "chunk", "slice", "isLastChunk", "push", "trigger", "queuedMessages", "get", "set", "_sendChunkedMessages", "wait", "receiveData", "data", "fromBinary", "chunkAccumulator", "undefined", "delete", "destroy", "_sendTimeout", "clearTimeout", "channelChunks", "values", "forEach", "wake", "clear", "readyState", "warn", "timeout", "emptyChannels", "messages", "entries", "bufferedAmount", "nextMessage", "shift", "size", "setTimeout", "id"]
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\n\n/**\n * 0000 0001 - message contains a part of segmented message chunk sequence.\n * The next byte defines a channel id and the rest of the message contains a part of Message proto binary.\n * Messages from different channels might interleave.\n * When the flag is NOT set the rest of the message should be interpreted as the valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ = 1;\n/**\n * 0000 0010 - message terminates a segmented message chunk sequence.\n * All the chunks accumulated for the channel specified by the second byte can be concatenated\n * and interpreted as a valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ_TERMINATED = 1 << 1;\n\n/**\n * https://developers.cloudflare.com/durable-objects/platform/limits/\n */\nexport const CLOUDFLARE_MESSAGE_MAX_BYTES = 1000 * 1000; // 1MB\nexport const CLOUDFLARE_RPC_MAX_BYTES = 32 * 1000 * 1000; // 32MB\n\nconst MAX_CHUNK_LENGTH = 16384;\nconst MAX_BUFFERED_AMOUNT = CLOUDFLARE_MESSAGE_MAX_BYTES;\nconst BUFFER_FULL_BACKOFF_TIMEOUT = 100;\n\nexport class WebSocketMuxer {\n private readonly _inMessageAccumulator = new Map<number, Buffer[]>();\n private readonly _outMessageChunks = new Map<number, MessageChunk[]>();\n private readonly _outMessageChannelByService = new Map<string, number>();\n\n private _sendTimeout: any | undefined;\n\n private readonly _maxChunkLength: number;\n\n constructor(\n private readonly _ws: WebSocketCompat,\n config?: { maxChunkLength: number },\n ) {\n this._maxChunkLength = config?.maxChunkLength ?? MAX_CHUNK_LENGTH;\n }\n\n /**\n * Resolves when all the message chunks get enqueued for sending.\n */\n public async send(message: Message): Promise<void> {\n const binary = buf.toBinary(MessageSchema, message);\n const channelId = this._resolveChannel(message);\n if (\n (channelId == null && binary.byteLength > CLOUDFLARE_MESSAGE_MAX_BYTES) ||\n binary.byteLength > CLOUDFLARE_RPC_MAX_BYTES\n ) {\n log.error('Large message dropped', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n channelId,\n });\n return;\n }\n\n if (channelId == null || binary.length < this._maxChunkLength) {\n const flags = Buffer.from([0]);\n this._ws.send(Buffer.concat([flags, binary]));\n return;\n }\n\n const terminatorSentTrigger = new Trigger();\n const messageChunks: MessageChunk[] = [];\n for (let i = 0; i < binary.length; i += this._maxChunkLength) {\n const chunk = binary.slice(i, i + this._maxChunkLength);\n const isLastChunk = i + this._maxChunkLength >= binary.length;\n if (isLastChunk) {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ | FLAG_SEGMENT_SEQ_TERMINATED, channelId]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]), trigger: terminatorSentTrigger });\n } else {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ, channelId]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]) });\n }\n }\n\n const queuedMessages = this._outMessageChunks.get(channelId);\n if (queuedMessages) {\n queuedMessages.push(...messageChunks);\n } else {\n this._outMessageChunks.set(channelId, messageChunks);\n }\n\n this._sendChunkedMessages();\n\n return terminatorSentTrigger.wait();\n }\n\n public receiveData(data: Uint8Array): Message | undefined {\n if ((data[0] & FLAG_SEGMENT_SEQ) === 0) {\n return buf.fromBinary(MessageSchema, data.slice(1));\n }\n\n const [flags, channelId, ...payload] = data;\n let chunkAccumulator = this._inMessageAccumulator.get(channelId);\n if (chunkAccumulator) {\n chunkAccumulator.push(Buffer.from(payload));\n } else {\n chunkAccumulator = [Buffer.from(payload)];\n this._inMessageAccumulator.set(channelId, chunkAccumulator);\n }\n\n if ((flags & FLAG_SEGMENT_SEQ_TERMINATED) === 0) {\n return undefined;\n }\n\n const message = buf.fromBinary(MessageSchema, Buffer.concat(chunkAccumulator));\n this._inMessageAccumulator.delete(channelId);\n return message;\n }\n\n public destroy(): void {\n if (this._sendTimeout) {\n clearTimeout(this._sendTimeout);\n this._sendTimeout = undefined;\n }\n for (const channelChunks of this._outMessageChunks.values()) {\n channelChunks.forEach((chunk) => chunk.trigger?.wake());\n }\n this._outMessageChunks.clear();\n this._inMessageAccumulator.clear();\n this._outMessageChannelByService.clear();\n }\n\n private _sendChunkedMessages(): void {\n if (this._sendTimeout) {\n return;\n }\n\n const send = () => {\n if (this._ws.readyState === WebSocket.CLOSING || this._ws.readyState === WebSocket.CLOSED) {\n log.warn('send called for closed websocket');\n this._sendTimeout = undefined;\n return;\n }\n\n let timeout = 0;\n const emptyChannels: number[] = [];\n for (const [channelId, messages] of this._outMessageChunks.entries()) {\n if (this._ws.bufferedAmount != null) {\n if (this._ws.bufferedAmount + MAX_CHUNK_LENGTH > MAX_BUFFERED_AMOUNT) {\n timeout = BUFFER_FULL_BACKOFF_TIMEOUT;\n break;\n }\n }\n\n const nextMessage = messages.shift();\n if (nextMessage) {\n this._ws.send(nextMessage.payload);\n nextMessage.trigger?.wake();\n } else {\n emptyChannels.push(channelId);\n }\n }\n\n emptyChannels.forEach((channelId) => this._outMessageChunks.delete(channelId));\n\n if (this._outMessageChunks.size > 0) {\n this._sendTimeout = setTimeout(send, timeout);\n } else {\n this._sendTimeout = undefined;\n }\n };\n this._sendTimeout = setTimeout(send);\n }\n\n private _resolveChannel(message: Message): number | undefined {\n if (!message.serviceId) {\n return undefined;\n }\n let id = this._outMessageChannelByService.get(message.serviceId);\n if (!id) {\n id = this._outMessageChannelByService.size + 1;\n this._outMessageChannelByService.set(message.serviceId, id);\n }\n return id;\n }\n}\n\ntype WebSocketCompat = {\n readonly readyState: number;\n /**\n * Not available in workerd.\n */\n bufferedAmount?: number;\n send(message: (ArrayBuffer | ArrayBufferView) | string): void;\n};\n\ntype MessageChunk = {\n payload: Buffer;\n /**\n * Wakes when the payload is enqueued by WebSocket.\n */\n trigger?: Trigger;\n};\n\n/**\n * To avoid using isomorphic-ws on edge.\n */\nenum WebSocket {\n CLOSING = 2,\n CLOSED = 3,\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { bufWkt } from '@dxos/protocols/buf';\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = buf.MessageInitShape<typeof PeerSchema>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ): Message {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["Trigger", "log", "buf", "MessageSchema", "bufWkt", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "invariant", "buf", "bufWkt", "MessageSchema", "bufferToArray", "getTypename", "typeName", "Protocol", "_typeRegistry", "types", "createRegistry", "typeRegistry", "toJson", "message", "registry", "err", "type", "getPayloadType", "getPayload", "payload", "payloadTypename", "Error", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "Blob", "Uint8Array", "arrayBuffer", "protocol", "Protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "bufWkt", "AnySchema", "FLAG_SEGMENT_SEQ", "FLAG_SEGMENT_SEQ_TERMINATED", "CLOUDFLARE_MESSAGE_MAX_BYTES", "CLOUDFLARE_RPC_MAX_BYTES", "MAX_CHUNK_LENGTH", "MAX_BUFFERED_AMOUNT", "BUFFER_FULL_BACKOFF_TIMEOUT", "WebSocketMuxer", "_inMessageAccumulator", "_outMessageChunks", "_outMessageChannelByService", "_sendTimeout", "_maxChunkLength", "_ws", "config", "Map", "maxChunkLength", "send", "message", "binary", "buf", "toBinary", "MessageSchema", "channelId", "_resolveChannel", "byteLength", "log", "error", "serviceId", "payload", "protocol", "getPayloadType", "length", "flags", "Buffer", "from", "concat", "terminatorSentTrigger", "Trigger", "messageChunks", "i", "chunk", "slice", "isLastChunk", "push", "trigger", "queuedMessages", "get", "set", "_sendChunkedMessages", "wait", "receiveData", "data", "fromBinary", "chunkAccumulator", "undefined", "delete", "destroy", "clearTimeout", "channelChunks", "values", "forEach", "wake", "clear", "readyState", "warn", "timeout", "emptyChannels", "messages", "entries", "bufferedAmount", "nextMessage", "shift", "size", "setTimeout", "id"]
7
7
  }
@@ -3,7 +3,7 @@ import {
3
3
  CLOUDFLARE_MESSAGE_MAX_BYTES,
4
4
  CLOUDFLARE_RPC_MAX_BYTES,
5
5
  WebSocketMuxer
6
- } from "./chunk-X7J46ISZ.mjs";
6
+ } from "./chunk-R6K4IIBW.mjs";
7
7
  export {
8
8
  CLOUDFLARE_MESSAGE_MAX_BYTES,
9
9
  CLOUDFLARE_RPC_MAX_BYTES,
@@ -7,13 +7,13 @@ import {
7
7
  getTypename,
8
8
  protocol,
9
9
  toUint8Array
10
- } from "./chunk-X7J46ISZ.mjs";
10
+ } from "./chunk-R6K4IIBW.mjs";
11
11
 
12
12
  // src/index.ts
13
13
  export * from "@dxos/protocols/buf/dxos/edge/messenger_pb";
14
14
 
15
15
  // src/edge-client.ts
16
- import { Trigger, scheduleMicroTask, TriggerState, PersistentLifecycle, Event } from "@dxos/async";
16
+ import { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask } from "@dxos/async";
17
17
  import { Resource as Resource2 } from "@dxos/context";
18
18
  import { log as log2, logInfo as logInfo2 } from "@dxos/log";
19
19
  import { EdgeStatus } from "@dxos/protocols/proto/dxos/client/services";
@@ -77,8 +77,15 @@ var __dxlog_file2 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-ws-c
77
77
  var SIGNAL_KEEPALIVE_INTERVAL = 4e3;
78
78
  var SIGNAL_KEEPALIVE_TIMEOUT = 12e3;
79
79
  var EdgeWsConnection = class extends Resource {
80
+ _identity;
81
+ _connectionInfo;
82
+ _callbacks;
83
+ _inactivityTimeoutCtx;
84
+ _ws;
85
+ _wsMuxer;
86
+ _lastReceivedMessageTimestamp;
80
87
  constructor(_identity, _connectionInfo, _callbacks) {
81
- super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks;
88
+ super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks, this._lastReceivedMessageTimestamp = Date.now();
82
89
  }
83
90
  get info() {
84
91
  return {
@@ -90,7 +97,7 @@ var EdgeWsConnection = class extends Resource {
90
97
  send(message) {
91
98
  invariant2(this._ws, void 0, {
92
99
  F: __dxlog_file2,
93
- L: 52,
100
+ L: 53,
94
101
  S: this,
95
102
  A: [
96
103
  "this._ws",
@@ -99,7 +106,7 @@ var EdgeWsConnection = class extends Resource {
99
106
  });
100
107
  invariant2(this._wsMuxer, void 0, {
101
108
  F: __dxlog_file2,
102
- L: 53,
109
+ L: 54,
103
110
  S: this,
104
111
  A: [
105
112
  "this._wsMuxer",
@@ -111,7 +118,7 @@ var EdgeWsConnection = class extends Resource {
111
118
  payload: protocol.getPayloadType(message)
112
119
  }, {
113
120
  F: __dxlog_file2,
114
- L: 54,
121
+ L: 55,
115
122
  S: this,
116
123
  C: (f, a) => f(...a)
117
124
  });
@@ -124,7 +131,7 @@ var EdgeWsConnection = class extends Resource {
124
131
  payload: protocol.getPayloadType(message)
125
132
  }, {
126
133
  F: __dxlog_file2,
127
- L: 58,
134
+ L: 59,
128
135
  S: this,
129
136
  C: (f, a) => f(...a)
130
137
  });
@@ -134,7 +141,7 @@ var EdgeWsConnection = class extends Resource {
134
141
  } else {
135
142
  this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, {
136
143
  F: __dxlog_file2,
137
- L: 67,
144
+ L: 68,
138
145
  S: this,
139
146
  C: (f, a) => f(...a)
140
147
  }));
@@ -156,7 +163,7 @@ var EdgeWsConnection = class extends Resource {
156
163
  if (this.isOpen) {
157
164
  log("connected", void 0, {
158
165
  F: __dxlog_file2,
159
- L: 84,
166
+ L: 85,
160
167
  S: this,
161
168
  C: (f, a) => f(...a)
162
169
  });
@@ -167,7 +174,7 @@ var EdgeWsConnection = class extends Resource {
167
174
  currentIdentity: this._identity
168
175
  }, {
169
176
  F: __dxlog_file2,
170
- L: 88,
177
+ L: 89,
171
178
  S: this,
172
179
  C: (f, a) => f(...a)
173
180
  });
@@ -180,7 +187,7 @@ var EdgeWsConnection = class extends Resource {
180
187
  reason: event.reason
181
188
  }, {
182
189
  F: __dxlog_file2,
183
- L: 93,
190
+ L: 94,
184
191
  S: this,
185
192
  C: (f, a) => f(...a)
186
193
  });
@@ -195,7 +202,7 @@ var EdgeWsConnection = class extends Resource {
195
202
  info: event.message
196
203
  }, {
197
204
  F: __dxlog_file2,
198
- L: 100,
205
+ L: 101,
199
206
  S: this,
200
207
  C: (f, a) => f(...a)
201
208
  });
@@ -205,7 +212,7 @@ var EdgeWsConnection = class extends Resource {
205
212
  error: event.error
206
213
  }, {
207
214
  F: __dxlog_file2,
208
- L: 103,
215
+ L: 104,
209
216
  S: this,
210
217
  C: (f, a) => f(...a)
211
218
  });
@@ -217,12 +224,13 @@ var EdgeWsConnection = class extends Resource {
217
224
  event: event.type
218
225
  }, {
219
226
  F: __dxlog_file2,
220
- L: 111,
227
+ L: 112,
221
228
  S: this,
222
229
  C: (f, a) => f(...a)
223
230
  });
224
231
  return;
225
232
  }
233
+ this._lastReceivedMessageTimestamp = Date.now();
226
234
  if (event.data === "__pong__") {
227
235
  this._rescheduleHeartbeatTimeout();
228
236
  return;
@@ -238,7 +246,7 @@ var EdgeWsConnection = class extends Resource {
238
246
  payload: protocol.getPayloadType(message)
239
247
  }, {
240
248
  F: __dxlog_file2,
241
- L: 128,
249
+ L: 130,
242
250
  S: this,
243
251
  C: (f, a) => f(...a)
244
252
  });
@@ -262,7 +270,7 @@ var EdgeWsConnection = class extends Resource {
262
270
  err
263
271
  }, {
264
272
  F: __dxlog_file2,
265
- L: 146,
273
+ L: 148,
266
274
  S: this,
267
275
  C: (f, a) => f(...a)
268
276
  });
@@ -271,7 +279,7 @@ var EdgeWsConnection = class extends Resource {
271
279
  _scheduleHeartbeats() {
272
280
  invariant2(this._ws, void 0, {
273
281
  F: __dxlog_file2,
274
- L: 151,
282
+ L: 153,
275
283
  S: this,
276
284
  A: [
277
285
  "this._ws",
@@ -291,17 +299,23 @@ var EdgeWsConnection = class extends Resource {
291
299
  void this._inactivityTimeoutCtx?.dispose();
292
300
  this._inactivityTimeoutCtx = new Context(void 0, {
293
301
  F: __dxlog_file2,
294
- L: 170
302
+ L: 172
295
303
  });
296
304
  scheduleTask(this._inactivityTimeoutCtx, () => {
297
305
  if (this.isOpen) {
298
- log.warn("restart due to inactivity timeout", void 0, {
299
- F: __dxlog_file2,
300
- L: 175,
301
- S: this,
302
- C: (f, a) => f(...a)
303
- });
304
- this._callbacks.onRestartRequired();
306
+ if (Date.now() - this._lastReceivedMessageTimestamp > SIGNAL_KEEPALIVE_TIMEOUT) {
307
+ log.warn("restart due to inactivity timeout", {
308
+ lastReceivedMessageTimestamp: this._lastReceivedMessageTimestamp
309
+ }, {
310
+ F: __dxlog_file2,
311
+ L: 178,
312
+ S: this,
313
+ C: (f, a) => f(...a)
314
+ });
315
+ this._callbacks.onRestartRequired();
316
+ } else {
317
+ this._rescheduleHeartbeatTimeout();
318
+ }
305
319
  }
306
320
  }, SIGNAL_KEEPALIVE_TIMEOUT);
307
321
  }
@@ -340,6 +354,16 @@ function _ts_decorate2(decorators, target, key, desc) {
340
354
  var __dxlog_file3 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
341
355
  var DEFAULT_TIMEOUT = 1e4;
342
356
  var EdgeClient = class extends Resource2 {
357
+ _identity;
358
+ _config;
359
+ statusChanged;
360
+ _persistentLifecycle;
361
+ _messageListeners;
362
+ _reconnectListeners;
363
+ _baseWsUrl;
364
+ _baseHttpUrl;
365
+ _currentConnection;
366
+ _ready;
343
367
  constructor(_identity, _config) {
344
368
  super(), this._identity = _identity, this._config = _config, this.statusChanged = new Event(), this._persistentLifecycle = new PersistentLifecycle({
345
369
  start: async () => this._connect(),
@@ -616,6 +640,7 @@ var EdgeClient = class extends Resource2 {
616
640
  return void 0;
617
641
  }
618
642
  }
643
+ _isActive;
619
644
  };
620
645
  _ts_decorate2([
621
646
  logInfo2
@@ -750,13 +775,11 @@ import { Context as Context2, Duration, Effect, Layer, Schedule } from "effect";
750
775
  import { log as log3 } from "@dxos/log";
751
776
  var __dxlog_file5 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/http-client.ts";
752
777
  var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
753
- static {
754
- this.default = Layer.succeed(_HttpConfig, {
755
- timeout: Duration.millis(1e3),
756
- retryTimes: 3,
757
- retryBaseDelay: Duration.millis(1e3)
758
- });
759
- }
778
+ static default = Layer.succeed(_HttpConfig, {
779
+ timeout: Duration.millis(1e3),
780
+ retryTimes: 3,
781
+ retryBaseDelay: Duration.millis(1e3)
782
+ });
760
783
  };
761
784
  var withRetry = (effect, { timeout = Duration.millis(1e3), retryBaseDelay = Duration.millis(1e3), retryTimes = 3 } = {}) => {
762
785
  return effect.pipe(Effect.flatMap((res) => (
@@ -790,6 +813,12 @@ var DEFAULT_RETRY_TIMEOUT = 1500;
790
813
  var DEFAULT_RETRY_JITTER = 500;
791
814
  var DEFAULT_MAX_RETRIES_COUNT = 3;
792
815
  var EdgeHttpClient = class {
816
+ _baseUrl;
817
+ _edgeIdentity;
818
+ /**
819
+ * Auth header is cached until receiving the next 401 from EDGE, at which point it gets refreshed.
820
+ */
821
+ _authHeader;
793
822
  constructor(baseUrl) {
794
823
  this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
795
824
  log4("created", {
@@ -874,6 +903,12 @@ var EdgeHttpClient = class {
874
903
  //
875
904
  // OAuth and credentials
876
905
  //
906
+ async listFunctions(args) {
907
+ return this._call(new URL("/functions", this.baseUrl), {
908
+ ...args,
909
+ method: "GET"
910
+ });
911
+ }
877
912
  async initiateOAuthFlow(body, args) {
878
913
  return this._call(new URL("/oauth/initiate", this.baseUrl), {
879
914
  ...args,
@@ -961,14 +996,14 @@ var EdgeHttpClient = class {
961
996
  const shouldRetry = createRetryHandler(args);
962
997
  const requestContext = args.context ?? new Context3(void 0, {
963
998
  F: __dxlog_file6,
964
- L: 289
999
+ L: 293
965
1000
  });
966
1001
  log4("fetch", {
967
1002
  url,
968
1003
  request: args.body
969
1004
  }, {
970
1005
  F: __dxlog_file6,
971
- L: 290,
1006
+ L: 294,
972
1007
  S: this,
973
1008
  C: (f, a) => f(...a)
974
1009
  });
@@ -990,7 +1025,7 @@ var EdgeHttpClient = class {
990
1025
  body
991
1026
  }, {
992
1027
  F: __dxlog_file6,
993
- L: 306,
1028
+ L: 310,
994
1029
  S: this,
995
1030
  C: (f, a) => f(...a)
996
1031
  });
@@ -1015,7 +1050,7 @@ var EdgeHttpClient = class {
1015
1050
  processingError
1016
1051
  }, {
1017
1052
  F: __dxlog_file6,
1018
- L: 324,
1053
+ L: 328,
1019
1054
  S: this,
1020
1055
  C: (f, a) => f(...a)
1021
1056
  });
@@ -1028,7 +1063,7 @@ var EdgeHttpClient = class {
1028
1063
  if (!this._edgeIdentity) {
1029
1064
  log4.warn("unauthorized response received before identity was set", void 0, {
1030
1065
  F: __dxlog_file6,
1031
- L: 333,
1066
+ L: 337,
1032
1067
  S: this,
1033
1068
  C: (f, a) => f(...a)
1034
1069
  });