@syllm/brickly-test-host 0.11.0 → 0.12.1
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/README.md +17 -1
- package/dist/host.cjs +585 -14
- package/dist/index.cjs +489 -13
- package/dist/sources.lst +1 -0
- package/index.d.ts +157 -93
- package/package.json +2 -2
package/dist/host.cjs
CHANGED
|
@@ -24210,14 +24210,14 @@ var require_varint = __commonJS({
|
|
|
24210
24210
|
"../../node_modules/@bufbuild/protobuf/dist/commonjs/wire/varint.js"(exports2) {
|
|
24211
24211
|
"use strict";
|
|
24212
24212
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
24213
|
-
exports2.varint64read =
|
|
24213
|
+
exports2.varint64read = varint64read2;
|
|
24214
24214
|
exports2.varint64write = varint64write;
|
|
24215
24215
|
exports2.int64FromString = int64FromString2;
|
|
24216
24216
|
exports2.int64ToString = int64ToString2;
|
|
24217
24217
|
exports2.uInt64ToString = uInt64ToString2;
|
|
24218
24218
|
exports2.varint32write = varint32write;
|
|
24219
|
-
exports2.varint32read =
|
|
24220
|
-
function
|
|
24219
|
+
exports2.varint32read = varint32read2;
|
|
24220
|
+
function varint64read2() {
|
|
24221
24221
|
const buf = this.buf;
|
|
24222
24222
|
let pos = this.pos;
|
|
24223
24223
|
let lo = 0;
|
|
@@ -24376,7 +24376,7 @@ var require_varint = __commonJS({
|
|
|
24376
24376
|
bytes.push(1);
|
|
24377
24377
|
}
|
|
24378
24378
|
}
|
|
24379
|
-
function
|
|
24379
|
+
function varint32read2() {
|
|
24380
24380
|
let b = this.buf[this.pos++];
|
|
24381
24381
|
if ((b & 128) === 0) {
|
|
24382
24382
|
this.assertBounds();
|
|
@@ -36412,6 +36412,45 @@ var import_grpc_js2 = __toESM(require_src3());
|
|
|
36412
36412
|
var import_grpc_js = __toESM(require_src3());
|
|
36413
36413
|
|
|
36414
36414
|
// ../../node_modules/@bufbuild/protobuf/dist/esm/wire/varint.js
|
|
36415
|
+
function varint64read() {
|
|
36416
|
+
const buf = this.buf;
|
|
36417
|
+
let pos = this.pos;
|
|
36418
|
+
let lo = 0;
|
|
36419
|
+
let hi = 0;
|
|
36420
|
+
for (let shift = 0; shift < 28; shift += 7) {
|
|
36421
|
+
const b = buf[pos++];
|
|
36422
|
+
lo |= (b & 127) << shift;
|
|
36423
|
+
if ((b & 128) == 0) {
|
|
36424
|
+
this.pos = pos;
|
|
36425
|
+
this.assertBounds();
|
|
36426
|
+
this.varint64Lo = lo;
|
|
36427
|
+
this.varint64Hi = hi;
|
|
36428
|
+
return;
|
|
36429
|
+
}
|
|
36430
|
+
}
|
|
36431
|
+
const middleByte = buf[pos++];
|
|
36432
|
+
lo |= (middleByte & 15) << 28;
|
|
36433
|
+
hi = (middleByte & 112) >> 4;
|
|
36434
|
+
if ((middleByte & 128) == 0) {
|
|
36435
|
+
this.pos = pos;
|
|
36436
|
+
this.assertBounds();
|
|
36437
|
+
this.varint64Lo = lo;
|
|
36438
|
+
this.varint64Hi = hi;
|
|
36439
|
+
return;
|
|
36440
|
+
}
|
|
36441
|
+
for (let shift = 3; shift <= 31; shift += 7) {
|
|
36442
|
+
const b = buf[pos++];
|
|
36443
|
+
hi |= (b & 127) << shift;
|
|
36444
|
+
if ((b & 128) == 0) {
|
|
36445
|
+
this.pos = pos;
|
|
36446
|
+
this.assertBounds();
|
|
36447
|
+
this.varint64Lo = lo;
|
|
36448
|
+
this.varint64Hi = hi;
|
|
36449
|
+
return;
|
|
36450
|
+
}
|
|
36451
|
+
}
|
|
36452
|
+
throw new Error("invalid varint");
|
|
36453
|
+
}
|
|
36415
36454
|
var TWO_PWR_32_DBL = 4294967296;
|
|
36416
36455
|
function int64FromString(dec) {
|
|
36417
36456
|
const minus = dec[0] === "-";
|
|
@@ -36486,6 +36525,40 @@ var decimalFrom1e7WithLeadingZeros = (digit1e7) => {
|
|
|
36486
36525
|
const partial = String(digit1e7);
|
|
36487
36526
|
return "0000000".slice(partial.length) + partial;
|
|
36488
36527
|
};
|
|
36528
|
+
function varint32read() {
|
|
36529
|
+
let b = this.buf[this.pos++];
|
|
36530
|
+
if ((b & 128) === 0) {
|
|
36531
|
+
this.assertBounds();
|
|
36532
|
+
return b;
|
|
36533
|
+
}
|
|
36534
|
+
let result = b & 127;
|
|
36535
|
+
b = this.buf[this.pos++];
|
|
36536
|
+
result |= (b & 127) << 7;
|
|
36537
|
+
if ((b & 128) === 0) {
|
|
36538
|
+
this.assertBounds();
|
|
36539
|
+
return result;
|
|
36540
|
+
}
|
|
36541
|
+
b = this.buf[this.pos++];
|
|
36542
|
+
result |= (b & 127) << 14;
|
|
36543
|
+
if ((b & 128) === 0) {
|
|
36544
|
+
this.assertBounds();
|
|
36545
|
+
return result;
|
|
36546
|
+
}
|
|
36547
|
+
b = this.buf[this.pos++];
|
|
36548
|
+
result |= (b & 127) << 21;
|
|
36549
|
+
if ((b & 128) === 0) {
|
|
36550
|
+
this.assertBounds();
|
|
36551
|
+
return result;
|
|
36552
|
+
}
|
|
36553
|
+
b = this.buf[this.pos++];
|
|
36554
|
+
result |= (b & 15) << 28;
|
|
36555
|
+
for (let readBytes = 5; (b & 128) !== 0 && readBytes < 10; readBytes++)
|
|
36556
|
+
b = this.buf[this.pos++];
|
|
36557
|
+
if ((b & 128) !== 0)
|
|
36558
|
+
throw new Error("invalid varint");
|
|
36559
|
+
this.assertBounds();
|
|
36560
|
+
return result >>> 0;
|
|
36561
|
+
}
|
|
36489
36562
|
|
|
36490
36563
|
// ../../node_modules/@bufbuild/protobuf/dist/esm/proto-int64.js
|
|
36491
36564
|
var protoInt64 = /* @__PURE__ */ makeInt64Support();
|
|
@@ -36988,6 +37061,206 @@ function varint32Size(value) {
|
|
|
36988
37061
|
return 4;
|
|
36989
37062
|
return 5;
|
|
36990
37063
|
}
|
|
37064
|
+
var BinaryReader = class {
|
|
37065
|
+
constructor(buf, decodeUtf8 = getTextEncoding().decodeUtf8) {
|
|
37066
|
+
this.decodeUtf8 = decodeUtf8;
|
|
37067
|
+
this.varint64Lo = 0;
|
|
37068
|
+
this.varint64Hi = 0;
|
|
37069
|
+
this.varint64 = varint64read;
|
|
37070
|
+
this.uint32 = varint32read;
|
|
37071
|
+
this.buf = buf;
|
|
37072
|
+
this.len = buf.length;
|
|
37073
|
+
this.pos = 0;
|
|
37074
|
+
this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
37075
|
+
}
|
|
37076
|
+
/**
|
|
37077
|
+
* Reads a tag - field number and wire type. Tags are uint32 varints; values
|
|
37078
|
+
* that do not fit in uint32 are rejected.
|
|
37079
|
+
*/
|
|
37080
|
+
tag() {
|
|
37081
|
+
const start = this.pos;
|
|
37082
|
+
const tag = this.uint32();
|
|
37083
|
+
const bytesRead = this.pos - start;
|
|
37084
|
+
if (bytesRead > 5 || bytesRead == 5 && this.buf[this.pos - 1] > 15) {
|
|
37085
|
+
throw new Error("illegal tag: varint overflows uint32");
|
|
37086
|
+
}
|
|
37087
|
+
const fieldNo = tag >>> 3;
|
|
37088
|
+
const wireType = tag & 7;
|
|
37089
|
+
if (fieldNo <= 0 || wireType > 5) {
|
|
37090
|
+
throw new Error("illegal tag: field no " + fieldNo + " wire type " + wireType);
|
|
37091
|
+
}
|
|
37092
|
+
return [fieldNo, wireType];
|
|
37093
|
+
}
|
|
37094
|
+
/**
|
|
37095
|
+
* Skip one element and return the skipped data.
|
|
37096
|
+
*
|
|
37097
|
+
* When skipping StartGroup, provide the tags field number to check for
|
|
37098
|
+
* matching field number in the EndGroup tag. Recursion into nested groups
|
|
37099
|
+
* is guarded by the `recursionLimit` argument: When the limit is reached,
|
|
37100
|
+
* this method throws.
|
|
37101
|
+
*/
|
|
37102
|
+
skip(wireType, fieldNo, recursionLimit = 100) {
|
|
37103
|
+
let start = this.pos;
|
|
37104
|
+
switch (wireType) {
|
|
37105
|
+
case WireType.Varint:
|
|
37106
|
+
while (this.buf[this.pos++] & 128) {
|
|
37107
|
+
}
|
|
37108
|
+
break;
|
|
37109
|
+
// @ts-ignore TS7029: Fallthrough case in switch -- ignore instead of expect-error for compiler settings without noFallthroughCasesInSwitch: true
|
|
37110
|
+
case WireType.Bit64:
|
|
37111
|
+
this.pos += 4;
|
|
37112
|
+
case WireType.Bit32:
|
|
37113
|
+
this.pos += 4;
|
|
37114
|
+
break;
|
|
37115
|
+
case WireType.LengthDelimited:
|
|
37116
|
+
let len = this.uint32();
|
|
37117
|
+
this.pos += len;
|
|
37118
|
+
break;
|
|
37119
|
+
case WireType.StartGroup:
|
|
37120
|
+
if (recursionLimit <= 0) {
|
|
37121
|
+
throw new Error("maximum recursion depth reached");
|
|
37122
|
+
}
|
|
37123
|
+
for (; ; ) {
|
|
37124
|
+
const [fn, wt] = this.tag();
|
|
37125
|
+
if (wt === WireType.EndGroup) {
|
|
37126
|
+
if (fieldNo !== void 0 && fn !== fieldNo) {
|
|
37127
|
+
throw new Error("invalid end group tag");
|
|
37128
|
+
}
|
|
37129
|
+
break;
|
|
37130
|
+
}
|
|
37131
|
+
this.skip(wt, fn, recursionLimit - 1);
|
|
37132
|
+
}
|
|
37133
|
+
break;
|
|
37134
|
+
default:
|
|
37135
|
+
throw new Error("cant skip wire type " + wireType);
|
|
37136
|
+
}
|
|
37137
|
+
this.assertBounds();
|
|
37138
|
+
return this.buf.subarray(start, this.pos);
|
|
37139
|
+
}
|
|
37140
|
+
/**
|
|
37141
|
+
* Throws error if position in byte array is out of range.
|
|
37142
|
+
*/
|
|
37143
|
+
assertBounds() {
|
|
37144
|
+
if (this.pos > this.len)
|
|
37145
|
+
throw new RangeError("premature EOF");
|
|
37146
|
+
}
|
|
37147
|
+
/**
|
|
37148
|
+
* Read a `int32` field, a signed 32 bit varint.
|
|
37149
|
+
*/
|
|
37150
|
+
int32() {
|
|
37151
|
+
return this.uint32() | 0;
|
|
37152
|
+
}
|
|
37153
|
+
/**
|
|
37154
|
+
* Read a `sint32` field, a signed, zigzag-encoded 32-bit varint.
|
|
37155
|
+
*/
|
|
37156
|
+
sint32() {
|
|
37157
|
+
let zze = this.uint32();
|
|
37158
|
+
return zze >>> 1 ^ -(zze & 1);
|
|
37159
|
+
}
|
|
37160
|
+
/**
|
|
37161
|
+
* Read a `int64` field, a signed 64-bit varint.
|
|
37162
|
+
*/
|
|
37163
|
+
int64() {
|
|
37164
|
+
this.varint64();
|
|
37165
|
+
return protoInt64.dec(this.varint64Lo, this.varint64Hi);
|
|
37166
|
+
}
|
|
37167
|
+
/**
|
|
37168
|
+
* Read a `uint64` field, an unsigned 64-bit varint.
|
|
37169
|
+
*/
|
|
37170
|
+
uint64() {
|
|
37171
|
+
this.varint64();
|
|
37172
|
+
return protoInt64.uDec(this.varint64Lo, this.varint64Hi);
|
|
37173
|
+
}
|
|
37174
|
+
/**
|
|
37175
|
+
* Read a `sint64` field, a signed, zig-zag-encoded 64-bit varint.
|
|
37176
|
+
*/
|
|
37177
|
+
sint64() {
|
|
37178
|
+
this.varint64();
|
|
37179
|
+
let lo = this.varint64Lo;
|
|
37180
|
+
let hi = this.varint64Hi;
|
|
37181
|
+
let s = -(lo & 1);
|
|
37182
|
+
lo = (lo >>> 1 | (hi & 1) << 31) ^ s;
|
|
37183
|
+
hi = hi >>> 1 ^ s;
|
|
37184
|
+
return protoInt64.dec(lo, hi);
|
|
37185
|
+
}
|
|
37186
|
+
/**
|
|
37187
|
+
* Read a `bool` field, a variant.
|
|
37188
|
+
*/
|
|
37189
|
+
bool() {
|
|
37190
|
+
const b = this.buf[this.pos];
|
|
37191
|
+
if (b < 128) {
|
|
37192
|
+
this.pos++;
|
|
37193
|
+
return b !== 0;
|
|
37194
|
+
}
|
|
37195
|
+
this.varint64();
|
|
37196
|
+
return this.varint64Lo !== 0 || this.varint64Hi !== 0;
|
|
37197
|
+
}
|
|
37198
|
+
/**
|
|
37199
|
+
* Read a `fixed32` field, an unsigned, fixed-length 32-bit integer.
|
|
37200
|
+
*/
|
|
37201
|
+
fixed32() {
|
|
37202
|
+
return this.view.getUint32((this.pos += 4) - 4, true);
|
|
37203
|
+
}
|
|
37204
|
+
/**
|
|
37205
|
+
* Read a `sfixed32` field, a signed, fixed-length 32-bit integer.
|
|
37206
|
+
*/
|
|
37207
|
+
sfixed32() {
|
|
37208
|
+
return this.view.getInt32((this.pos += 4) - 4, true);
|
|
37209
|
+
}
|
|
37210
|
+
/**
|
|
37211
|
+
* Read a `fixed64` field, an unsigned, fixed-length 64 bit integer.
|
|
37212
|
+
*/
|
|
37213
|
+
fixed64() {
|
|
37214
|
+
return protoInt64.uDec(this.sfixed32(), this.sfixed32());
|
|
37215
|
+
}
|
|
37216
|
+
/**
|
|
37217
|
+
* Read a `fixed64` field, a signed, fixed-length 64-bit integer.
|
|
37218
|
+
*/
|
|
37219
|
+
sfixed64() {
|
|
37220
|
+
return protoInt64.dec(this.sfixed32(), this.sfixed32());
|
|
37221
|
+
}
|
|
37222
|
+
/**
|
|
37223
|
+
* Read a `float` field, 32-bit floating point number.
|
|
37224
|
+
*/
|
|
37225
|
+
float() {
|
|
37226
|
+
return this.view.getFloat32((this.pos += 4) - 4, true);
|
|
37227
|
+
}
|
|
37228
|
+
/**
|
|
37229
|
+
* Read a `double` field, a 64-bit floating point number.
|
|
37230
|
+
*/
|
|
37231
|
+
double() {
|
|
37232
|
+
return this.view.getFloat64((this.pos += 8) - 8, true);
|
|
37233
|
+
}
|
|
37234
|
+
/**
|
|
37235
|
+
* Read a `bytes` field, length-delimited arbitrary data.
|
|
37236
|
+
*/
|
|
37237
|
+
bytes() {
|
|
37238
|
+
let len = this.uint32(), start = this.pos;
|
|
37239
|
+
this.pos += len;
|
|
37240
|
+
this.assertBounds();
|
|
37241
|
+
return this.buf.subarray(start, start + len);
|
|
37242
|
+
}
|
|
37243
|
+
/**
|
|
37244
|
+
* Read a `string` field, length-delimited data converted to UTF-8 text. If
|
|
37245
|
+
* `strict` is true, throw on invalid UTF-8 instead of substituting U+FFFD.
|
|
37246
|
+
*/
|
|
37247
|
+
string(strict) {
|
|
37248
|
+
const bytes = this.bytes();
|
|
37249
|
+
const len = bytes.length;
|
|
37250
|
+
if (len <= ASCII_MAX_LENGTH) {
|
|
37251
|
+
const codes = new Array(len);
|
|
37252
|
+
for (let i = 0; i < len; i++) {
|
|
37253
|
+
const byte = bytes[i];
|
|
37254
|
+
if (byte > 127) {
|
|
37255
|
+
return this.decodeUtf8(bytes, strict);
|
|
37256
|
+
}
|
|
37257
|
+
codes[i] = byte;
|
|
37258
|
+
}
|
|
37259
|
+
return String.fromCharCode.apply(String, codes);
|
|
37260
|
+
}
|
|
37261
|
+
return this.decodeUtf8(bytes, strict);
|
|
37262
|
+
}
|
|
37263
|
+
};
|
|
36991
37264
|
function assertInt32(arg) {
|
|
36992
37265
|
if (typeof arg == "string") {
|
|
36993
37266
|
arg = Number(arg);
|
|
@@ -37086,6 +37359,17 @@ function toBrickGrpcStatus(error) {
|
|
|
37086
37359
|
metadata
|
|
37087
37360
|
};
|
|
37088
37361
|
}
|
|
37362
|
+
function unpackBrickError(error) {
|
|
37363
|
+
const bin = error.metadata?.get("grpc-status-details-bin")[0];
|
|
37364
|
+
if (!bin) return void 0;
|
|
37365
|
+
const bytes = typeof bin === "string" ? Buffer.from(bin, "utf8") : bin;
|
|
37366
|
+
for (const item of decodeRpcStatus(bytes)) {
|
|
37367
|
+
if (item.typeUrl === BRICK_ERROR_TYPE_URL || item.typeUrl.endsWith("BrickError")) {
|
|
37368
|
+
return import_error.BrickError.decode(item.value);
|
|
37369
|
+
}
|
|
37370
|
+
}
|
|
37371
|
+
return void 0;
|
|
37372
|
+
}
|
|
37089
37373
|
function registeredDetail(code, error) {
|
|
37090
37374
|
const extra = error && typeof error === "object" && "detail" in error && error.detail && typeof error.detail === "object" ? error.detail : {};
|
|
37091
37375
|
const text = (key, fallback) => typeof extra[key] === "string" ? extra[key] : fallback;
|
|
@@ -37256,6 +37540,19 @@ function encodeRpcStatus(code, message, details) {
|
|
|
37256
37540
|
}
|
|
37257
37541
|
return Buffer.from(writer.finish());
|
|
37258
37542
|
}
|
|
37543
|
+
function decodeRpcStatus(bytes) {
|
|
37544
|
+
const reader = new BinaryReader(bytes);
|
|
37545
|
+
const details = [];
|
|
37546
|
+
while (reader.pos < reader.len) {
|
|
37547
|
+
const tag = reader.uint32();
|
|
37548
|
+
const field = tag >>> 3;
|
|
37549
|
+
if (field === 3) details.push(import_any.Any.decode(reader.bytes()));
|
|
37550
|
+
else if (field === 1) reader.int32();
|
|
37551
|
+
else if (field === 2) reader.string();
|
|
37552
|
+
else reader.skip(tag & 7);
|
|
37553
|
+
}
|
|
37554
|
+
return details;
|
|
37555
|
+
}
|
|
37259
37556
|
|
|
37260
37557
|
// ../../src/main/runtime/transport/connector-interact-relay.ts
|
|
37261
37558
|
function relayConnectorInteract(call, openInteract) {
|
|
@@ -40403,19 +40700,30 @@ var HostGrpcServer = class {
|
|
|
40403
40700
|
});
|
|
40404
40701
|
this.server.addService(
|
|
40405
40702
|
import_resource.ResourceServiceService,
|
|
40406
|
-
createResourceServiceImplementation(
|
|
40703
|
+
createResourceServiceImplementation(
|
|
40704
|
+
this.resources,
|
|
40705
|
+
this.spawns,
|
|
40706
|
+
this.resourceContext,
|
|
40707
|
+
this.helperAccess
|
|
40708
|
+
)
|
|
40407
40709
|
);
|
|
40408
40710
|
this.server.addService(
|
|
40409
40711
|
import_event.EventServiceService,
|
|
40410
40712
|
createEventServiceImplementation(this.events, this.spawns, () => this.eventRouter)
|
|
40411
40713
|
);
|
|
40412
|
-
this.server.addService(
|
|
40714
|
+
this.server.addService(
|
|
40715
|
+
import_storage.StorageServiceService,
|
|
40716
|
+
createStorageServiceImplementation(this.storage, this.spawns)
|
|
40717
|
+
);
|
|
40413
40718
|
this.server.addService(
|
|
40414
40719
|
import_brick_storage.BrickStorageServiceService,
|
|
40415
40720
|
createBrickStorageServiceImplementation(() => this.brickStorageService, this.spawns)
|
|
40416
40721
|
);
|
|
40417
40722
|
this.server.addService(import_system.SystemServiceService, createSystemServiceImplementation(this.spawns));
|
|
40418
|
-
this.server.addService(
|
|
40723
|
+
this.server.addService(
|
|
40724
|
+
import_window.WindowServiceService,
|
|
40725
|
+
createWindowServiceImplementation(this.windows, this.spawns)
|
|
40726
|
+
);
|
|
40419
40727
|
this.server.addService(
|
|
40420
40728
|
import_connector.BrickConnectorServiceService,
|
|
40421
40729
|
createConnectorServiceImplementation(this.connector, this.spawns)
|
|
@@ -40473,6 +40781,10 @@ var HostGrpcServer = class {
|
|
|
40473
40781
|
getHandle(runtimeHandleId) {
|
|
40474
40782
|
return this.handles.get(runtimeHandleId);
|
|
40475
40783
|
}
|
|
40784
|
+
/** 已注册 runtime 句柄快照(测试驱动面用,只读)。 */
|
|
40785
|
+
listHandles() {
|
|
40786
|
+
return [...this.handles.values()];
|
|
40787
|
+
}
|
|
40476
40788
|
async listen(host = "127.0.0.1", port = 0) {
|
|
40477
40789
|
assertLoopbackHost(host);
|
|
40478
40790
|
if (this.started) {
|
|
@@ -40480,13 +40792,17 @@ var HostGrpcServer = class {
|
|
|
40480
40792
|
return this.endpoint;
|
|
40481
40793
|
}
|
|
40482
40794
|
const bound = await new Promise((resolve2, reject) => {
|
|
40483
|
-
this.server.bindAsync(
|
|
40484
|
-
|
|
40485
|
-
|
|
40486
|
-
|
|
40795
|
+
this.server.bindAsync(
|
|
40796
|
+
`${host}:${port}`,
|
|
40797
|
+
import_grpc_js12.ServerCredentials.createInsecure(),
|
|
40798
|
+
(error, boundPort) => {
|
|
40799
|
+
if (error) {
|
|
40800
|
+
reject(error);
|
|
40801
|
+
return;
|
|
40802
|
+
}
|
|
40803
|
+
resolve2(`${host}:${boundPort}`);
|
|
40487
40804
|
}
|
|
40488
|
-
|
|
40489
|
-
});
|
|
40805
|
+
);
|
|
40490
40806
|
});
|
|
40491
40807
|
this.endpoint = bound;
|
|
40492
40808
|
this.started = true;
|
|
@@ -40691,11 +41007,174 @@ async function startTestHost(options = {}) {
|
|
|
40691
41007
|
};
|
|
40692
41008
|
}
|
|
40693
41009
|
|
|
41010
|
+
// ../../src/main/runtime/transport/test-host/drive.ts
|
|
41011
|
+
var CANNED_UI_METHODS = [
|
|
41012
|
+
"createBrowserWindow",
|
|
41013
|
+
"callWindow",
|
|
41014
|
+
"closeWindow",
|
|
41015
|
+
"forceCloseWindow",
|
|
41016
|
+
"listWindows",
|
|
41017
|
+
"sendToChild",
|
|
41018
|
+
"replyToChild",
|
|
41019
|
+
"emitToChild"
|
|
41020
|
+
];
|
|
41021
|
+
var HostDriver = class {
|
|
41022
|
+
constructor(testHost) {
|
|
41023
|
+
this.testHost = testHost;
|
|
41024
|
+
}
|
|
41025
|
+
cannedUi = /* @__PURE__ */ new Map();
|
|
41026
|
+
uiCallLog = [];
|
|
41027
|
+
uiHandlerInstalled = false;
|
|
41028
|
+
/** 再铸一套 spawn 凭据(依赖 invoke 等需要多个 runtime 的用例)。 */
|
|
41029
|
+
spawn(input) {
|
|
41030
|
+
const credentials2 = this.testHost.host.createSpawn({
|
|
41031
|
+
brickId: input.brickId,
|
|
41032
|
+
instanceId: input.instanceId,
|
|
41033
|
+
origin: input.origin ?? "development",
|
|
41034
|
+
version: input.version ?? "0.0.0"
|
|
41035
|
+
});
|
|
41036
|
+
const record = this.testHost.host.spawns.get(credentials2.spawnId);
|
|
41037
|
+
return {
|
|
41038
|
+
...credentials2,
|
|
41039
|
+
brickId: record?.brickId ?? input.brickId,
|
|
41040
|
+
instanceId: record?.instanceId ?? credentials2.spawnId
|
|
41041
|
+
};
|
|
41042
|
+
}
|
|
41043
|
+
/** 已注册 runtime 句柄快照(测试等待/断言用)。 */
|
|
41044
|
+
runtimes() {
|
|
41045
|
+
return this.testHost.host.listHandles().map((handle) => ({
|
|
41046
|
+
spawnId: handle.runtimeHandleId,
|
|
41047
|
+
brickId: handle.brickId,
|
|
41048
|
+
instanceId: handle.instanceId
|
|
41049
|
+
}));
|
|
41050
|
+
}
|
|
41051
|
+
/** 等待 runtime 完成注册,拿到 host→runtime 通道句柄。 */
|
|
41052
|
+
async waitHandle(spawnId, timeoutMs = 1e4) {
|
|
41053
|
+
const id = spawnId ?? this.testHost.spawnCredentials.spawnId;
|
|
41054
|
+
const deadline = Date.now() + timeoutMs;
|
|
41055
|
+
while (Date.now() < deadline) {
|
|
41056
|
+
const handle = this.testHost.host.getHandle(id);
|
|
41057
|
+
if (handle) return handle;
|
|
41058
|
+
await sleep(40);
|
|
41059
|
+
}
|
|
41060
|
+
throw new Error(`\u7B49\u5F85 runtime \u6CE8\u518C\u8D85\u65F6\uFF1AspawnId=${id}`);
|
|
41061
|
+
}
|
|
41062
|
+
/** host→runtime 单向 invoke;错误按 brick 码结构化返回而不抛出。 */
|
|
41063
|
+
async invoke(input) {
|
|
41064
|
+
try {
|
|
41065
|
+
const handle = await this.waitHandle(input.spawnId, input.timeoutMs);
|
|
41066
|
+
const result = await handle.channel.invoke(
|
|
41067
|
+
{ commandId: input.commandId, input: jsToBrickValue(input.input ?? null) },
|
|
41068
|
+
{ deadlineMs: input.timeoutMs }
|
|
41069
|
+
);
|
|
41070
|
+
return { ok: true, result: brickValueToJs(result.result) };
|
|
41071
|
+
} catch (error) {
|
|
41072
|
+
return { ok: false, error: serializeError(error) };
|
|
41073
|
+
}
|
|
41074
|
+
}
|
|
41075
|
+
/** host→runtime interact 批量模式:open → closeInput → 收 events 与 final。 */
|
|
41076
|
+
async interact(input) {
|
|
41077
|
+
try {
|
|
41078
|
+
const handle = await this.waitHandle(input.spawnId, input.timeoutMs);
|
|
41079
|
+
const signal = input.timeoutMs ? AbortSignal.timeout(input.timeoutMs) : void 0;
|
|
41080
|
+
const { events, result } = await handle.channel.stream(
|
|
41081
|
+
input.commandId,
|
|
41082
|
+
jsToBrickValue(input.input ?? null),
|
|
41083
|
+
{ signal }
|
|
41084
|
+
);
|
|
41085
|
+
return { ok: true, events: events.map(brickValueToJs), result: brickValueToJs(result) };
|
|
41086
|
+
} catch (error) {
|
|
41087
|
+
return { ok: false, error: serializeError(error) };
|
|
41088
|
+
}
|
|
41089
|
+
}
|
|
41090
|
+
/** 往指定 runtime 推 domain event(经真 HostEventBus 投递到订阅流)。 */
|
|
41091
|
+
async pushEvent(input) {
|
|
41092
|
+
const spawnId = input.spawnId ?? this.testHost.spawnCredentials.spawnId;
|
|
41093
|
+
const record = this.testHost.host.spawns.get(spawnId);
|
|
41094
|
+
const instanceId = record?.instanceId ?? spawnId;
|
|
41095
|
+
this.testHost.host.events.publishTo(
|
|
41096
|
+
instanceId,
|
|
41097
|
+
input.topic,
|
|
41098
|
+
jsToBrickValue(input.payload ?? null)
|
|
41099
|
+
);
|
|
41100
|
+
}
|
|
41101
|
+
/**
|
|
41102
|
+
* 注册 UI 方法罐头响应(重复注册后者覆盖前者)。
|
|
41103
|
+
* method 取 HostUiHandler 方法名,如 createBrowserWindow / callWindow。
|
|
41104
|
+
*/
|
|
41105
|
+
setUiResponse(method, result) {
|
|
41106
|
+
if (!CANNED_UI_METHODS.includes(method)) {
|
|
41107
|
+
throw new Error(`\u672A\u77E5 UI \u65B9\u6CD5\uFF1A${method}\uFF08\u53EF\u9009\uFF1A${CANNED_UI_METHODS.join(", ")}\uFF09`);
|
|
41108
|
+
}
|
|
41109
|
+
this.cannedUi.set(method, result);
|
|
41110
|
+
if (!this.uiHandlerInstalled) {
|
|
41111
|
+
this.installUiHandler();
|
|
41112
|
+
this.uiHandlerInstalled = true;
|
|
41113
|
+
}
|
|
41114
|
+
}
|
|
41115
|
+
/** UI handler 被调记录(按序),/reset 清空。 */
|
|
41116
|
+
uiCalls() {
|
|
41117
|
+
return [...this.uiCallLog];
|
|
41118
|
+
}
|
|
41119
|
+
/** 清驱动面状态:罐头响应与 UI 调用记录(不动 storage/故障规则,那些归 control)。 */
|
|
41120
|
+
reset() {
|
|
41121
|
+
this.cannedUi.clear();
|
|
41122
|
+
this.uiCallLog.length = 0;
|
|
41123
|
+
}
|
|
41124
|
+
installUiHandler() {
|
|
41125
|
+
const dispatch = (method, args) => {
|
|
41126
|
+
this.uiCallLog.push({ method, args, at: Date.now() });
|
|
41127
|
+
if (!this.cannedUi.has(method)) {
|
|
41128
|
+
throw new Error(`UI \u65B9\u6CD5 ${method} \u672A\u6CE8\u518C\u7F50\u5934\u54CD\u5E94`);
|
|
41129
|
+
}
|
|
41130
|
+
return this.cannedUi.get(method);
|
|
41131
|
+
};
|
|
41132
|
+
const handler = {
|
|
41133
|
+
createBrowserWindow: (...args) => dispatch("createBrowserWindow", args),
|
|
41134
|
+
callWindow: (...args) => dispatch("callWindow", args),
|
|
41135
|
+
closeWindow: (...args) => dispatch("closeWindow", args),
|
|
41136
|
+
forceCloseWindow: (...args) => dispatch("forceCloseWindow", args),
|
|
41137
|
+
listWindows: (...args) => dispatch("listWindows", args),
|
|
41138
|
+
sendToChild: (...args) => dispatch("sendToChild", args),
|
|
41139
|
+
replyToChild: (...args) => dispatch("replyToChild", args),
|
|
41140
|
+
emitToChild: (...args) => dispatch("emitToChild", args)
|
|
41141
|
+
};
|
|
41142
|
+
this.testHost.host.setUiHandler(handler);
|
|
41143
|
+
}
|
|
41144
|
+
};
|
|
41145
|
+
function createHostDriver(testHost) {
|
|
41146
|
+
return new HostDriver(testHost);
|
|
41147
|
+
}
|
|
41148
|
+
function serializeError(error) {
|
|
41149
|
+
const serviceError = error;
|
|
41150
|
+
let brick;
|
|
41151
|
+
try {
|
|
41152
|
+
brick = unpackBrickError(serviceError);
|
|
41153
|
+
} catch {
|
|
41154
|
+
brick = void 0;
|
|
41155
|
+
}
|
|
41156
|
+
return {
|
|
41157
|
+
brickCode: brick?.code,
|
|
41158
|
+
message: serviceError?.message ?? String(error),
|
|
41159
|
+
grpcStatus: serviceError?.code
|
|
41160
|
+
};
|
|
41161
|
+
}
|
|
41162
|
+
function sleep(ms) {
|
|
41163
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
41164
|
+
}
|
|
41165
|
+
|
|
40694
41166
|
// ../../src/main/runtime/transport/test-host/main.ts
|
|
40695
41167
|
async function main() {
|
|
40696
41168
|
const testHost = await startTestHost();
|
|
41169
|
+
const driver = createHostDriver(testHost);
|
|
40697
41170
|
const control = (0, import_node_http.createServer)((request, response) => {
|
|
40698
|
-
void handle(request, response).catch(() =>
|
|
41171
|
+
void handle(request, response).catch((error) => {
|
|
41172
|
+
process.stderr.write(
|
|
41173
|
+
`[test-host] \u63A7\u5236\u9762\u5185\u90E8\u9519\u8BEF: ${error instanceof Error ? error.stack ?? error.message : String(error)}
|
|
41174
|
+
`
|
|
41175
|
+
);
|
|
41176
|
+
reply(response, 500, { error: "control internal error" });
|
|
41177
|
+
});
|
|
40699
41178
|
});
|
|
40700
41179
|
async function handle(request, response) {
|
|
40701
41180
|
const url = request.url ?? "/";
|
|
@@ -40716,6 +41195,7 @@ async function main() {
|
|
|
40716
41195
|
}
|
|
40717
41196
|
if (request.method === "POST" && url === "/reset") {
|
|
40718
41197
|
testHost.control.reset();
|
|
41198
|
+
driver.reset();
|
|
40719
41199
|
reply(response, 200, { ok: true });
|
|
40720
41200
|
return;
|
|
40721
41201
|
}
|
|
@@ -40723,6 +41203,97 @@ async function main() {
|
|
|
40723
41203
|
reply(response, 200, { calls: testHost.control.recordedCalls() });
|
|
40724
41204
|
return;
|
|
40725
41205
|
}
|
|
41206
|
+
if (request.method === "POST" && url === "/spawn") {
|
|
41207
|
+
const body = await readBody(request);
|
|
41208
|
+
if (typeof body.brickId !== "string" || body.brickId.length === 0) {
|
|
41209
|
+
reply(response, 400, { error: "spawn \u9700\u8981 brickId" });
|
|
41210
|
+
return;
|
|
41211
|
+
}
|
|
41212
|
+
reply(
|
|
41213
|
+
response,
|
|
41214
|
+
200,
|
|
41215
|
+
driver.spawn({
|
|
41216
|
+
brickId: body.brickId,
|
|
41217
|
+
instanceId: typeof body.instanceId === "string" ? body.instanceId : void 0,
|
|
41218
|
+
origin: body.origin === "installed" || body.origin === "review" || body.origin === "platform" ? body.origin : "development",
|
|
41219
|
+
version: typeof body.version === "string" ? body.version : void 0
|
|
41220
|
+
})
|
|
41221
|
+
);
|
|
41222
|
+
return;
|
|
41223
|
+
}
|
|
41224
|
+
if (request.method === "POST" && url === "/invoke") {
|
|
41225
|
+
const body = await readBody(request);
|
|
41226
|
+
if (typeof body.commandId !== "string" || body.commandId.length === 0) {
|
|
41227
|
+
reply(response, 400, { error: "invoke \u9700\u8981 commandId" });
|
|
41228
|
+
return;
|
|
41229
|
+
}
|
|
41230
|
+
reply(
|
|
41231
|
+
response,
|
|
41232
|
+
200,
|
|
41233
|
+
await driver.invoke({
|
|
41234
|
+
spawnId: typeof body.spawnId === "string" ? body.spawnId : void 0,
|
|
41235
|
+
commandId: body.commandId,
|
|
41236
|
+
input: body.input,
|
|
41237
|
+
timeoutMs: typeof body.timeoutMs === "number" ? body.timeoutMs : void 0
|
|
41238
|
+
})
|
|
41239
|
+
);
|
|
41240
|
+
return;
|
|
41241
|
+
}
|
|
41242
|
+
if (request.method === "POST" && url === "/interact") {
|
|
41243
|
+
const body = await readBody(request);
|
|
41244
|
+
if (typeof body.commandId !== "string" || body.commandId.length === 0) {
|
|
41245
|
+
reply(response, 400, { error: "interact \u9700\u8981 commandId" });
|
|
41246
|
+
return;
|
|
41247
|
+
}
|
|
41248
|
+
reply(
|
|
41249
|
+
response,
|
|
41250
|
+
200,
|
|
41251
|
+
await driver.interact({
|
|
41252
|
+
spawnId: typeof body.spawnId === "string" ? body.spawnId : void 0,
|
|
41253
|
+
commandId: body.commandId,
|
|
41254
|
+
input: body.input,
|
|
41255
|
+
timeoutMs: typeof body.timeoutMs === "number" ? body.timeoutMs : void 0
|
|
41256
|
+
})
|
|
41257
|
+
);
|
|
41258
|
+
return;
|
|
41259
|
+
}
|
|
41260
|
+
if (request.method === "POST" && url === "/events/push") {
|
|
41261
|
+
const body = await readBody(request);
|
|
41262
|
+
if (typeof body.topic !== "string" || body.topic.length === 0) {
|
|
41263
|
+
reply(response, 400, { error: "events/push \u9700\u8981 topic" });
|
|
41264
|
+
return;
|
|
41265
|
+
}
|
|
41266
|
+
await driver.pushEvent({
|
|
41267
|
+
spawnId: typeof body.spawnId === "string" ? body.spawnId : void 0,
|
|
41268
|
+
topic: body.topic,
|
|
41269
|
+
payload: body.payload
|
|
41270
|
+
});
|
|
41271
|
+
reply(response, 200, { ok: true });
|
|
41272
|
+
return;
|
|
41273
|
+
}
|
|
41274
|
+
if (request.method === "POST" && url === "/ui-handler") {
|
|
41275
|
+
const body = await readBody(request);
|
|
41276
|
+
if (typeof body.method !== "string" || body.method.length === 0) {
|
|
41277
|
+
reply(response, 400, { error: "ui-handler \u9700\u8981 method \u4E0E result" });
|
|
41278
|
+
return;
|
|
41279
|
+
}
|
|
41280
|
+
try {
|
|
41281
|
+
driver.setUiResponse(body.method, body.result);
|
|
41282
|
+
} catch (error) {
|
|
41283
|
+
reply(response, 400, { error: error instanceof Error ? error.message : String(error) });
|
|
41284
|
+
return;
|
|
41285
|
+
}
|
|
41286
|
+
reply(response, 200, { ok: true });
|
|
41287
|
+
return;
|
|
41288
|
+
}
|
|
41289
|
+
if (request.method === "GET" && url === "/ui-calls") {
|
|
41290
|
+
reply(response, 200, { calls: driver.uiCalls() });
|
|
41291
|
+
return;
|
|
41292
|
+
}
|
|
41293
|
+
if (request.method === "GET" && url === "/runtimes") {
|
|
41294
|
+
reply(response, 200, { runtimes: driver.runtimes() });
|
|
41295
|
+
return;
|
|
41296
|
+
}
|
|
40726
41297
|
reply(response, 404, { error: `\u672A\u77E5\u63A7\u5236\u9762\u8DEF\u5F84\uFF1A${request.method} ${url}` });
|
|
40727
41298
|
}
|
|
40728
41299
|
await new Promise((resolve2) => {
|