@meshagent/meshagent 0.35.6 → 0.35.8
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/CHANGELOG.md +12 -0
- package/dist/browser/containers-client.d.ts +79 -2
- package/dist/browser/containers-client.js +341 -19
- package/dist/browser/database-client.d.ts +95 -24
- package/dist/browser/database-client.js +150 -49
- package/dist/browser/messaging-client.d.ts +33 -52
- package/dist/browser/messaging-client.js +180 -184
- package/dist/browser/participant.d.ts +5 -3
- package/dist/browser/participant.js +9 -1
- package/dist/browser/room-client.js +2 -0
- package/dist/browser/room-event.d.ts +6 -2
- package/dist/browser/room-event.js +4 -2
- package/dist/browser/secrets-client.d.ts +86 -16
- package/dist/browser/secrets-client.js +243 -44
- package/dist/browser/storage-client.d.ts +17 -4
- package/dist/browser/storage-client.js +104 -16
- package/dist/esm/containers-client.d.ts +79 -2
- package/dist/esm/containers-client.js +341 -19
- package/dist/esm/database-client.d.ts +95 -24
- package/dist/esm/database-client.js +150 -49
- package/dist/esm/messaging-client.d.ts +33 -52
- package/dist/esm/messaging-client.js +179 -180
- package/dist/esm/participant.d.ts +5 -3
- package/dist/esm/participant.js +9 -1
- package/dist/esm/room-client.js +2 -0
- package/dist/esm/room-event.d.ts +6 -2
- package/dist/esm/room-event.js +4 -2
- package/dist/esm/secrets-client.d.ts +86 -16
- package/dist/esm/secrets-client.js +243 -44
- package/dist/esm/storage-client.d.ts +17 -4
- package/dist/esm/storage-client.js +103 -16
- package/dist/node/containers-client.d.ts +79 -2
- package/dist/node/containers-client.js +341 -19
- package/dist/node/database-client.d.ts +95 -24
- package/dist/node/database-client.js +150 -49
- package/dist/node/messaging-client.d.ts +33 -52
- package/dist/node/messaging-client.js +180 -184
- package/dist/node/participant.d.ts +5 -3
- package/dist/node/participant.js +9 -1
- package/dist/node/room-client.js +2 -0
- package/dist/node/room-event.d.ts +6 -2
- package/dist/node/room-event.js +4 -2
- package/dist/node/secrets-client.d.ts +86 -16
- package/dist/node/secrets-client.js +243 -44
- package/dist/node/storage-client.d.ts +17 -4
- package/dist/node/storage-client.js +104 -16
- package/package.json +1 -1
|
@@ -17,11 +17,14 @@ function toPortPairs(values) {
|
|
|
17
17
|
}
|
|
18
18
|
function toCredentials(values) {
|
|
19
19
|
return values.map((entry) => ({
|
|
20
|
-
registry: entry.registry,
|
|
20
|
+
registry: entry.registry ?? null,
|
|
21
21
|
username: entry.username,
|
|
22
22
|
password: entry.password,
|
|
23
23
|
}));
|
|
24
24
|
}
|
|
25
|
+
function toMountList(values) {
|
|
26
|
+
return values.map((entry) => entry);
|
|
27
|
+
}
|
|
25
28
|
function readStringField(data, field, operation) {
|
|
26
29
|
const value = data[field];
|
|
27
30
|
if (typeof value !== "string") {
|
|
@@ -29,29 +32,126 @@ function readStringField(data, field, operation) {
|
|
|
29
32
|
}
|
|
30
33
|
return value;
|
|
31
34
|
}
|
|
32
|
-
function
|
|
33
|
-
const
|
|
35
|
+
function readIntegerField(data, field, operation) {
|
|
36
|
+
const value = data[field];
|
|
37
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
38
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
function readOptionalIntegerField(data, field, operation) {
|
|
43
|
+
const value = data[field];
|
|
44
|
+
if (value === undefined || value === null) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
48
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
function decodeUtf8(data, operation) {
|
|
53
|
+
try {
|
|
54
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(data);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new RoomServerException(`containers.${operation} returned invalid UTF-8 data`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function decodeJsonStatus(data, operation) {
|
|
61
|
+
const text = decodeUtf8(data, operation);
|
|
34
62
|
let parsed;
|
|
35
63
|
try {
|
|
36
64
|
parsed = JSON.parse(text);
|
|
37
65
|
}
|
|
38
66
|
catch {
|
|
39
|
-
throw new RoomServerException(
|
|
67
|
+
throw new RoomServerException(`containers.${operation} returned an invalid status payload`);
|
|
40
68
|
}
|
|
41
69
|
if (!isRecord(parsed)) {
|
|
42
|
-
throw new RoomServerException(
|
|
70
|
+
throw new RoomServerException(`containers.${operation} returned an invalid status payload`);
|
|
43
71
|
}
|
|
44
72
|
const status = parsed["status"];
|
|
45
73
|
if (typeof status !== "number" || !Number.isInteger(status)) {
|
|
46
|
-
throw new RoomServerException(
|
|
74
|
+
throw new RoomServerException(`containers.${operation} returned an invalid status payload`);
|
|
47
75
|
}
|
|
48
76
|
return status;
|
|
49
77
|
}
|
|
78
|
+
function normalizeImageLabels(labelsRaw, operation) {
|
|
79
|
+
if (Array.isArray(labelsRaw)) {
|
|
80
|
+
const labels = {};
|
|
81
|
+
for (const entry of labelsRaw) {
|
|
82
|
+
if (!isRecord(entry)) {
|
|
83
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
84
|
+
}
|
|
85
|
+
const key = entry["key"];
|
|
86
|
+
const value = entry["value"];
|
|
87
|
+
if (typeof key !== "string" || typeof value !== "string") {
|
|
88
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
89
|
+
}
|
|
90
|
+
labels[key] = value;
|
|
91
|
+
}
|
|
92
|
+
return labels;
|
|
93
|
+
}
|
|
94
|
+
if (isRecord(labelsRaw)) {
|
|
95
|
+
const labels = {};
|
|
96
|
+
for (const [key, value] of Object.entries(labelsRaw)) {
|
|
97
|
+
if (typeof value !== "string") {
|
|
98
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
99
|
+
}
|
|
100
|
+
labels[key] = value;
|
|
101
|
+
}
|
|
102
|
+
return labels;
|
|
103
|
+
}
|
|
104
|
+
if (labelsRaw === undefined || labelsRaw === null) {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
108
|
+
}
|
|
109
|
+
function parseImportedImage(data, operation) {
|
|
110
|
+
const resolvedRef = data["resolved_ref"];
|
|
111
|
+
const refsRaw = data["refs"];
|
|
112
|
+
if (typeof resolvedRef !== "string" || !Array.isArray(refsRaw) || refsRaw.some((entry) => typeof entry !== "string")) {
|
|
113
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
resolvedRef,
|
|
117
|
+
refs: refsRaw,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function parseBuildJob(data, operation) {
|
|
121
|
+
const id = readStringField(data, "id", operation);
|
|
122
|
+
const tag = readStringField(data, "tag", operation);
|
|
123
|
+
const status = readStringField(data, "status", operation);
|
|
124
|
+
if (!["queued", "running", "failed", "cancelled", "succeeded"].includes(status)) {
|
|
125
|
+
throw new RoomServerException(`unexpected return type from containers.${operation}`);
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
id,
|
|
129
|
+
tag,
|
|
130
|
+
status: status,
|
|
131
|
+
exitCode: readOptionalIntegerField(data, "exit_code", operation),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function buildRequestPayload(params) {
|
|
135
|
+
return {
|
|
136
|
+
tag: params.tag,
|
|
137
|
+
mounts: toMountList(params.mounts),
|
|
138
|
+
context_path: params.contextPath,
|
|
139
|
+
dockerfile_path: params.dockerfilePath ?? null,
|
|
140
|
+
private: params.private ?? false,
|
|
141
|
+
credentials: toCredentials(params.credentials ?? []),
|
|
142
|
+
context_archive_path: params.contextArchivePath ?? null,
|
|
143
|
+
context_archive_ref: params.contextArchiveRef ?? null,
|
|
144
|
+
context_archive_mount_path: params.contextArchiveMountPath ?? null,
|
|
145
|
+
context_archive_arch: params.contextArchiveArch ?? null,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
50
148
|
export class ExecSession {
|
|
51
149
|
constructor(params) {
|
|
52
150
|
this.previousOutput = [];
|
|
151
|
+
this.previousError = [];
|
|
53
152
|
this.resultCompleter = new Completer();
|
|
54
153
|
this.outputController = new StreamController();
|
|
154
|
+
this.errorController = new StreamController();
|
|
55
155
|
this.queuedInput = [];
|
|
56
156
|
this.inputClosed = false;
|
|
57
157
|
this.closed = false;
|
|
@@ -62,6 +162,7 @@ export class ExecSession {
|
|
|
62
162
|
this.tty = params.tty;
|
|
63
163
|
this.result = this.resultCompleter.fut;
|
|
64
164
|
this.output = this.outputController.stream;
|
|
165
|
+
this.stderr = this.errorController.stream;
|
|
65
166
|
}
|
|
66
167
|
async *inputStream() {
|
|
67
168
|
yield new BinaryContent({
|
|
@@ -116,6 +217,7 @@ export class ExecSession {
|
|
|
116
217
|
this.closed = true;
|
|
117
218
|
this.closeInputStream();
|
|
118
219
|
this.outputController.close();
|
|
220
|
+
this.errorController.close();
|
|
119
221
|
}
|
|
120
222
|
closeError(error) {
|
|
121
223
|
if (!this.resultCompleter.completed) {
|
|
@@ -124,11 +226,16 @@ export class ExecSession {
|
|
|
124
226
|
this.closed = true;
|
|
125
227
|
this.closeInputStream();
|
|
126
228
|
this.outputController.close();
|
|
229
|
+
this.errorController.close();
|
|
127
230
|
}
|
|
128
231
|
addOutput(data) {
|
|
129
232
|
this.previousOutput.push(data);
|
|
130
233
|
this.outputController.add(data);
|
|
131
234
|
}
|
|
235
|
+
addError(data) {
|
|
236
|
+
this.previousError.push(data);
|
|
237
|
+
this.errorController.add(data);
|
|
238
|
+
}
|
|
132
239
|
get isClosed() {
|
|
133
240
|
return this.closed;
|
|
134
241
|
}
|
|
@@ -171,7 +278,7 @@ export class ContainersClient {
|
|
|
171
278
|
}
|
|
172
279
|
async listImages() {
|
|
173
280
|
const output = await this.invoke("list_images", {});
|
|
174
|
-
if (!(output instanceof JsonContent)) {
|
|
281
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
175
282
|
throw this.unexpectedResponseError("list_images");
|
|
176
283
|
}
|
|
177
284
|
const imagesRaw = output.json["images"];
|
|
@@ -195,17 +302,65 @@ export class ContainersClient {
|
|
|
195
302
|
id,
|
|
196
303
|
tags: normalizedTags,
|
|
197
304
|
size: typeof size === "number" ? size : undefined,
|
|
198
|
-
labels:
|
|
305
|
+
labels: normalizeImageLabels(labelsRaw, "list_images"),
|
|
199
306
|
});
|
|
200
307
|
}
|
|
201
308
|
return images;
|
|
202
309
|
}
|
|
310
|
+
async deleteImage(params) {
|
|
311
|
+
await this.invoke("delete_image", {
|
|
312
|
+
image: params.image,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
203
315
|
async pullImage(params) {
|
|
204
316
|
await this.invoke("pull_image", {
|
|
205
317
|
tag: params.tag,
|
|
206
318
|
credentials: toCredentials(params.credentials ?? []),
|
|
207
319
|
});
|
|
208
320
|
}
|
|
321
|
+
async pushImage(params) {
|
|
322
|
+
const output = await this.invoke("push_image", {
|
|
323
|
+
tag: params.tag,
|
|
324
|
+
credentials: toCredentials(params.credentials ?? []),
|
|
325
|
+
private: params.private ?? false,
|
|
326
|
+
});
|
|
327
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
328
|
+
throw this.unexpectedResponseError("push_image");
|
|
329
|
+
}
|
|
330
|
+
return readStringField(output.json, "container_id", "push_image");
|
|
331
|
+
}
|
|
332
|
+
async load(params) {
|
|
333
|
+
const output = await this.invoke("load", {
|
|
334
|
+
archive_path: params.archivePath,
|
|
335
|
+
});
|
|
336
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
337
|
+
throw this.unexpectedResponseError("load");
|
|
338
|
+
}
|
|
339
|
+
return parseImportedImage(output.json, "load");
|
|
340
|
+
}
|
|
341
|
+
async loadImage(params) {
|
|
342
|
+
const output = await this.invoke("load_image", {
|
|
343
|
+
mounts: toMountList(params.mounts),
|
|
344
|
+
archive_path: params.archivePath,
|
|
345
|
+
private: params.private ?? false,
|
|
346
|
+
});
|
|
347
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
348
|
+
throw this.unexpectedResponseError("load_image");
|
|
349
|
+
}
|
|
350
|
+
return readStringField(output.json, "container_id", "load_image");
|
|
351
|
+
}
|
|
352
|
+
async saveImage(params) {
|
|
353
|
+
const output = await this.invoke("save_image", {
|
|
354
|
+
tag: params.tag,
|
|
355
|
+
mounts: toMountList(params.mounts),
|
|
356
|
+
archive_path: params.archivePath,
|
|
357
|
+
private: params.private ?? false,
|
|
358
|
+
});
|
|
359
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
360
|
+
throw this.unexpectedResponseError("save_image");
|
|
361
|
+
}
|
|
362
|
+
return readStringField(output.json, "container_id", "save_image");
|
|
363
|
+
}
|
|
209
364
|
async run(params) {
|
|
210
365
|
const output = await this.invoke("run", {
|
|
211
366
|
image: params.image,
|
|
@@ -228,6 +383,46 @@ export class ContainersClient {
|
|
|
228
383
|
}
|
|
229
384
|
return readStringField(output.json, "container_id", "run");
|
|
230
385
|
}
|
|
386
|
+
async startBuild(params) {
|
|
387
|
+
const output = await this.invoke("start_build", buildRequestPayload(params));
|
|
388
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
389
|
+
throw this.unexpectedResponseError("start_build");
|
|
390
|
+
}
|
|
391
|
+
return readStringField(output.json, "build_id", "start_build");
|
|
392
|
+
}
|
|
393
|
+
async build(params) {
|
|
394
|
+
const output = await this.invoke("build", buildRequestPayload(params));
|
|
395
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
396
|
+
throw this.unexpectedResponseError("build");
|
|
397
|
+
}
|
|
398
|
+
return readStringField(output.json, "build_id", "build");
|
|
399
|
+
}
|
|
400
|
+
async listBuilds() {
|
|
401
|
+
const output = await this.invoke("list_builds", {});
|
|
402
|
+
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
403
|
+
throw this.unexpectedResponseError("list_builds");
|
|
404
|
+
}
|
|
405
|
+
const buildsRaw = output.json["builds"];
|
|
406
|
+
if (!Array.isArray(buildsRaw)) {
|
|
407
|
+
throw this.unexpectedResponseError("list_builds");
|
|
408
|
+
}
|
|
409
|
+
return buildsRaw.map((entry) => {
|
|
410
|
+
if (!isRecord(entry)) {
|
|
411
|
+
throw this.unexpectedResponseError("list_builds");
|
|
412
|
+
}
|
|
413
|
+
return parseBuildJob(entry, "list_builds");
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
async cancelBuild(params) {
|
|
417
|
+
await this.invoke("cancel_build", {
|
|
418
|
+
build_id: params.buildId,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
async deleteBuild(params) {
|
|
422
|
+
await this.invoke("delete_build", {
|
|
423
|
+
build_id: params.buildId,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
231
426
|
async runService(params) {
|
|
232
427
|
const output = await this.invoke("run_service", {
|
|
233
428
|
service_id: params.serviceId,
|
|
@@ -257,6 +452,12 @@ export class ContainersClient {
|
|
|
257
452
|
if (chunk instanceof ErrorContent) {
|
|
258
453
|
throw new RoomServerException(chunk.text, chunk.code);
|
|
259
454
|
}
|
|
455
|
+
if (chunk instanceof ControlContent) {
|
|
456
|
+
if (chunk.method === "close") {
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
throw this.unexpectedResponseError("exec");
|
|
460
|
+
}
|
|
260
461
|
if (!(chunk instanceof BinaryContent)) {
|
|
261
462
|
throw this.unexpectedResponseError("exec");
|
|
262
463
|
}
|
|
@@ -268,8 +469,12 @@ export class ContainersClient {
|
|
|
268
469
|
session.addOutput(chunk.data);
|
|
269
470
|
continue;
|
|
270
471
|
}
|
|
472
|
+
if (channel === 2) {
|
|
473
|
+
session.addError(chunk.data);
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
271
476
|
if (channel === 3) {
|
|
272
|
-
session.close(decodeJsonStatus(chunk.data));
|
|
477
|
+
session.close(decodeJsonStatus(chunk.data, "exec"));
|
|
273
478
|
return;
|
|
274
479
|
}
|
|
275
480
|
}
|
|
@@ -283,7 +488,7 @@ export class ContainersClient {
|
|
|
283
488
|
async stop(params) {
|
|
284
489
|
await this.invoke("stop_container", {
|
|
285
490
|
container_id: params.containerId,
|
|
286
|
-
force: params.force ??
|
|
491
|
+
force: params.force ?? false,
|
|
287
492
|
});
|
|
288
493
|
}
|
|
289
494
|
async waitForExit(params) {
|
|
@@ -293,11 +498,7 @@ export class ContainersClient {
|
|
|
293
498
|
if (!(output instanceof JsonContent) || !isRecord(output.json)) {
|
|
294
499
|
throw this.unexpectedResponseError("wait_for_exit");
|
|
295
500
|
}
|
|
296
|
-
|
|
297
|
-
if (typeof exitCode !== "number" || !Number.isInteger(exitCode)) {
|
|
298
|
-
throw this.unexpectedResponseError("wait_for_exit");
|
|
299
|
-
}
|
|
300
|
-
return exitCode;
|
|
501
|
+
return readIntegerField(output.json, "exit_code", "wait_for_exit");
|
|
301
502
|
}
|
|
302
503
|
async deleteContainer(params) {
|
|
303
504
|
await this.invoke("delete_container", {
|
|
@@ -338,13 +539,20 @@ export class ContainersClient {
|
|
|
338
539
|
input: inputStream(),
|
|
339
540
|
})
|
|
340
541
|
.then(async (stream) => {
|
|
341
|
-
const decoder = new TextDecoder();
|
|
342
542
|
for await (const chunk of stream) {
|
|
343
543
|
if (chunk instanceof ErrorContent) {
|
|
344
544
|
throw new RoomServerException(chunk.text, chunk.code);
|
|
345
545
|
}
|
|
346
546
|
if (chunk instanceof ControlContent) {
|
|
347
|
-
|
|
547
|
+
if (chunk.method === "close") {
|
|
548
|
+
closeInputStream();
|
|
549
|
+
streamController.close();
|
|
550
|
+
if (!result.completed) {
|
|
551
|
+
result.complete();
|
|
552
|
+
}
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
throw this.unexpectedResponseError("logs");
|
|
348
556
|
}
|
|
349
557
|
if (!(chunk instanceof BinaryContent)) {
|
|
350
558
|
throw this.unexpectedResponseError("logs");
|
|
@@ -356,11 +564,125 @@ export class ContainersClient {
|
|
|
356
564
|
if (channel !== 1) {
|
|
357
565
|
continue;
|
|
358
566
|
}
|
|
359
|
-
streamController.add(
|
|
567
|
+
streamController.add(decodeUtf8(chunk.data, "logs"));
|
|
568
|
+
}
|
|
569
|
+
closeInputStream();
|
|
570
|
+
streamController.close();
|
|
571
|
+
if (!result.completed) {
|
|
572
|
+
result.complete();
|
|
573
|
+
}
|
|
574
|
+
})
|
|
575
|
+
.catch((error) => {
|
|
576
|
+
closeInputStream();
|
|
577
|
+
streamController.close();
|
|
578
|
+
if (!result.completed) {
|
|
579
|
+
result.completeError(error);
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
const outputStream = {
|
|
583
|
+
[Symbol.asyncIterator]() {
|
|
584
|
+
const it = streamController.stream[Symbol.asyncIterator]();
|
|
585
|
+
return {
|
|
586
|
+
async next() {
|
|
587
|
+
return await it.next();
|
|
588
|
+
},
|
|
589
|
+
async return(value) {
|
|
590
|
+
closeInputStream();
|
|
591
|
+
return await it.return?.(value) ?? { done: true, value };
|
|
592
|
+
},
|
|
593
|
+
async throw(e) {
|
|
594
|
+
closeInputStream();
|
|
595
|
+
if (it.throw) {
|
|
596
|
+
return await it.throw(e);
|
|
597
|
+
}
|
|
598
|
+
throw e;
|
|
599
|
+
},
|
|
600
|
+
};
|
|
601
|
+
},
|
|
602
|
+
};
|
|
603
|
+
return {
|
|
604
|
+
stream: outputStream,
|
|
605
|
+
result: result.fut,
|
|
606
|
+
cancel: async () => {
|
|
607
|
+
closeInputStream();
|
|
608
|
+
await result.fut.catch(() => undefined);
|
|
609
|
+
},
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
getBuildLogs(params) {
|
|
613
|
+
const requestId = uuidv4();
|
|
614
|
+
const closeInput = new Completer();
|
|
615
|
+
const streamController = new StreamController();
|
|
616
|
+
const result = new Completer();
|
|
617
|
+
let inputClosed = false;
|
|
618
|
+
const closeInputStream = () => {
|
|
619
|
+
if (inputClosed) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
inputClosed = true;
|
|
623
|
+
if (!closeInput.completed) {
|
|
624
|
+
closeInput.complete();
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
const inputStream = async function* () {
|
|
628
|
+
yield new BinaryContent({
|
|
629
|
+
data: new Uint8Array(0),
|
|
630
|
+
headers: {
|
|
631
|
+
kind: "start",
|
|
632
|
+
request_id: requestId,
|
|
633
|
+
build_id: params.buildId,
|
|
634
|
+
follow: params.follow ?? true,
|
|
635
|
+
},
|
|
636
|
+
});
|
|
637
|
+
await closeInput.fut;
|
|
638
|
+
};
|
|
639
|
+
this.room
|
|
640
|
+
.invokeStream({
|
|
641
|
+
toolkit: "containers",
|
|
642
|
+
tool: "get_build_logs",
|
|
643
|
+
input: inputStream(),
|
|
644
|
+
})
|
|
645
|
+
.then(async (stream) => {
|
|
646
|
+
for await (const chunk of stream) {
|
|
647
|
+
if (chunk instanceof ErrorContent) {
|
|
648
|
+
throw new RoomServerException(chunk.text, chunk.code);
|
|
649
|
+
}
|
|
650
|
+
if (chunk instanceof ControlContent) {
|
|
651
|
+
if (chunk.method === "close") {
|
|
652
|
+
closeInputStream();
|
|
653
|
+
streamController.close();
|
|
654
|
+
if (!result.completed) {
|
|
655
|
+
result.complete(null);
|
|
656
|
+
}
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
throw this.unexpectedResponseError("get_build_logs");
|
|
660
|
+
}
|
|
661
|
+
if (!(chunk instanceof BinaryContent)) {
|
|
662
|
+
throw this.unexpectedResponseError("get_build_logs");
|
|
663
|
+
}
|
|
664
|
+
const channel = chunk.headers["channel"];
|
|
665
|
+
if (typeof channel !== "number") {
|
|
666
|
+
throw new RoomServerException("containers.get_build_logs returned a chunk without a valid channel");
|
|
667
|
+
}
|
|
668
|
+
if (channel === 1) {
|
|
669
|
+
streamController.add(decodeUtf8(chunk.data, "get_build_logs"));
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
if (channel === 3) {
|
|
673
|
+
closeInputStream();
|
|
674
|
+
streamController.close();
|
|
675
|
+
if (!result.completed) {
|
|
676
|
+
result.complete(decodeJsonStatus(chunk.data, "get_build_logs"));
|
|
677
|
+
}
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
360
680
|
}
|
|
361
681
|
closeInputStream();
|
|
362
682
|
streamController.close();
|
|
363
|
-
result.
|
|
683
|
+
if (!result.completed) {
|
|
684
|
+
result.complete(null);
|
|
685
|
+
}
|
|
364
686
|
})
|
|
365
687
|
.catch((error) => {
|
|
366
688
|
closeInputStream();
|