iii-sdk 0.17.0 → 0.18.0
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/helpers.cjs +30 -0
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +20 -0
- package/dist/helpers.d.cts.map +1 -0
- package/dist/helpers.d.mts +20 -0
- package/dist/helpers.d.mts.map +1 -0
- package/dist/helpers.mjs +24 -0
- package/dist/helpers.mjs.map +1 -0
- package/dist/index.cjs +11 -301
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -718
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -718
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -264
- package/dist/index.mjs.map +1 -1
- package/dist/state.d.cts +1 -1
- package/dist/state.d.mts +1 -1
- package/dist/stream.d.cts +267 -2
- package/dist/stream.d.cts.map +1 -0
- package/dist/stream.d.mts +267 -2
- package/dist/stream.d.mts.map +1 -0
- package/dist/utils-CuS1Knym.cjs +401 -0
- package/dist/utils-CuS1Knym.cjs.map +1 -0
- package/dist/utils-DXL7JI0q.mjs +319 -0
- package/dist/utils-DXL7JI0q.mjs.map +1 -0
- package/dist/utils-DcbZmefT.d.cts +707 -0
- package/dist/utils-DcbZmefT.d.cts.map +1 -0
- package/dist/utils-tcJ0Rzg-.d.mts +707 -0
- package/dist/utils-tcJ0Rzg-.d.mts.map +1 -0
- package/package.json +7 -2
- package/dist/stream-CNxp3Hhu.d.cts +0 -267
- package/dist/stream-CNxp3Hhu.d.cts.map +0 -1
- package/dist/stream-CPQKQv-x.d.mts +0 -267
- package/dist/stream-CPQKQv-x.d.mts.map +0 -1
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/iii-constants.ts","../src/iii.ts"],"mappings":";;;;;;;;AAaA;;;;;;;;;KAAY,sBAAA;EACV,IAAA;EACA,OAAA;EACA,WAAA;EACA,UAAA;AAAA;AAAA,cAGW,kBAAA,SAA2B,KAAA;EAAA,SACtB,IAAA;EAAA,SACA,WAAA;EAAA,SACA,UAAA;cAEJ,IAAA,EAAM,sBAAA;AAAA;;;;;;;AAZpB;;;;;;;;cCAa,eAAA;EAAA;;;;;;;;;;;cAaA,cAAA;EAAA,SAGH,mBAAA;EAAA,SAAA,GAAA;AAAA;;UAmBO,qBAAA;;EAEf,cAAA;;EAEA,UAAA;;EAEA,iBAAA;EA5BW;EA8BX,YAAA;;EAEA,UAAA;AAAA;;;AD7CF;AAAA,KE4DY,gBAAA;EACV,QAAA;EACA,YAAA;EACA,SAAA;EACA,iBAAA;AAAA;;;;AFzDF;;;;;;;;;KEwEY,WAAA;EFnEE,gEEqEZ,UAAA,WFrEwC;EEuExC,sBAAA;EAEA,mBAAA;EDrFW;;;;;EC2FX,kBAAA,GAAqB,OAAA,CAAQ,qBAAA;;;;;;EAM7B,IAAA,GAAO,IAAA,CAAK,UAAA;EAEZ,OAAA,GAAU,MAAA;EAEV,SAAA,GAAY,gBAAA;AAAA;;;;ADlEd;;;;;;;;;;;;;;ACyBA;;;;;cAi7Ba,aAAA;EA96BX;;;;AAgBF;;;;EAhBE;IAu7BkB,KAAA;EAAA,MAAkB,eAAA;EAn5B1B;;;;EAAA,qBAw5BA,eAAA;AAAA;;;;;;;;;;;;;;AAdZ;;;;cAkCa,cAAA,GAAkB,OAAA,UAAiB,OAAA,GAAU,WAAA,KAAc,IAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,197 +1,11 @@
|
|
|
1
|
+
import { c as ChannelWriter, i as isChannelRef, r as http, s as ChannelReader, t as detectProjectName } from "./utils-DXL7JI0q.mjs";
|
|
1
2
|
import { createRequire } from "node:module";
|
|
2
|
-
import { Readable, Writable } from "node:stream";
|
|
3
3
|
import { WebSocket } from "ws";
|
|
4
4
|
import { SpanKind, context, trace } from "@opentelemetry/api";
|
|
5
5
|
import * as os from "node:os";
|
|
6
6
|
import { Logger, SeverityNumber, extractContext, getLogger, initOtel, injectBaggage, injectTraceparent, recordSpanEvent, redactAndTruncate, registerWorkerGauges, resolveMaxBytesFromEnv, shutdownOtel, stopWorkerGauges, withSpan } from "@iii-dev/observability";
|
|
7
7
|
import { getMeter, getTracer } from "@iii-dev/observability/internal";
|
|
8
|
-
import * as fs from "node:fs";
|
|
9
|
-
import * as path from "node:path";
|
|
10
8
|
|
|
11
|
-
//#region src/channels.ts
|
|
12
|
-
/**
|
|
13
|
-
* Write end of a streaming channel. Provides both a Node.js `Writable` stream
|
|
14
|
-
* and a `sendMessage` method for sending structured text messages.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* const channel = await iii.createChannel()
|
|
19
|
-
*
|
|
20
|
-
* // Stream binary data
|
|
21
|
-
* channel.writer.stream.write(Buffer.from('hello'))
|
|
22
|
-
* channel.writer.stream.end()
|
|
23
|
-
*
|
|
24
|
-
* // Or send text messages
|
|
25
|
-
* channel.writer.sendMessage(JSON.stringify({ type: 'event', data: 'test' }))
|
|
26
|
-
* channel.writer.close()
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
var ChannelWriter = class ChannelWriter {
|
|
30
|
-
static {
|
|
31
|
-
this.FRAME_SIZE = 64 * 1024;
|
|
32
|
-
}
|
|
33
|
-
constructor(engineWsBase, ref) {
|
|
34
|
-
this.ws = null;
|
|
35
|
-
this.wsReady = false;
|
|
36
|
-
this.pendingMessages = [];
|
|
37
|
-
this.url = buildChannelUrl(engineWsBase, ref.channel_id, ref.access_key, "write");
|
|
38
|
-
this.stream = new Writable({
|
|
39
|
-
write: (chunk, _encoding, callback) => {
|
|
40
|
-
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
41
|
-
this.sendChunked(buf, callback);
|
|
42
|
-
},
|
|
43
|
-
final: (callback) => {
|
|
44
|
-
if (!this.ws) {
|
|
45
|
-
callback();
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const doClose = () => {
|
|
49
|
-
if (this.ws) this.ws.close(1e3, "stream_complete");
|
|
50
|
-
callback();
|
|
51
|
-
};
|
|
52
|
-
if (this.wsReady) setTimeout(doClose, 10);
|
|
53
|
-
else this.ws.on("open", () => setTimeout(doClose, 10));
|
|
54
|
-
},
|
|
55
|
-
destroy: (err, callback) => {
|
|
56
|
-
if (this.ws) this.ws.terminate();
|
|
57
|
-
callback(err);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
ensureConnected() {
|
|
62
|
-
if (this.ws) return;
|
|
63
|
-
this.ws = new WebSocket(this.url);
|
|
64
|
-
this.ws.on("open", () => {
|
|
65
|
-
this.wsReady = true;
|
|
66
|
-
for (const { data, callback } of this.pendingMessages) this.ws?.send(data, callback);
|
|
67
|
-
this.pendingMessages.length = 0;
|
|
68
|
-
});
|
|
69
|
-
this.ws.on("error", (err) => {
|
|
70
|
-
this.stream.destroy(err);
|
|
71
|
-
});
|
|
72
|
-
this.ws.on("close", () => {
|
|
73
|
-
if (!this.stream.destroyed) this.stream.destroy();
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
/** Send a text message through the channel. */
|
|
77
|
-
sendMessage(msg) {
|
|
78
|
-
this.ensureConnected();
|
|
79
|
-
this.sendRaw(msg, (err) => {
|
|
80
|
-
if (err) this.stream.destroy(err);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
/** Close the channel writer. */
|
|
84
|
-
close() {
|
|
85
|
-
if (!this.ws) return;
|
|
86
|
-
const doClose = () => {
|
|
87
|
-
if (this.ws) this.ws.close(1e3, "channel_close");
|
|
88
|
-
};
|
|
89
|
-
if (this.wsReady) doClose();
|
|
90
|
-
else this.ws.on("open", () => doClose());
|
|
91
|
-
}
|
|
92
|
-
sendChunked(data, callback) {
|
|
93
|
-
let offset = 0;
|
|
94
|
-
const sendNext = (err) => {
|
|
95
|
-
if (err) {
|
|
96
|
-
callback(err);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (offset >= data.length) {
|
|
100
|
-
callback(null);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const end = Math.min(offset + ChannelWriter.FRAME_SIZE, data.length);
|
|
104
|
-
const part = data.subarray(offset, end);
|
|
105
|
-
offset = end;
|
|
106
|
-
this.sendRaw(part, sendNext);
|
|
107
|
-
};
|
|
108
|
-
sendNext(null);
|
|
109
|
-
}
|
|
110
|
-
sendRaw(data, callback) {
|
|
111
|
-
this.ensureConnected();
|
|
112
|
-
if (this.wsReady && this.ws) this.ws.send(data, (err) => callback(err ?? null));
|
|
113
|
-
else this.pendingMessages.push({
|
|
114
|
-
data,
|
|
115
|
-
callback
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
/**
|
|
120
|
-
* Read end of a streaming channel. Provides both a Node.js `Readable` stream
|
|
121
|
-
* for binary data and an `onMessage` callback for structured text messages.
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* ```typescript
|
|
125
|
-
* const channel = await iii.createChannel()
|
|
126
|
-
*
|
|
127
|
-
* // Stream binary data
|
|
128
|
-
* channel.reader.stream.on('data', (chunk) => console.log(chunk))
|
|
129
|
-
*
|
|
130
|
-
* // Or receive text messages
|
|
131
|
-
* channel.reader.onMessage((msg) => console.log('Got:', msg))
|
|
132
|
-
* ```
|
|
133
|
-
*/
|
|
134
|
-
var ChannelReader = class {
|
|
135
|
-
constructor(engineWsBase, ref) {
|
|
136
|
-
this.ws = null;
|
|
137
|
-
this.connected = false;
|
|
138
|
-
this.messageCallbacks = [];
|
|
139
|
-
this.url = buildChannelUrl(engineWsBase, ref.channel_id, ref.access_key, "read");
|
|
140
|
-
const self = this;
|
|
141
|
-
this.stream = new Readable({
|
|
142
|
-
read() {
|
|
143
|
-
self.ensureConnected();
|
|
144
|
-
if (self.ws) self.ws.resume();
|
|
145
|
-
},
|
|
146
|
-
destroy(err, callback) {
|
|
147
|
-
if (self.ws && self.ws.readyState !== WebSocket.CLOSED) self.ws.terminate();
|
|
148
|
-
self.ws = null;
|
|
149
|
-
callback(err);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
ensureConnected() {
|
|
154
|
-
if (this.connected) return;
|
|
155
|
-
this.connected = true;
|
|
156
|
-
this.ws = new WebSocket(this.url);
|
|
157
|
-
this.ws.on("open", () => {
|
|
158
|
-
this.ws.binaryType = "nodebuffer";
|
|
159
|
-
});
|
|
160
|
-
this.ws.on("message", (data, isBinary) => {
|
|
161
|
-
if (isBinary) {
|
|
162
|
-
if (!this.stream.push(data)) this.ws?.pause();
|
|
163
|
-
} else {
|
|
164
|
-
const msg = data.toString("utf-8");
|
|
165
|
-
for (const cb of this.messageCallbacks) cb(msg);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
this.ws.on("close", () => {
|
|
169
|
-
this.ws = null;
|
|
170
|
-
if (!this.stream.destroyed) this.stream.push(null);
|
|
171
|
-
});
|
|
172
|
-
this.ws.on("error", (err) => {
|
|
173
|
-
this.stream.destroy(err);
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
/** Register a callback to receive text messages from the channel. */
|
|
177
|
-
onMessage(callback) {
|
|
178
|
-
this.messageCallbacks.push(callback);
|
|
179
|
-
}
|
|
180
|
-
async readAll() {
|
|
181
|
-
this.ensureConnected();
|
|
182
|
-
const chunks = [];
|
|
183
|
-
for await (const chunk of this.stream) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
184
|
-
return Buffer.concat(chunks);
|
|
185
|
-
}
|
|
186
|
-
close() {
|
|
187
|
-
if (this.ws && this.ws.readyState !== WebSocket.CLOSED) this.ws.close(1e3, "channel_close");
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
function buildChannelUrl(engineWsBase, channelId, accessKey, direction) {
|
|
191
|
-
return `${engineWsBase.replace(/\/$/, "")}/ws/channels/${channelId}?key=${encodeURIComponent(accessKey)}&dir=${direction}`;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
//#endregion
|
|
195
9
|
//#region src/errors.ts
|
|
196
10
|
var IIIInvocationError = class extends Error {
|
|
197
11
|
constructor(init) {
|
|
@@ -271,81 +85,6 @@ let MessageType = /* @__PURE__ */ function(MessageType) {
|
|
|
271
85
|
return MessageType;
|
|
272
86
|
}({});
|
|
273
87
|
|
|
274
|
-
//#endregion
|
|
275
|
-
//#region src/utils.ts
|
|
276
|
-
/**
|
|
277
|
-
* Returns a project identifier for telemetry, derived from the current working
|
|
278
|
-
* directory. Reads `package.json` `name` if present at `cwd`; otherwise falls
|
|
279
|
-
* back to the basename of `cwd`. Returns `undefined` only when both signals
|
|
280
|
-
* are unavailable (e.g. cwd is the filesystem root).
|
|
281
|
-
*
|
|
282
|
-
* No directory walking — only inspects `cwd` itself, so the SDK never reads
|
|
283
|
-
* files outside the user's explicit working directory.
|
|
284
|
-
*/
|
|
285
|
-
function detectProjectName(cwd = process.cwd()) {
|
|
286
|
-
try {
|
|
287
|
-
const manifest = path.join(cwd, "package.json");
|
|
288
|
-
if (fs.existsSync(manifest)) {
|
|
289
|
-
const parsed = JSON.parse(fs.readFileSync(manifest, "utf8"));
|
|
290
|
-
if (typeof parsed.name === "string") {
|
|
291
|
-
const trimmed = parsed.name.trim();
|
|
292
|
-
if (trimmed) return trimmed;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
} catch {}
|
|
296
|
-
return path.basename(cwd).trim() || void 0;
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Helper that wraps an HTTP-style handler (with separate `req`/`res` arguments)
|
|
300
|
-
* into the function handler format expected by the SDK.
|
|
301
|
-
*
|
|
302
|
-
* @param callback - Async handler receiving an {@link HttpRequest} and {@link HttpResponse}.
|
|
303
|
-
* @returns A function handler compatible with {@link ISdk.registerFunction}.
|
|
304
|
-
*
|
|
305
|
-
* @example
|
|
306
|
-
* ```typescript
|
|
307
|
-
* import { http } from 'iii-sdk'
|
|
308
|
-
*
|
|
309
|
-
* iii.registerFunction(
|
|
310
|
-
* 'my-api',
|
|
311
|
-
* http(async (req, res) => {
|
|
312
|
-
* res.status(200)
|
|
313
|
-
* res.headers({ 'content-type': 'application/json' })
|
|
314
|
-
* res.stream.end(JSON.stringify({ hello: 'world' }))
|
|
315
|
-
* res.close()
|
|
316
|
-
* }),
|
|
317
|
-
* )
|
|
318
|
-
* ```
|
|
319
|
-
*/
|
|
320
|
-
const http = (callback) => {
|
|
321
|
-
return async (req) => {
|
|
322
|
-
const { response, ...request } = req;
|
|
323
|
-
return callback(request, {
|
|
324
|
-
status: (status_code) => response.sendMessage(JSON.stringify({
|
|
325
|
-
type: "set_status",
|
|
326
|
-
status_code
|
|
327
|
-
})),
|
|
328
|
-
headers: (headers) => response.sendMessage(JSON.stringify({
|
|
329
|
-
type: "set_headers",
|
|
330
|
-
headers
|
|
331
|
-
})),
|
|
332
|
-
stream: response.stream,
|
|
333
|
-
close: () => response.close()
|
|
334
|
-
});
|
|
335
|
-
};
|
|
336
|
-
};
|
|
337
|
-
/**
|
|
338
|
-
* Type guard that checks if a value is a {@link StreamChannelRef}.
|
|
339
|
-
*
|
|
340
|
-
* @param value - Value to check.
|
|
341
|
-
* @returns `true` if the value is a valid `StreamChannelRef`.
|
|
342
|
-
*/
|
|
343
|
-
const isChannelRef = (value) => {
|
|
344
|
-
if (typeof value !== "object" || value === null) return false;
|
|
345
|
-
const maybe = value;
|
|
346
|
-
return typeof maybe.channel_id === "string" && typeof maybe.access_key === "string" && (maybe.direction === "read" || maybe.direction === "write");
|
|
347
|
-
};
|
|
348
|
-
|
|
349
88
|
//#endregion
|
|
350
89
|
//#region src/iii.ts
|
|
351
90
|
const { version: SDK_VERSION } = createRequire(import.meta.url)("../package.json");
|
|
@@ -505,7 +244,7 @@ var Sdk = class {
|
|
|
505
244
|
}
|
|
506
245
|
};
|
|
507
246
|
};
|
|
508
|
-
this.
|
|
247
|
+
this.__helpers_create_channel = async (bufferSize) => {
|
|
509
248
|
const result = await this.trigger({
|
|
510
249
|
function_id: "engine::channels::create",
|
|
511
250
|
payload: { buffer_size: bufferSize }
|
|
@@ -568,7 +307,7 @@ var Sdk = class {
|
|
|
568
307
|
});
|
|
569
308
|
});
|
|
570
309
|
};
|
|
571
|
-
this.
|
|
310
|
+
this.__helpers_create_stream = (streamName, stream) => {
|
|
572
311
|
this.registerFunction(`stream::get(${streamName})`, stream.get.bind(stream));
|
|
573
312
|
this.registerFunction(`stream::set(${streamName})`, stream.set.bind(stream));
|
|
574
313
|
this.registerFunction(`stream::delete(${streamName})`, stream.delete.bind(stream));
|