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