iii-sdk 0.21.8-next.1 → 0.21.8-next.2
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/dist/channel.cjs +1 -1
- package/dist/channel.d.cts +1 -1
- package/dist/channel.d.mts +1 -1
- package/dist/channel.mjs +1 -1
- package/dist/{channels-DfBRsGN1.cjs → channels-C2ezAJ_g.cjs} +4 -3
- package/dist/channels-C2ezAJ_g.cjs.map +1 -0
- package/dist/{channels-D3WzAo7Z.mjs → channels-C4f7nfQr.mjs} +4 -3
- package/dist/channels-C4f7nfQr.mjs.map +1 -0
- package/dist/engine.cjs +1 -1
- package/dist/engine.d.cts +1 -1
- package/dist/engine.d.mts +1 -1
- package/dist/engine.mjs +1 -1
- package/dist/helpers.cjs +1 -1
- package/dist/helpers.d.cts +1 -1
- package/dist/helpers.d.mts +1 -1
- package/dist/helpers.mjs +1 -1
- package/dist/{iii-constants-Br94RUNi.cjs → iii-constants-M_BGfxGD.cjs} +25 -1
- package/dist/{iii-constants-_k3SoHry.mjs.map → iii-constants-M_BGfxGD.cjs.map} +1 -1
- package/dist/{iii-constants-_k3SoHry.mjs → iii-constants-TIcoyiOl.mjs} +8 -2
- package/dist/{iii-constants-Br94RUNi.cjs.map → iii-constants-TIcoyiOl.mjs.map} +1 -1
- package/dist/{iii-types-6aHBgy7l.cjs → iii-types-BvaIabiX.cjs} +2 -1
- package/dist/iii-types-BvaIabiX.cjs.map +1 -0
- package/dist/{iii-types-CRx2qAjB.mjs → iii-types-wPYrg7hX.mjs} +2 -1
- package/dist/iii-types-wPYrg7hX.mjs.map +1 -0
- package/dist/index.cjs +43 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +43 -5
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.mts +1 -1
- package/dist/protocol.cjs +1 -1
- package/dist/protocol.d.cts +1 -1
- package/dist/protocol.d.mts +1 -1
- package/dist/protocol.mjs +1 -1
- package/dist/runtime.d.cts +1 -1
- package/dist/runtime.d.mts +1 -1
- package/dist/trigger.d.cts +1 -1
- package/dist/trigger.d.mts +1 -1
- package/dist/{types-Bl-ha_EI.d.mts → types-BQJauFOT.d.cts} +4 -3
- package/dist/types-BQJauFOT.d.cts.map +1 -0
- package/dist/{types-CoEglURT.d.cts → types-CZ6tnyUT.d.mts} +4 -3
- package/dist/types-CZ6tnyUT.d.mts.map +1 -0
- package/package.json +2 -2
- package/dist/channels-D3WzAo7Z.mjs.map +0 -1
- package/dist/channels-DfBRsGN1.cjs.map +0 -1
- package/dist/iii-types-6aHBgy7l.cjs.map +0 -1
- package/dist/iii-types-CRx2qAjB.mjs.map +0 -1
- package/dist/types-Bl-ha_EI.d.mts.map +0 -1
- package/dist/types-CoEglURT.d.cts.map +0 -1
package/dist/channel.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_channels = require('./channels-
|
|
2
|
+
const require_channels = require('./channels-C2ezAJ_g.cjs');
|
|
3
3
|
|
|
4
4
|
exports.ChannelReader = require_channels.ChannelReader;
|
|
5
5
|
exports.ChannelWriter = require_channels.ChannelWriter;
|
package/dist/channel.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { O as StreamChannelRef, t as Channel, v as ChannelReader, y as ChannelWriter } from "./types-
|
|
1
|
+
import { O as StreamChannelRef, t as Channel, v as ChannelReader, y as ChannelWriter } from "./types-BQJauFOT.cjs";
|
|
2
2
|
export { type Channel, ChannelReader, ChannelWriter, type StreamChannelRef };
|
package/dist/channel.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { O as StreamChannelRef, t as Channel, v as ChannelReader, y as ChannelWriter } from "./types-
|
|
1
|
+
import { O as StreamChannelRef, t as Channel, v as ChannelReader, y as ChannelWriter } from "./types-CZ6tnyUT.mjs";
|
|
2
2
|
export { type Channel, ChannelReader, ChannelWriter, type StreamChannelRef };
|
package/dist/channel.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_utils = require('./utils-63wxBJg-.cjs');
|
|
2
|
+
const require_iii_constants = require('./iii-constants-M_BGfxGD.cjs');
|
|
2
3
|
let ws = require("ws");
|
|
3
4
|
let node_stream = require("node:stream");
|
|
4
5
|
|
|
@@ -79,7 +80,7 @@ var ChannelWriter = class ChannelWriter {
|
|
|
79
80
|
ensureConnected() {
|
|
80
81
|
if (this.ws && this.ws.readyState !== ws.WebSocket.CLOSING && this.ws.readyState !== ws.WebSocket.CLOSED) return;
|
|
81
82
|
this.wsReady = false;
|
|
82
|
-
this.ws = new ws.WebSocket(this.url);
|
|
83
|
+
this.ws = new ws.WebSocket(this.url, { handshakeTimeout: require_iii_constants.WS_HANDSHAKE_TIMEOUT_MS });
|
|
83
84
|
this.ws.on("open", () => {
|
|
84
85
|
this.wsReady = true;
|
|
85
86
|
for (const { data, callback } of this.pendingMessages) this.ws?.send(data, callback);
|
|
@@ -182,7 +183,7 @@ var ChannelReader = class {
|
|
|
182
183
|
ensureConnected() {
|
|
183
184
|
if (this.connected) return;
|
|
184
185
|
this.connected = true;
|
|
185
|
-
this.ws = new ws.WebSocket(this.url);
|
|
186
|
+
this.ws = new ws.WebSocket(this.url, { handshakeTimeout: require_iii_constants.WS_HANDSHAKE_TIMEOUT_MS });
|
|
186
187
|
this.ws.on("open", () => {
|
|
187
188
|
this.ws.binaryType = "nodebuffer";
|
|
188
189
|
});
|
|
@@ -245,4 +246,4 @@ Object.defineProperty(exports, 'ChannelWriter', {
|
|
|
245
246
|
return ChannelWriter;
|
|
246
247
|
}
|
|
247
248
|
});
|
|
248
|
-
//# sourceMappingURL=channels-
|
|
249
|
+
//# sourceMappingURL=channels-C2ezAJ_g.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels-C2ezAJ_g.cjs","names":["Writable","WebSocket","WS_HANDSHAKE_TIMEOUT_MS","Readable"],"sources":["../src/channels.ts"],"sourcesContent":["import { Readable, Writable } from 'node:stream'\nimport { WebSocket } from 'ws'\nimport { WS_HANDSHAKE_TIMEOUT_MS } from './iii-constants'\nimport type { StreamChannelRef } from './iii-types'\n\n/**\n * Direction of a streaming channel endpoint. Mirrors the Rust SDK's\n * `ChannelDirection` enum and matches the literal values used by\n * {@link StreamChannelRef.direction}.\n */\nexport const ChannelDirection = {\n Read: 'read',\n Write: 'write',\n} as const\nexport type ChannelDirection = (typeof ChannelDirection)[keyof typeof ChannelDirection]\n\n/**\n * Discriminated runtime tag for an item observed on a streaming channel.\n * Mirrors the Rust SDK's `ChannelItem` enum (`Text` / `Binary`). Carrier for\n * factory + type-guard helpers so callers can construct and discriminate\n * channel items without depending on Rust-specific shape.\n */\nexport type ChannelItem =\n | { type: 'text'; value: string }\n | { type: 'binary'; value: Uint8Array }\n\nexport const ChannelItem = {\n /** Construct a text channel item. */\n Text(value: string): ChannelItem {\n return { type: 'text', value }\n },\n /** Construct a binary channel item. */\n Binary(value: Uint8Array): ChannelItem {\n return { type: 'binary', value }\n },\n} as const\n\n/**\n * Write end of a streaming channel. Provides both a Node.js `Writable` stream\n * and a `sendMessage` method for sending structured text messages.\n *\n * @example\n * ```typescript\n * import { createChannel } from 'iii-sdk/helpers'\n * const channel = await createChannel(iii)\n *\n * // Stream binary data\n * channel.writer.stream.write(Buffer.from('hello'))\n * channel.writer.stream.end()\n *\n * // Or send text messages\n * channel.writer.sendMessage(JSON.stringify({ type: 'event', data: 'test' }))\n * channel.writer.close()\n * ```\n */\nexport class ChannelWriter {\n private static readonly FRAME_SIZE = 64 * 1024\n private ws: WebSocket | null = null\n private wsReady = false\n private readonly pendingMessages: {\n data: Buffer | string\n callback: (err?: Error | null) => void\n }[] = []\n /** Node.js Writable stream for binary data. */\n public readonly stream: Writable\n private readonly url: string\n\n constructor(engineWsBase: string, ref: StreamChannelRef) {\n this.url = buildChannelUrl(engineWsBase, ref.channel_id, ref.access_key, 'write')\n\n this.stream = new Writable({\n write: (chunk: Buffer, _encoding, callback) => {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n this.sendChunked(buf, callback)\n },\n final: (callback) => {\n if (!this.ws) {\n callback()\n return\n }\n // Delay the close frame slightly to allow the TCP stack to flush\n // all buffered send() data. Without this, the close frame can arrive\n // at the engine before all data frames, causing data truncation.\n const doClose = () => {\n if (this.ws) {\n this.ws.close(1000, 'stream_complete')\n }\n callback()\n }\n if (this.wsReady) {\n setTimeout(doClose, 10)\n } else {\n this.ws.on('open', () => setTimeout(doClose, 10))\n }\n },\n destroy: (err, callback) => {\n if (this.ws) this.ws.terminate()\n callback(err)\n },\n })\n }\n\n private ensureConnected(): void {\n // A non-null socket is only reusable while it is still connecting or open.\n // A CLOSING/CLOSED socket is dead and must be replaced — guarding solely on\n // `this.ws` being non-null would pin a terminated socket forever, so every\n // subsequent send would target a connection that can never deliver it.\n if (\n this.ws &&\n this.ws.readyState !== WebSocket.CLOSING &&\n this.ws.readyState !== WebSocket.CLOSED\n ) {\n return\n }\n this.wsReady = false\n this.ws = new WebSocket(this.url, { handshakeTimeout: WS_HANDSHAKE_TIMEOUT_MS })\n\n this.ws.on('open', () => {\n this.wsReady = true\n for (const { data, callback } of this.pendingMessages) {\n this.ws?.send(data, callback)\n }\n this.pendingMessages.length = 0\n })\n\n this.ws.on('error', (err) => {\n this.wsReady = false\n this.stream.destroy(err)\n })\n\n this.ws.on('close', () => {\n this.wsReady = false\n if (!this.stream.destroyed) {\n this.stream.destroy()\n }\n })\n }\n\n /** Send a text message through the channel. */\n sendMessage(msg: string): void {\n this.ensureConnected()\n this.sendRaw(msg, (err) => {\n if (err) this.stream.destroy(err)\n })\n }\n\n /** Close the channel writer. */\n close(): void {\n if (!this.ws) return\n const doClose = () => {\n if (this.ws) {\n this.ws.close(1000, 'channel_close')\n }\n }\n if (this.wsReady) {\n doClose()\n } else {\n this.ws.on('open', () => doClose())\n }\n }\n\n private sendChunked(data: Buffer, callback: (err?: Error | null) => void): void {\n let offset = 0\n const sendNext = (err?: Error | null): void => {\n if (err) {\n callback(err)\n return\n }\n\n if (offset >= data.length) {\n callback(null)\n return\n }\n\n const end = Math.min(offset + ChannelWriter.FRAME_SIZE, data.length)\n const part = data.subarray(offset, end)\n offset = end\n this.sendRaw(part, sendNext)\n }\n sendNext(null)\n }\n\n private sendRaw(data: Buffer | string, callback: (err?: Error | null) => void): void {\n this.ensureConnected()\n // Trust the socket's live readyState over the tracked `wsReady` flag, which\n // can stay true after a drop. Queue anything we cannot send right now — and\n // requeue a send() that throws because the socket died underneath us — so it\n // flushes on the next open instead of being lost or throwing to the caller.\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(data, (err) => callback(err ?? null))\n } catch {\n this.pendingMessages.push({ data, callback })\n }\n } else {\n this.pendingMessages.push({ data, callback })\n }\n }\n}\n\n/**\n * Read end of a streaming channel. Provides both a Node.js `Readable` stream\n * for binary data and an `onMessage` callback for structured text messages.\n *\n * @example\n * ```typescript\n * import { createChannel } from 'iii-sdk/helpers'\n * const channel = await createChannel(iii)\n *\n * // Stream binary data\n * channel.reader.stream.on('data', (chunk) => console.log(chunk))\n *\n * // Or receive text messages\n * channel.reader.onMessage((msg) => console.log('Got:', msg))\n * ```\n */\nexport class ChannelReader {\n private ws: WebSocket | null = null\n private connected = false\n private readonly messageCallbacks: Array<(msg: string) => void> = []\n /** Node.js Readable stream for binary data. */\n public readonly stream: Readable\n private readonly url: string\n\n constructor(engineWsBase: string, ref: StreamChannelRef) {\n this.url = buildChannelUrl(engineWsBase, ref.channel_id, ref.access_key, 'read')\n\n const self = this\n this.stream = new Readable({\n read() {\n self.ensureConnected()\n if (self.ws) self.ws.resume()\n },\n destroy(err, callback) {\n if (self.ws && self.ws.readyState !== WebSocket.CLOSED) {\n self.ws.terminate()\n }\n self.ws = null\n callback(err)\n },\n })\n }\n\n private ensureConnected(): void {\n if (this.connected) return\n this.connected = true\n this.ws = new WebSocket(this.url, { handshakeTimeout: WS_HANDSHAKE_TIMEOUT_MS })\n\n this.ws.on('open', () => {\n ;(this.ws as unknown as { binaryType: string }).binaryType = 'nodebuffer'\n })\n\n this.ws.on('message', (data: Buffer, isBinary: boolean) => {\n if (isBinary) {\n if (!this.stream.push(data)) {\n this.ws?.pause()\n }\n } else {\n const msg = data.toString('utf-8')\n for (const cb of this.messageCallbacks) {\n cb(msg)\n }\n }\n })\n\n this.ws.on('close', () => {\n this.ws = null\n if (!this.stream.destroyed) this.stream.push(null)\n })\n\n this.ws.on('error', (err) => {\n this.stream.destroy(err)\n })\n }\n\n /** Register a callback to receive text messages from the channel. */\n onMessage(callback: (msg: string) => void): void {\n this.messageCallbacks.push(callback)\n }\n\n async readAll(): Promise<Buffer> {\n this.ensureConnected()\n const chunks: Buffer[] = []\n\n for await (const chunk of this.stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n }\n\n return Buffer.concat(chunks)\n }\n\n close(): void {\n if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {\n this.ws.close(1000, 'channel_close')\n }\n }\n}\n\nfunction buildChannelUrl(\n engineWsBase: string,\n channelId: string,\n accessKey: string,\n direction: 'read' | 'write',\n): string {\n const base = engineWsBase.replace(/\\/$/, '')\n return `${base}/ws/channels/${channelId}?key=${encodeURIComponent(accessKey)}&dir=${direction}`\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { a as WS_HANDSHAKE_TIMEOUT_MS } from "./iii-constants-TIcoyiOl.mjs";
|
|
1
2
|
import { WebSocket } from "ws";
|
|
2
3
|
import { Readable, Writable } from "node:stream";
|
|
3
4
|
|
|
@@ -78,7 +79,7 @@ var ChannelWriter = class ChannelWriter {
|
|
|
78
79
|
ensureConnected() {
|
|
79
80
|
if (this.ws && this.ws.readyState !== WebSocket.CLOSING && this.ws.readyState !== WebSocket.CLOSED) return;
|
|
80
81
|
this.wsReady = false;
|
|
81
|
-
this.ws = new WebSocket(this.url);
|
|
82
|
+
this.ws = new WebSocket(this.url, { handshakeTimeout: WS_HANDSHAKE_TIMEOUT_MS });
|
|
82
83
|
this.ws.on("open", () => {
|
|
83
84
|
this.wsReady = true;
|
|
84
85
|
for (const { data, callback } of this.pendingMessages) this.ws?.send(data, callback);
|
|
@@ -181,7 +182,7 @@ var ChannelReader = class {
|
|
|
181
182
|
ensureConnected() {
|
|
182
183
|
if (this.connected) return;
|
|
183
184
|
this.connected = true;
|
|
184
|
-
this.ws = new WebSocket(this.url);
|
|
185
|
+
this.ws = new WebSocket(this.url, { handshakeTimeout: WS_HANDSHAKE_TIMEOUT_MS });
|
|
185
186
|
this.ws.on("open", () => {
|
|
186
187
|
this.ws.binaryType = "nodebuffer";
|
|
187
188
|
});
|
|
@@ -221,4 +222,4 @@ function buildChannelUrl(engineWsBase, channelId, accessKey, direction) {
|
|
|
221
222
|
|
|
222
223
|
//#endregion
|
|
223
224
|
export { ChannelWriter as i, ChannelItem as n, ChannelReader as r, ChannelDirection as t };
|
|
224
|
-
//# sourceMappingURL=channels-
|
|
225
|
+
//# sourceMappingURL=channels-C4f7nfQr.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels-C4f7nfQr.mjs","names":[],"sources":["../src/channels.ts"],"sourcesContent":["import { Readable, Writable } from 'node:stream'\nimport { WebSocket } from 'ws'\nimport { WS_HANDSHAKE_TIMEOUT_MS } from './iii-constants'\nimport type { StreamChannelRef } from './iii-types'\n\n/**\n * Direction of a streaming channel endpoint. Mirrors the Rust SDK's\n * `ChannelDirection` enum and matches the literal values used by\n * {@link StreamChannelRef.direction}.\n */\nexport const ChannelDirection = {\n Read: 'read',\n Write: 'write',\n} as const\nexport type ChannelDirection = (typeof ChannelDirection)[keyof typeof ChannelDirection]\n\n/**\n * Discriminated runtime tag for an item observed on a streaming channel.\n * Mirrors the Rust SDK's `ChannelItem` enum (`Text` / `Binary`). Carrier for\n * factory + type-guard helpers so callers can construct and discriminate\n * channel items without depending on Rust-specific shape.\n */\nexport type ChannelItem =\n | { type: 'text'; value: string }\n | { type: 'binary'; value: Uint8Array }\n\nexport const ChannelItem = {\n /** Construct a text channel item. */\n Text(value: string): ChannelItem {\n return { type: 'text', value }\n },\n /** Construct a binary channel item. */\n Binary(value: Uint8Array): ChannelItem {\n return { type: 'binary', value }\n },\n} as const\n\n/**\n * Write end of a streaming channel. Provides both a Node.js `Writable` stream\n * and a `sendMessage` method for sending structured text messages.\n *\n * @example\n * ```typescript\n * import { createChannel } from 'iii-sdk/helpers'\n * const channel = await createChannel(iii)\n *\n * // Stream binary data\n * channel.writer.stream.write(Buffer.from('hello'))\n * channel.writer.stream.end()\n *\n * // Or send text messages\n * channel.writer.sendMessage(JSON.stringify({ type: 'event', data: 'test' }))\n * channel.writer.close()\n * ```\n */\nexport class ChannelWriter {\n private static readonly FRAME_SIZE = 64 * 1024\n private ws: WebSocket | null = null\n private wsReady = false\n private readonly pendingMessages: {\n data: Buffer | string\n callback: (err?: Error | null) => void\n }[] = []\n /** Node.js Writable stream for binary data. */\n public readonly stream: Writable\n private readonly url: string\n\n constructor(engineWsBase: string, ref: StreamChannelRef) {\n this.url = buildChannelUrl(engineWsBase, ref.channel_id, ref.access_key, 'write')\n\n this.stream = new Writable({\n write: (chunk: Buffer, _encoding, callback) => {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n this.sendChunked(buf, callback)\n },\n final: (callback) => {\n if (!this.ws) {\n callback()\n return\n }\n // Delay the close frame slightly to allow the TCP stack to flush\n // all buffered send() data. Without this, the close frame can arrive\n // at the engine before all data frames, causing data truncation.\n const doClose = () => {\n if (this.ws) {\n this.ws.close(1000, 'stream_complete')\n }\n callback()\n }\n if (this.wsReady) {\n setTimeout(doClose, 10)\n } else {\n this.ws.on('open', () => setTimeout(doClose, 10))\n }\n },\n destroy: (err, callback) => {\n if (this.ws) this.ws.terminate()\n callback(err)\n },\n })\n }\n\n private ensureConnected(): void {\n // A non-null socket is only reusable while it is still connecting or open.\n // A CLOSING/CLOSED socket is dead and must be replaced — guarding solely on\n // `this.ws` being non-null would pin a terminated socket forever, so every\n // subsequent send would target a connection that can never deliver it.\n if (\n this.ws &&\n this.ws.readyState !== WebSocket.CLOSING &&\n this.ws.readyState !== WebSocket.CLOSED\n ) {\n return\n }\n this.wsReady = false\n this.ws = new WebSocket(this.url, { handshakeTimeout: WS_HANDSHAKE_TIMEOUT_MS })\n\n this.ws.on('open', () => {\n this.wsReady = true\n for (const { data, callback } of this.pendingMessages) {\n this.ws?.send(data, callback)\n }\n this.pendingMessages.length = 0\n })\n\n this.ws.on('error', (err) => {\n this.wsReady = false\n this.stream.destroy(err)\n })\n\n this.ws.on('close', () => {\n this.wsReady = false\n if (!this.stream.destroyed) {\n this.stream.destroy()\n }\n })\n }\n\n /** Send a text message through the channel. */\n sendMessage(msg: string): void {\n this.ensureConnected()\n this.sendRaw(msg, (err) => {\n if (err) this.stream.destroy(err)\n })\n }\n\n /** Close the channel writer. */\n close(): void {\n if (!this.ws) return\n const doClose = () => {\n if (this.ws) {\n this.ws.close(1000, 'channel_close')\n }\n }\n if (this.wsReady) {\n doClose()\n } else {\n this.ws.on('open', () => doClose())\n }\n }\n\n private sendChunked(data: Buffer, callback: (err?: Error | null) => void): void {\n let offset = 0\n const sendNext = (err?: Error | null): void => {\n if (err) {\n callback(err)\n return\n }\n\n if (offset >= data.length) {\n callback(null)\n return\n }\n\n const end = Math.min(offset + ChannelWriter.FRAME_SIZE, data.length)\n const part = data.subarray(offset, end)\n offset = end\n this.sendRaw(part, sendNext)\n }\n sendNext(null)\n }\n\n private sendRaw(data: Buffer | string, callback: (err?: Error | null) => void): void {\n this.ensureConnected()\n // Trust the socket's live readyState over the tracked `wsReady` flag, which\n // can stay true after a drop. Queue anything we cannot send right now — and\n // requeue a send() that throws because the socket died underneath us — so it\n // flushes on the next open instead of being lost or throwing to the caller.\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(data, (err) => callback(err ?? null))\n } catch {\n this.pendingMessages.push({ data, callback })\n }\n } else {\n this.pendingMessages.push({ data, callback })\n }\n }\n}\n\n/**\n * Read end of a streaming channel. Provides both a Node.js `Readable` stream\n * for binary data and an `onMessage` callback for structured text messages.\n *\n * @example\n * ```typescript\n * import { createChannel } from 'iii-sdk/helpers'\n * const channel = await createChannel(iii)\n *\n * // Stream binary data\n * channel.reader.stream.on('data', (chunk) => console.log(chunk))\n *\n * // Or receive text messages\n * channel.reader.onMessage((msg) => console.log('Got:', msg))\n * ```\n */\nexport class ChannelReader {\n private ws: WebSocket | null = null\n private connected = false\n private readonly messageCallbacks: Array<(msg: string) => void> = []\n /** Node.js Readable stream for binary data. */\n public readonly stream: Readable\n private readonly url: string\n\n constructor(engineWsBase: string, ref: StreamChannelRef) {\n this.url = buildChannelUrl(engineWsBase, ref.channel_id, ref.access_key, 'read')\n\n const self = this\n this.stream = new Readable({\n read() {\n self.ensureConnected()\n if (self.ws) self.ws.resume()\n },\n destroy(err, callback) {\n if (self.ws && self.ws.readyState !== WebSocket.CLOSED) {\n self.ws.terminate()\n }\n self.ws = null\n callback(err)\n },\n })\n }\n\n private ensureConnected(): void {\n if (this.connected) return\n this.connected = true\n this.ws = new WebSocket(this.url, { handshakeTimeout: WS_HANDSHAKE_TIMEOUT_MS })\n\n this.ws.on('open', () => {\n ;(this.ws as unknown as { binaryType: string }).binaryType = 'nodebuffer'\n })\n\n this.ws.on('message', (data: Buffer, isBinary: boolean) => {\n if (isBinary) {\n if (!this.stream.push(data)) {\n this.ws?.pause()\n }\n } else {\n const msg = data.toString('utf-8')\n for (const cb of this.messageCallbacks) {\n cb(msg)\n }\n }\n })\n\n this.ws.on('close', () => {\n this.ws = null\n if (!this.stream.destroyed) this.stream.push(null)\n })\n\n this.ws.on('error', (err) => {\n this.stream.destroy(err)\n })\n }\n\n /** Register a callback to receive text messages from the channel. */\n onMessage(callback: (msg: string) => void): void {\n this.messageCallbacks.push(callback)\n }\n\n async readAll(): Promise<Buffer> {\n this.ensureConnected()\n const chunks: Buffer[] = []\n\n for await (const chunk of this.stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n }\n\n return Buffer.concat(chunks)\n }\n\n close(): void {\n if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {\n this.ws.close(1000, 'channel_close')\n }\n }\n}\n\nfunction buildChannelUrl(\n engineWsBase: string,\n channelId: string,\n accessKey: string,\n direction: 'read' | 'write',\n): string {\n const base = engineWsBase.replace(/\\/$/, '')\n return `${base}/ws/channels/${channelId}?key=${encodeURIComponent(accessKey)}&dir=${direction}`\n}\n"],"mappings":"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"}
|
package/dist/engine.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_iii_constants = require('./iii-constants-
|
|
2
|
+
const require_iii_constants = require('./iii-constants-M_BGfxGD.cjs');
|
|
3
3
|
|
|
4
4
|
exports.EngineFunctions = require_iii_constants.EngineFunctions;
|
|
5
5
|
exports.EngineTriggers = require_iii_constants.EngineTriggers;
|
package/dist/engine.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { l as RemoteFunctionHandler } from "./types-
|
|
1
|
+
import { l as RemoteFunctionHandler } from "./types-BQJauFOT.cjs";
|
|
2
2
|
import { n as EngineTriggers, t as EngineFunctions } from "./iii-constants-BqXp8xSN.cjs";
|
|
3
3
|
export { EngineFunctions, EngineTriggers, type RemoteFunctionHandler };
|
package/dist/engine.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { l as RemoteFunctionHandler } from "./types-
|
|
1
|
+
import { l as RemoteFunctionHandler } from "./types-CZ6tnyUT.mjs";
|
|
2
2
|
import { n as EngineTriggers, t as EngineFunctions } from "./iii-constants-Baptl8nm.mjs";
|
|
3
3
|
export { EngineFunctions, EngineTriggers, type RemoteFunctionHandler };
|
package/dist/engine.mjs
CHANGED
package/dist/helpers.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_utils = require('./utils-63wxBJg-.cjs');
|
|
3
|
-
const require_channels = require('./channels-
|
|
3
|
+
const require_channels = require('./channels-C2ezAJ_g.cjs');
|
|
4
4
|
|
|
5
5
|
//#region src/helpers.ts
|
|
6
6
|
/**
|
package/dist/helpers.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as StreamChannelRef, _ as ChannelItem, g as ChannelDirection, r as IIIClient, t as Channel } from "./types-
|
|
1
|
+
import { O as StreamChannelRef, _ as ChannelItem, g as ChannelDirection, r as IIIClient, t as Channel } from "./types-BQJauFOT.cjs";
|
|
2
2
|
import { IStream } from "./stream.cjs";
|
|
3
3
|
|
|
4
4
|
//#region src/utils.d.ts
|
package/dist/helpers.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as StreamChannelRef, _ as ChannelItem, g as ChannelDirection, r as IIIClient, t as Channel } from "./types-
|
|
1
|
+
import { O as StreamChannelRef, _ as ChannelItem, g as ChannelDirection, r as IIIClient, t as Channel } from "./types-CZ6tnyUT.mjs";
|
|
2
2
|
import { IStream } from "./stream.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/utils.d.ts
|
package/dist/helpers.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as ChannelItem, t as ChannelDirection } from "./channels-
|
|
1
|
+
import { n as ChannelItem, t as ChannelDirection } from "./channels-C4f7nfQr.mjs";
|
|
2
2
|
import { n as extractChannelRefs, r as isChannelRef } from "./utils-8G4hHqvZ.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/helpers.ts
|
|
@@ -38,6 +38,12 @@ const DEFAULT_BRIDGE_RECONNECTION_CONFIG = {
|
|
|
38
38
|
};
|
|
39
39
|
/** Default invocation timeout in milliseconds */
|
|
40
40
|
const DEFAULT_INVOCATION_TIMEOUT_MS = 3e4;
|
|
41
|
+
/** WebSocket opening-handshake timeout in ms (parity with Rust SDK connect_timeout, MOT-3857) */
|
|
42
|
+
const WS_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
43
|
+
/** Client keepalive ping cadence in ms (parity with Rust SDK ping_interval) */
|
|
44
|
+
const WS_PING_INTERVAL_MS = 2e4;
|
|
45
|
+
/** Force reconnect after this long with no inbound frame (parity with Rust SDK idle_timeout) */
|
|
46
|
+
const WS_IDLE_TIMEOUT_MS = 6e4;
|
|
41
47
|
|
|
42
48
|
//#endregion
|
|
43
49
|
Object.defineProperty(exports, 'DEFAULT_BRIDGE_RECONNECTION_CONFIG', {
|
|
@@ -64,4 +70,22 @@ Object.defineProperty(exports, 'EngineTriggers', {
|
|
|
64
70
|
return EngineTriggers;
|
|
65
71
|
}
|
|
66
72
|
});
|
|
67
|
-
|
|
73
|
+
Object.defineProperty(exports, 'WS_HANDSHAKE_TIMEOUT_MS', {
|
|
74
|
+
enumerable: true,
|
|
75
|
+
get: function () {
|
|
76
|
+
return WS_HANDSHAKE_TIMEOUT_MS;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
Object.defineProperty(exports, 'WS_IDLE_TIMEOUT_MS', {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
get: function () {
|
|
82
|
+
return WS_IDLE_TIMEOUT_MS;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
Object.defineProperty(exports, 'WS_PING_INTERVAL_MS', {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get: function () {
|
|
88
|
+
return WS_PING_INTERVAL_MS;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=iii-constants-M_BGfxGD.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iii-constants-
|
|
1
|
+
{"version":3,"file":"iii-constants-M_BGfxGD.cjs","names":[],"sources":["../src/iii-constants.ts"],"sourcesContent":["/**\n * Constants for the III module.\n */\n\n/**\n * Engine function paths for internal operations.\n *\n * Naming note: `LIST_TRIGGERS` / `INFO_TRIGGERS` cover trigger TYPES\n * (templates). `LIST_REGISTERED_TRIGGERS` / `INFO_REGISTERED_TRIGGERS`\n * cover trigger INSTANCES (subscriber rows). The old\n * `engine::trigger-types::list` builtin has been removed and is now\n * served by `engine::triggers::list`.\n */\nexport const EngineFunctions = {\n LIST_FUNCTIONS: 'engine::functions::list',\n INFO_FUNCTIONS: 'engine::functions::info',\n LIST_WORKERS: 'engine::workers::list',\n INFO_WORKERS: 'engine::workers::info',\n LIST_TRIGGERS: 'engine::triggers::list',\n INFO_TRIGGERS: 'engine::triggers::info',\n LIST_REGISTERED_TRIGGERS: 'engine::registered-triggers::list',\n INFO_REGISTERED_TRIGGERS: 'engine::registered-triggers::info',\n REGISTER_WORKER: 'engine::workers::register',\n} as const\n\n/** Engine trigger types */\nexport const EngineTriggers = {\n FUNCTIONS_AVAILABLE: 'engine::functions-available',\n LOG: 'log',\n} as const\n\n/** Log function paths */\nexport const LogFunctions = {\n INFO: 'engine::log::info',\n WARN: 'engine::log::warn',\n ERROR: 'engine::log::error',\n DEBUG: 'engine::log::debug',\n} as const\n\n/** Connection state for the III WebSocket */\nexport type IIIConnectionState =\n | 'disconnected'\n | 'connecting'\n | 'connected'\n | 'reconnecting'\n | 'failed'\n\n/** Configuration for WebSocket reconnection behavior */\nexport interface IIIReconnectionConfig {\n /** Starting delay in milliseconds (default: 1000ms) */\n initialDelayMs: number\n /** Maximum delay cap in milliseconds (default: 30000ms) */\n maxDelayMs: number\n /** Exponential backoff multiplier (default: 2) */\n backoffMultiplier: number\n /** Random jitter factor 0-1 (default: 0.3) */\n jitterFactor: number\n /** Maximum retry attempts, -1 for infinite (default: -1) */\n maxRetries: number\n}\n\n/** Default reconnection configuration */\nexport const DEFAULT_BRIDGE_RECONNECTION_CONFIG: IIIReconnectionConfig = {\n initialDelayMs: 1000,\n maxDelayMs: 30000,\n backoffMultiplier: 2,\n jitterFactor: 0.3,\n maxRetries: -1,\n}\n\n/** Default invocation timeout in milliseconds */\nexport const DEFAULT_INVOCATION_TIMEOUT_MS = 30000\n\n/** WebSocket opening-handshake timeout in ms (parity with Rust SDK connect_timeout, MOT-3857) */\nexport const WS_HANDSHAKE_TIMEOUT_MS = 10000\n\n/** Client keepalive ping cadence in ms (parity with Rust SDK ping_interval) */\nexport const WS_PING_INTERVAL_MS = 20000\n\n/** Force reconnect after this long with no inbound frame (parity with Rust SDK idle_timeout) */\nexport const WS_IDLE_TIMEOUT_MS = 60000\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,kBAAkB;CAC7B,gBAAgB;CAChB,gBAAgB;CAChB,cAAc;CACd,cAAc;CACd,eAAe;CACf,eAAe;CACf,0BAA0B;CAC1B,0BAA0B;CAC1B,iBAAiB;CAClB;;AAGD,MAAa,iBAAiB;CAC5B,qBAAqB;CACrB,KAAK;CACN;;AAiCD,MAAa,qCAA4D;CACvE,gBAAgB;CAChB,YAAY;CACZ,mBAAmB;CACnB,cAAc;CACd,YAAY;CACb;;AAGD,MAAa,gCAAgC;;AAG7C,MAAa,0BAA0B;;AAGvC,MAAa,sBAAsB;;AAGnC,MAAa,qBAAqB"}
|
|
@@ -37,7 +37,13 @@ const DEFAULT_BRIDGE_RECONNECTION_CONFIG = {
|
|
|
37
37
|
};
|
|
38
38
|
/** Default invocation timeout in milliseconds */
|
|
39
39
|
const DEFAULT_INVOCATION_TIMEOUT_MS = 3e4;
|
|
40
|
+
/** WebSocket opening-handshake timeout in ms (parity with Rust SDK connect_timeout, MOT-3857) */
|
|
41
|
+
const WS_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
42
|
+
/** Client keepalive ping cadence in ms (parity with Rust SDK ping_interval) */
|
|
43
|
+
const WS_PING_INTERVAL_MS = 2e4;
|
|
44
|
+
/** Force reconnect after this long with no inbound frame (parity with Rust SDK idle_timeout) */
|
|
45
|
+
const WS_IDLE_TIMEOUT_MS = 6e4;
|
|
40
46
|
|
|
41
47
|
//#endregion
|
|
42
|
-
export { EngineTriggers as i, DEFAULT_INVOCATION_TIMEOUT_MS as n, EngineFunctions as r, DEFAULT_BRIDGE_RECONNECTION_CONFIG as t };
|
|
43
|
-
//# sourceMappingURL=iii-constants-
|
|
48
|
+
export { WS_HANDSHAKE_TIMEOUT_MS as a, EngineTriggers as i, DEFAULT_INVOCATION_TIMEOUT_MS as n, WS_IDLE_TIMEOUT_MS as o, EngineFunctions as r, WS_PING_INTERVAL_MS as s, DEFAULT_BRIDGE_RECONNECTION_CONFIG as t };
|
|
49
|
+
//# sourceMappingURL=iii-constants-TIcoyiOl.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iii-constants-
|
|
1
|
+
{"version":3,"file":"iii-constants-TIcoyiOl.mjs","names":[],"sources":["../src/iii-constants.ts"],"sourcesContent":["/**\n * Constants for the III module.\n */\n\n/**\n * Engine function paths for internal operations.\n *\n * Naming note: `LIST_TRIGGERS` / `INFO_TRIGGERS` cover trigger TYPES\n * (templates). `LIST_REGISTERED_TRIGGERS` / `INFO_REGISTERED_TRIGGERS`\n * cover trigger INSTANCES (subscriber rows). The old\n * `engine::trigger-types::list` builtin has been removed and is now\n * served by `engine::triggers::list`.\n */\nexport const EngineFunctions = {\n LIST_FUNCTIONS: 'engine::functions::list',\n INFO_FUNCTIONS: 'engine::functions::info',\n LIST_WORKERS: 'engine::workers::list',\n INFO_WORKERS: 'engine::workers::info',\n LIST_TRIGGERS: 'engine::triggers::list',\n INFO_TRIGGERS: 'engine::triggers::info',\n LIST_REGISTERED_TRIGGERS: 'engine::registered-triggers::list',\n INFO_REGISTERED_TRIGGERS: 'engine::registered-triggers::info',\n REGISTER_WORKER: 'engine::workers::register',\n} as const\n\n/** Engine trigger types */\nexport const EngineTriggers = {\n FUNCTIONS_AVAILABLE: 'engine::functions-available',\n LOG: 'log',\n} as const\n\n/** Log function paths */\nexport const LogFunctions = {\n INFO: 'engine::log::info',\n WARN: 'engine::log::warn',\n ERROR: 'engine::log::error',\n DEBUG: 'engine::log::debug',\n} as const\n\n/** Connection state for the III WebSocket */\nexport type IIIConnectionState =\n | 'disconnected'\n | 'connecting'\n | 'connected'\n | 'reconnecting'\n | 'failed'\n\n/** Configuration for WebSocket reconnection behavior */\nexport interface IIIReconnectionConfig {\n /** Starting delay in milliseconds (default: 1000ms) */\n initialDelayMs: number\n /** Maximum delay cap in milliseconds (default: 30000ms) */\n maxDelayMs: number\n /** Exponential backoff multiplier (default: 2) */\n backoffMultiplier: number\n /** Random jitter factor 0-1 (default: 0.3) */\n jitterFactor: number\n /** Maximum retry attempts, -1 for infinite (default: -1) */\n maxRetries: number\n}\n\n/** Default reconnection configuration */\nexport const DEFAULT_BRIDGE_RECONNECTION_CONFIG: IIIReconnectionConfig = {\n initialDelayMs: 1000,\n maxDelayMs: 30000,\n backoffMultiplier: 2,\n jitterFactor: 0.3,\n maxRetries: -1,\n}\n\n/** Default invocation timeout in milliseconds */\nexport const DEFAULT_INVOCATION_TIMEOUT_MS = 30000\n\n/** WebSocket opening-handshake timeout in ms (parity with Rust SDK connect_timeout, MOT-3857) */\nexport const WS_HANDSHAKE_TIMEOUT_MS = 10000\n\n/** Client keepalive ping cadence in ms (parity with Rust SDK ping_interval) */\nexport const WS_PING_INTERVAL_MS = 20000\n\n/** Force reconnect after this long with no inbound frame (parity with Rust SDK idle_timeout) */\nexport const WS_IDLE_TIMEOUT_MS = 60000\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAa,kBAAkB;CAC7B,gBAAgB;CAChB,gBAAgB;CAChB,cAAc;CACd,cAAc;CACd,eAAe;CACf,eAAe;CACf,0BAA0B;CAC1B,0BAA0B;CAC1B,iBAAiB;CAClB;;AAGD,MAAa,iBAAiB;CAC5B,qBAAqB;CACrB,KAAK;CACN;;AAiCD,MAAa,qCAA4D;CACvE,gBAAgB;CAChB,YAAY;CACZ,mBAAmB;CACnB,cAAc;CACd,YAAY;CACb;;AAGD,MAAa,gCAAgC;;AAG7C,MAAa,0BAA0B;;AAGvC,MAAa,sBAAsB;;AAGnC,MAAa,qBAAqB"}
|
|
@@ -11,6 +11,7 @@ let MessageType = /* @__PURE__ */ function(MessageType) {
|
|
|
11
11
|
MessageType["UnregisterTriggerType"] = "unregistertriggertype";
|
|
12
12
|
MessageType["TriggerRegistrationResult"] = "triggerregistrationresult";
|
|
13
13
|
MessageType["WorkerRegistered"] = "workerregistered";
|
|
14
|
+
MessageType["Reattach"] = "reattach";
|
|
14
15
|
return MessageType;
|
|
15
16
|
}({});
|
|
16
17
|
|
|
@@ -21,4 +22,4 @@ Object.defineProperty(exports, 'MessageType', {
|
|
|
21
22
|
return MessageType;
|
|
22
23
|
}
|
|
23
24
|
});
|
|
24
|
-
//# sourceMappingURL=iii-types-
|
|
25
|
+
//# sourceMappingURL=iii-types-BvaIabiX.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iii-types-BvaIabiX.cjs","names":[],"sources":["../src/iii-types.ts"],"sourcesContent":["import type { HttpInvocationConfig } from '@iii-dev/helpers/http'\n\n/**\n * Any JSON value: the TypeScript equivalent of the engine's arbitrary-JSON\n * wire values (Rust `serde_json::Value`). Used where the wire contract is\n * \"any JSON\", e.g. per-invocation `metadata`.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue }\n\nexport enum MessageType {\n RegisterFunction = 'registerfunction',\n UnregisterFunction = 'unregisterfunction',\n InvokeFunction = 'invokefunction',\n InvocationResult = 'invocationresult',\n RegisterTriggerType = 'registertriggertype',\n RegisterTrigger = 'registertrigger',\n UnregisterTrigger = 'unregistertrigger',\n UnregisterTriggerType = 'unregistertriggertype',\n TriggerRegistrationResult = 'triggerregistrationresult',\n WorkerRegistered = 'workerregistered',\n Reattach = 'reattach',\n}\n\nexport type RegisterTriggerTypeMessage = {\n message_type: MessageType.RegisterTriggerType\n /** Unique identifier for the trigger type (e.g. `state`, `durable:subscriber`). */\n id: string\n /** Human-readable description of what this trigger type does. */\n description: string\n}\n\nexport type UnregisterTriggerTypeMessage = {\n message_type: MessageType.UnregisterTriggerType\n id: string\n}\n\nexport type UnregisterTriggerMessage = {\n message_type: MessageType.UnregisterTrigger\n id: string\n type?: string\n}\n\nexport type ErrorBody = {\n code: string\n message: string\n stacktrace?: string\n}\n\nexport type TriggerRegistrationResultMessage = {\n message_type: MessageType.TriggerRegistrationResult\n id: string\n type: string\n function_id: string\n error?: ErrorBody\n}\n\nexport type RegisterTriggerMessage = {\n /** Wire discriminator; always `MessageType.RegisterTrigger`. */\n message_type: MessageType.RegisterTrigger\n /** Unique trigger identifier, generated by the SDK during registration. */\n id: string\n /** Identifier of the registered trigger type this trigger uses (e.g. `storage::object-created`, `http`). */\n type: string\n /** ID of the function this trigger invokes when it fires. */\n function_id: string\n /** Trigger-type-specific configuration, matching the shape the trigger type expects. */\n config: unknown\n /** Arbitrary user-specifiable metadata supplied to the triggered handler function on every invocation. */\n metadata?: Record<string, unknown>\n}\n\nexport type RegisterFunctionFormat = {\n /**\n * The name of the parameter.\n */\n name?: string\n /**\n * The description of the parameter.\n */\n description?: string\n /**\n * The type of the parameter.\n */\n type?: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'map' | 'integer'\n /**\n * The body of the parameter (for objects).\n */\n properties?: Record<string, unknown>\n /**\n * The items of the parameter (for arrays).\n */\n items?: unknown\n /**\n * Whether the parameter is required.\n */\n required?: string[]\n [key: string]: unknown\n}\n\nexport type RegisterFunctionMessage = {\n message_type: MessageType.RegisterFunction\n /**\n * The path of the function (use :: for namespacing, e.g. external::my_lambda).\n */\n id: string\n /**\n * The description of the function.\n */\n description?: string\n /**\n * The request format of the function.\n */\n request_format?: RegisterFunctionFormat\n /**\n * The response format of the function.\n */\n response_format?: RegisterFunctionFormat\n /**\n * Arbitrary metadata attached to the function.\n */\n metadata?: Record<string, unknown>\n /**\n * HTTP invocation config for external HTTP functions (Lambda, Cloudflare Workers, etc.).\n */\n invocation?: HttpInvocationConfig\n}\n\n/**\n * Routing action for {@link TriggerRequest}. Determines how the engine\n * handles the invocation.\n *\n * - `enqueue`: Routes through a named queue for async processing.\n * - `void`: Fire-and-forget, no response.\n */\nexport type TriggerAction = { type: 'enqueue'; queue: string } | { type: 'void' }\n\n/**\n * Input passed to the RBAC middleware function on every function invocation\n * through the RBAC port. The middleware can inspect, modify, or reject the\n * call before it reaches the target function.\n */\nexport type MiddlewareFunctionInput = {\n /** ID of the function being invoked. */\n function_id: string\n /** Payload sent by the caller. */\n payload: Record<string, unknown>\n /** Routing action, if any. */\n action?: TriggerAction\n /** Auth context returned by the auth function for this session. */\n context: Record<string, unknown>\n}\n\n/**\n * Request object passed to {@link IIIClient.trigger}.\n *\n * @typeParam TInput - Type of the payload.\n */\nexport type TriggerRequest<TInput = unknown> = {\n /** ID of the function to invoke. */\n function_id: string\n /** Input data passed to the function. */\n payload: TInput\n /** Sets how the trigger is routed. Omit for a synchronous request/response. Specify for a specific routing scheme (e.g. `TriggerAction.Enqueue()`, `TriggerAction.Void()`). */\n action?: TriggerAction\n /** Override the default invocation timeout, in milliseconds. */\n timeoutMs?: number\n /** Arbitrary user-specifiable metadata supplied to the triggered handler function on every invocation. */\n metadata?: unknown\n}\n\nexport type InvokeFunctionMessage = {\n message_type: MessageType.InvokeFunction\n /**\n * This is optional for async invocations\n */\n invocation_id?: string\n /**\n * The path of the function.\n */\n function_id: string\n /**\n * The data to pass to the function\n */\n data: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n /**\n * Trigger action for queue routing or fire-and-forget\n */\n action?: TriggerAction\n /**\n * Optional per-invocation metadata (arbitrary JSON). Travels as a separate\n * channel from `data`. Omitted from the JSON when undefined; absence on\n * inbound means \"no metadata\" (backward compatible with older engines).\n */\n metadata?: JsonValue\n}\n\nexport type InvocationResultMessage = {\n message_type: MessageType.InvocationResult\n /**\n * The id of the invocation\n */\n invocation_id: string\n /**\n * The path of the function.\n */\n function_id: string\n result?: unknown\n error?: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n}\n\nexport type WorkerRegisteredMessage = {\n message_type: MessageType.WorkerRegistered\n worker_id: string\n /** Secret to present in a reattach frame on reconnect; absent on older engines. */\n reattach_token?: string\n}\n\nexport type UnregisterFunctionMessage = {\n message_type: MessageType.UnregisterFunction\n id: string\n}\n\n/**\n * Serializable reference to one end of a streaming channel. Can be included\n * in invocation payloads to pass channel endpoints between workers.\n */\nexport type StreamChannelRef = {\n /** Unique channel identifier. */\n channel_id: string\n /** Access key for authentication. */\n access_key: string\n /** Whether this ref is for reading or writing. */\n direction: 'read' | 'write'\n}\n\nexport type IIIMessage =\n | RegisterFunctionMessage\n | UnregisterFunctionMessage\n | InvokeFunctionMessage\n | InvocationResultMessage\n | RegisterTriggerMessage\n | RegisterTriggerTypeMessage\n | UnregisterTriggerMessage\n | UnregisterTriggerTypeMessage\n | TriggerRegistrationResultMessage\n | WorkerRegisteredMessage\n"],"mappings":";;AAeA,IAAY,cAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;KACD"}
|
|
@@ -10,9 +10,10 @@ let MessageType = /* @__PURE__ */ function(MessageType) {
|
|
|
10
10
|
MessageType["UnregisterTriggerType"] = "unregistertriggertype";
|
|
11
11
|
MessageType["TriggerRegistrationResult"] = "triggerregistrationresult";
|
|
12
12
|
MessageType["WorkerRegistered"] = "workerregistered";
|
|
13
|
+
MessageType["Reattach"] = "reattach";
|
|
13
14
|
return MessageType;
|
|
14
15
|
}({});
|
|
15
16
|
|
|
16
17
|
//#endregion
|
|
17
18
|
export { MessageType as t };
|
|
18
|
-
//# sourceMappingURL=iii-types-
|
|
19
|
+
//# sourceMappingURL=iii-types-wPYrg7hX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iii-types-wPYrg7hX.mjs","names":[],"sources":["../src/iii-types.ts"],"sourcesContent":["import type { HttpInvocationConfig } from '@iii-dev/helpers/http'\n\n/**\n * Any JSON value: the TypeScript equivalent of the engine's arbitrary-JSON\n * wire values (Rust `serde_json::Value`). Used where the wire contract is\n * \"any JSON\", e.g. per-invocation `metadata`.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue }\n\nexport enum MessageType {\n RegisterFunction = 'registerfunction',\n UnregisterFunction = 'unregisterfunction',\n InvokeFunction = 'invokefunction',\n InvocationResult = 'invocationresult',\n RegisterTriggerType = 'registertriggertype',\n RegisterTrigger = 'registertrigger',\n UnregisterTrigger = 'unregistertrigger',\n UnregisterTriggerType = 'unregistertriggertype',\n TriggerRegistrationResult = 'triggerregistrationresult',\n WorkerRegistered = 'workerregistered',\n Reattach = 'reattach',\n}\n\nexport type RegisterTriggerTypeMessage = {\n message_type: MessageType.RegisterTriggerType\n /** Unique identifier for the trigger type (e.g. `state`, `durable:subscriber`). */\n id: string\n /** Human-readable description of what this trigger type does. */\n description: string\n}\n\nexport type UnregisterTriggerTypeMessage = {\n message_type: MessageType.UnregisterTriggerType\n id: string\n}\n\nexport type UnregisterTriggerMessage = {\n message_type: MessageType.UnregisterTrigger\n id: string\n type?: string\n}\n\nexport type ErrorBody = {\n code: string\n message: string\n stacktrace?: string\n}\n\nexport type TriggerRegistrationResultMessage = {\n message_type: MessageType.TriggerRegistrationResult\n id: string\n type: string\n function_id: string\n error?: ErrorBody\n}\n\nexport type RegisterTriggerMessage = {\n /** Wire discriminator; always `MessageType.RegisterTrigger`. */\n message_type: MessageType.RegisterTrigger\n /** Unique trigger identifier, generated by the SDK during registration. */\n id: string\n /** Identifier of the registered trigger type this trigger uses (e.g. `storage::object-created`, `http`). */\n type: string\n /** ID of the function this trigger invokes when it fires. */\n function_id: string\n /** Trigger-type-specific configuration, matching the shape the trigger type expects. */\n config: unknown\n /** Arbitrary user-specifiable metadata supplied to the triggered handler function on every invocation. */\n metadata?: Record<string, unknown>\n}\n\nexport type RegisterFunctionFormat = {\n /**\n * The name of the parameter.\n */\n name?: string\n /**\n * The description of the parameter.\n */\n description?: string\n /**\n * The type of the parameter.\n */\n type?: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'map' | 'integer'\n /**\n * The body of the parameter (for objects).\n */\n properties?: Record<string, unknown>\n /**\n * The items of the parameter (for arrays).\n */\n items?: unknown\n /**\n * Whether the parameter is required.\n */\n required?: string[]\n [key: string]: unknown\n}\n\nexport type RegisterFunctionMessage = {\n message_type: MessageType.RegisterFunction\n /**\n * The path of the function (use :: for namespacing, e.g. external::my_lambda).\n */\n id: string\n /**\n * The description of the function.\n */\n description?: string\n /**\n * The request format of the function.\n */\n request_format?: RegisterFunctionFormat\n /**\n * The response format of the function.\n */\n response_format?: RegisterFunctionFormat\n /**\n * Arbitrary metadata attached to the function.\n */\n metadata?: Record<string, unknown>\n /**\n * HTTP invocation config for external HTTP functions (Lambda, Cloudflare Workers, etc.).\n */\n invocation?: HttpInvocationConfig\n}\n\n/**\n * Routing action for {@link TriggerRequest}. Determines how the engine\n * handles the invocation.\n *\n * - `enqueue`: Routes through a named queue for async processing.\n * - `void`: Fire-and-forget, no response.\n */\nexport type TriggerAction = { type: 'enqueue'; queue: string } | { type: 'void' }\n\n/**\n * Input passed to the RBAC middleware function on every function invocation\n * through the RBAC port. The middleware can inspect, modify, or reject the\n * call before it reaches the target function.\n */\nexport type MiddlewareFunctionInput = {\n /** ID of the function being invoked. */\n function_id: string\n /** Payload sent by the caller. */\n payload: Record<string, unknown>\n /** Routing action, if any. */\n action?: TriggerAction\n /** Auth context returned by the auth function for this session. */\n context: Record<string, unknown>\n}\n\n/**\n * Request object passed to {@link IIIClient.trigger}.\n *\n * @typeParam TInput - Type of the payload.\n */\nexport type TriggerRequest<TInput = unknown> = {\n /** ID of the function to invoke. */\n function_id: string\n /** Input data passed to the function. */\n payload: TInput\n /** Sets how the trigger is routed. Omit for a synchronous request/response. Specify for a specific routing scheme (e.g. `TriggerAction.Enqueue()`, `TriggerAction.Void()`). */\n action?: TriggerAction\n /** Override the default invocation timeout, in milliseconds. */\n timeoutMs?: number\n /** Arbitrary user-specifiable metadata supplied to the triggered handler function on every invocation. */\n metadata?: unknown\n}\n\nexport type InvokeFunctionMessage = {\n message_type: MessageType.InvokeFunction\n /**\n * This is optional for async invocations\n */\n invocation_id?: string\n /**\n * The path of the function.\n */\n function_id: string\n /**\n * The data to pass to the function\n */\n data: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n /**\n * Trigger action for queue routing or fire-and-forget\n */\n action?: TriggerAction\n /**\n * Optional per-invocation metadata (arbitrary JSON). Travels as a separate\n * channel from `data`. Omitted from the JSON when undefined; absence on\n * inbound means \"no metadata\" (backward compatible with older engines).\n */\n metadata?: JsonValue\n}\n\nexport type InvocationResultMessage = {\n message_type: MessageType.InvocationResult\n /**\n * The id of the invocation\n */\n invocation_id: string\n /**\n * The path of the function.\n */\n function_id: string\n result?: unknown\n error?: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n}\n\nexport type WorkerRegisteredMessage = {\n message_type: MessageType.WorkerRegistered\n worker_id: string\n /** Secret to present in a reattach frame on reconnect; absent on older engines. */\n reattach_token?: string\n}\n\nexport type UnregisterFunctionMessage = {\n message_type: MessageType.UnregisterFunction\n id: string\n}\n\n/**\n * Serializable reference to one end of a streaming channel. Can be included\n * in invocation payloads to pass channel endpoints between workers.\n */\nexport type StreamChannelRef = {\n /** Unique channel identifier. */\n channel_id: string\n /** Access key for authentication. */\n access_key: string\n /** Whether this ref is for reading or writing. */\n direction: 'read' | 'write'\n}\n\nexport type IIIMessage =\n | RegisterFunctionMessage\n | UnregisterFunctionMessage\n | InvokeFunctionMessage\n | InvocationResultMessage\n | RegisterTriggerMessage\n | RegisterTriggerTypeMessage\n | UnregisterTriggerMessage\n | UnregisterTriggerTypeMessage\n | TriggerRegistrationResultMessage\n | WorkerRegisteredMessage\n"],"mappings":";AAeA,IAAY,cAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;KACD"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_utils = require('./utils-63wxBJg-.cjs');
|
|
3
3
|
const require_errors = require('./errors.cjs');
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const require_iii_types = require('./iii-types-
|
|
4
|
+
const require_iii_constants = require('./iii-constants-M_BGfxGD.cjs');
|
|
5
|
+
const require_channels = require('./channels-C2ezAJ_g.cjs');
|
|
6
|
+
const require_iii_types = require('./iii-types-BvaIabiX.cjs');
|
|
7
7
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
8
8
|
let node_module = require("node:module");
|
|
9
9
|
let node_os = require("node:os");
|
|
@@ -249,6 +249,7 @@ var Sdk = class {
|
|
|
249
249
|
this.stopMetricsReporting();
|
|
250
250
|
await (0, _iii_dev_helpers_observability.shutdownOtel)();
|
|
251
251
|
this.clearReconnectTimeout();
|
|
252
|
+
this.stopHeartbeat();
|
|
252
253
|
for (const [_id, invocation] of this.invocations) {
|
|
253
254
|
if (invocation.timeout) clearTimeout(invocation.timeout);
|
|
254
255
|
invocation.reject(/* @__PURE__ */ new Error("iii is shutting down"));
|
|
@@ -307,7 +308,10 @@ var Sdk = class {
|
|
|
307
308
|
connect() {
|
|
308
309
|
if (this.isShuttingDown) return;
|
|
309
310
|
this.setConnectionState("connecting");
|
|
310
|
-
this.ws = new ws.WebSocket(this.address, {
|
|
311
|
+
this.ws = new ws.WebSocket(this.address, {
|
|
312
|
+
headers: this.options?.headers,
|
|
313
|
+
handshakeTimeout: require_iii_constants.WS_HANDSHAKE_TIMEOUT_MS
|
|
314
|
+
});
|
|
311
315
|
this.ws.on("open", this.onSocketOpen.bind(this));
|
|
312
316
|
this.ws.on("close", this.onSocketClose.bind(this));
|
|
313
317
|
this.ws.on("error", this.onSocketError.bind(this));
|
|
@@ -318,6 +322,26 @@ var Sdk = class {
|
|
|
318
322
|
this.reconnectTimeout = void 0;
|
|
319
323
|
}
|
|
320
324
|
}
|
|
325
|
+
startHeartbeat() {
|
|
326
|
+
this.stopHeartbeat();
|
|
327
|
+
this.idleTimeout = setTimeout(() => {
|
|
328
|
+
this.logError(`No inbound data for ${require_iii_constants.WS_IDLE_TIMEOUT_MS}ms, terminating connection to force reconnect`);
|
|
329
|
+
this.ws?.terminate();
|
|
330
|
+
}, require_iii_constants.WS_IDLE_TIMEOUT_MS);
|
|
331
|
+
this.heartbeatInterval = setInterval(() => {
|
|
332
|
+
if (this.ws && this.isOpen()) this.ws.ping();
|
|
333
|
+
}, require_iii_constants.WS_PING_INTERVAL_MS);
|
|
334
|
+
}
|
|
335
|
+
stopHeartbeat() {
|
|
336
|
+
if (this.heartbeatInterval) {
|
|
337
|
+
clearInterval(this.heartbeatInterval);
|
|
338
|
+
this.heartbeatInterval = void 0;
|
|
339
|
+
}
|
|
340
|
+
if (this.idleTimeout) {
|
|
341
|
+
clearTimeout(this.idleTimeout);
|
|
342
|
+
this.idleTimeout = void 0;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
321
345
|
scheduleReconnect() {
|
|
322
346
|
if (this.isShuttingDown) return;
|
|
323
347
|
const { maxRetries, initialDelayMs, backoffMultiplier, maxDelayMs, jitterFactor } = this.reconnectionConfig;
|
|
@@ -358,6 +382,7 @@ var Sdk = class {
|
|
|
358
382
|
(0, _iii_dev_helpers_observability.stopWorkerGauges)();
|
|
359
383
|
}
|
|
360
384
|
onSocketClose() {
|
|
385
|
+
this.stopHeartbeat();
|
|
361
386
|
this.ws?.removeAllListeners();
|
|
362
387
|
this.ws?.terminate();
|
|
363
388
|
this.ws = void 0;
|
|
@@ -370,6 +395,18 @@ var Sdk = class {
|
|
|
370
395
|
this.reconnectAttempt = 0;
|
|
371
396
|
this.setConnectionState("connected");
|
|
372
397
|
this.ws?.on("message", this.onMessage.bind(this));
|
|
398
|
+
const touch = () => {
|
|
399
|
+
this.idleTimeout?.refresh();
|
|
400
|
+
};
|
|
401
|
+
this.ws?.on("message", touch);
|
|
402
|
+
this.ws?.on("ping", touch);
|
|
403
|
+
this.ws?.on("pong", touch);
|
|
404
|
+
this.startHeartbeat();
|
|
405
|
+
if (this.workerId) this.sendMessageRaw(JSON.stringify({
|
|
406
|
+
type: require_iii_types.MessageType.Reattach,
|
|
407
|
+
previous_worker_id: this.workerId,
|
|
408
|
+
reattach_token: this.reattachToken
|
|
409
|
+
}));
|
|
373
410
|
this.triggerTypes.forEach(({ message }) => {
|
|
374
411
|
this.sendMessage(require_iii_types.MessageType.RegisterTriggerType, message, true);
|
|
375
412
|
});
|
|
@@ -619,8 +656,9 @@ var Sdk = class {
|
|
|
619
656
|
else if (msgType === require_iii_types.MessageType.UnregisterTrigger) this.onUnregisterTrigger(message);
|
|
620
657
|
else if (msgType === require_iii_types.MessageType.TriggerRegistrationResult) this.onTriggerRegistrationResult(message);
|
|
621
658
|
else if (msgType === require_iii_types.MessageType.WorkerRegistered) {
|
|
622
|
-
const { worker_id } = message;
|
|
659
|
+
const { worker_id, reattach_token } = message;
|
|
623
660
|
this.workerId = worker_id;
|
|
661
|
+
this.reattachToken = reattach_token;
|
|
624
662
|
console.debug("[iii] Worker registered with ID:", worker_id);
|
|
625
663
|
this.startMetricsReporting();
|
|
626
664
|
}
|