@serverkgg/bridge 0.0.9 → 0.0.11
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/package.json +1 -1
- package/src/cli/validate.test.ts +116 -1
- package/src/cli/validate.ts +50 -3
- package/src/context/bridgeContext.ts +8 -1
- package/src/core/bridgeKind.ts +1 -0
- package/src/core/bridgeProbeError.ts +16 -0
- package/src/core/bridgeSetup.ts +20 -0
- package/src/core/bridgeValue.test.ts +29 -0
- package/src/core/bridgeValue.ts +12 -0
- package/src/core/index.ts +2 -0
- package/src/guides/blocks.ts +8 -0
- package/src/guides/markdown.test.ts +18 -0
- package/src/guides/markdown.ts +7 -1
- package/src/manifest/guide.ts +1 -0
- package/src/manifest/manifest.test.ts +49 -2
- package/src/manifest/presence.ts +9 -1
- package/src/modules/bridge.ts +20 -0
- package/src/modules/bridgeDriver.ts +2 -0
- package/src/modules/bridgeModule.ts +7 -0
- package/src/panel/bridgeControl.ts +1 -0
- package/src/panel/bridgeDetail.ts +6 -5
- package/src/panel/bridgePanel.ts +2 -0
- package/src/probes/a2s.test.ts +71 -0
- package/src/probes/a2s.ts +38 -11
- package/src/protocol/bridgeFrame.ts +5 -0
- package/src/protocol/bridgeLimits.ts +10 -0
- package/src/protocol/bridgeManifest.ts +2 -0
- package/src/protocol/bridgeSetup.ts +97 -0
- package/src/protocol/index.ts +1 -0
- package/src/runtime/bridgeConfigReader.ts +12 -8
- package/src/runtime/bridgeContext.ts +28 -2
- package/src/runtime/bridgeDriver.test.ts +512 -2
- package/src/runtime/bridgeDriver.ts +219 -1
- package/src/runtime/bridgeEvents.test.ts +96 -0
- package/src/runtime/bridgeEvents.ts +4 -1
- package/src/runtime/bridgeRegistry.test.ts +38 -1
- package/src/runtime/bridgeRegistry.ts +14 -1
- package/src/runtime/bridgeSecrets.test.ts +121 -0
- package/src/runtime/bridgeSecrets.ts +43 -0
- package/src/runtime/bridgeServer.test.ts +262 -2
- package/src/runtime/bridgeServer.ts +17 -0
- package/src/runtime/bridgeSetup.test.ts +575 -0
- package/src/runtime/bridgeSetup.ts +303 -0
- package/src/runtime/bridgeSetupHandlers.test.ts +303 -0
- package/src/runtime/bridgeSetupHandlers.ts +71 -0
- package/src/runtime/bridgeSignal.test.ts +114 -0
- package/src/runtime/bridgeSignal.ts +31 -0
- package/src/runtime/bridgeSupervisor.test.ts +111 -0
- package/src/runtime/bridgeSupervisor.ts +37 -5
- package/src/runtime/serve.ts +19 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/stripAnsi.ts +12 -0
- package/src/wire/panel.test.ts +155 -0
- package/src/wire/panel.ts +43 -0
|
@@ -2,9 +2,25 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
|
2
2
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
BridgeDesired,
|
|
7
|
+
BridgeFailureCode,
|
|
8
|
+
BridgeFailureError,
|
|
9
|
+
BridgeRuntime,
|
|
10
|
+
BridgeSetupPromptKind,
|
|
11
|
+
BridgeSetupStepState,
|
|
12
|
+
BridgeUserError,
|
|
13
|
+
} from "../core";
|
|
14
|
+
import {
|
|
15
|
+
BridgeMethod,
|
|
16
|
+
type BridgePendingResult,
|
|
17
|
+
type BridgeResponse,
|
|
18
|
+
type BridgeSetupResult,
|
|
19
|
+
type BridgeSetupRuntime,
|
|
20
|
+
type BridgeValues,
|
|
21
|
+
} from "../protocol";
|
|
7
22
|
import { createServer, type ServerOptions } from "./bridgeServer";
|
|
23
|
+
import { failedSetup, unsupportedSetup } from "./bridgeSetup";
|
|
8
24
|
|
|
9
25
|
const TOKEN = "test-token";
|
|
10
26
|
|
|
@@ -25,7 +41,9 @@ const baseOptions = (socket: string): ServerOptions => ({
|
|
|
25
41
|
outOfMemory: false,
|
|
26
42
|
restarts: 0,
|
|
27
43
|
installError: null,
|
|
44
|
+
installErrorText: null,
|
|
28
45
|
installHold: null,
|
|
46
|
+
setup: null,
|
|
29
47
|
}),
|
|
30
48
|
onManifest: unreachable("manifest"),
|
|
31
49
|
onStart: unreachable("start"),
|
|
@@ -40,6 +58,8 @@ const baseOptions = (socket: string): ServerOptions => ({
|
|
|
40
58
|
onAnnounce: unreachable("announce"),
|
|
41
59
|
onPendingList: unreachable("pendingList"),
|
|
42
60
|
onPendingAdd: unreachable("pendingAdd"),
|
|
61
|
+
onSetupStatus: unreachable("setupStatus"),
|
|
62
|
+
onSetupSubmit: unreachable("setupSubmit"),
|
|
43
63
|
onLog: () => {
|
|
44
64
|
return;
|
|
45
65
|
},
|
|
@@ -264,6 +284,246 @@ describe("pending dispatch", () => {
|
|
|
264
284
|
});
|
|
265
285
|
});
|
|
266
286
|
|
|
287
|
+
describe("setup dispatch", () => {
|
|
288
|
+
let dir = "";
|
|
289
|
+
let socket = "";
|
|
290
|
+
|
|
291
|
+
beforeEach(async () => {
|
|
292
|
+
dir = await mkdtemp(join(tmpdir(), "bridge-server-"));
|
|
293
|
+
socket = join(dir, "bridge.sock");
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
afterEach(async () => {
|
|
297
|
+
await rm(dir, {
|
|
298
|
+
force: true,
|
|
299
|
+
recursive: true,
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const runtime: BridgeSetupRuntime = {
|
|
304
|
+
steps: [
|
|
305
|
+
{
|
|
306
|
+
id: "sign-in",
|
|
307
|
+
state: BridgeSetupStepState.Active,
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
prompt: {
|
|
311
|
+
kind: BridgeSetupPromptKind.Link,
|
|
312
|
+
message: {
|
|
313
|
+
ar: "سجل دخولك",
|
|
314
|
+
en: "sign in with your account",
|
|
315
|
+
},
|
|
316
|
+
url: "https://hytale.com/device",
|
|
317
|
+
code: "ABCD-EFGH",
|
|
318
|
+
expiresAt: null,
|
|
319
|
+
actions: [
|
|
320
|
+
{
|
|
321
|
+
id: "renew",
|
|
322
|
+
label: {
|
|
323
|
+
ar: "كود جديد",
|
|
324
|
+
en: "Get a new code",
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const reported: BridgeSetupResult = {
|
|
332
|
+
supported: true,
|
|
333
|
+
runtime,
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
test("answers setupStatus with what the driver reported", async () => {
|
|
337
|
+
const server = createServer({
|
|
338
|
+
...baseOptions(socket),
|
|
339
|
+
onSetupStatus: () => reported,
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const response = await call(socket, {
|
|
343
|
+
id: 1,
|
|
344
|
+
token: TOKEN,
|
|
345
|
+
method: BridgeMethod.SetupStatus,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
server.stop(true);
|
|
349
|
+
|
|
350
|
+
expect(response).toEqual({
|
|
351
|
+
id: 1,
|
|
352
|
+
ok: true,
|
|
353
|
+
result: reported,
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test("answers setupStatus with the unsupported sentinel when the driver declares no setup", async () => {
|
|
358
|
+
const server = createServer({
|
|
359
|
+
...baseOptions(socket),
|
|
360
|
+
onSetupStatus: () => unsupportedSetup(),
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
const response = await call(socket, {
|
|
364
|
+
id: 2,
|
|
365
|
+
token: TOKEN,
|
|
366
|
+
method: BridgeMethod.SetupStatus,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
server.stop(true);
|
|
370
|
+
|
|
371
|
+
expect(response).toEqual({
|
|
372
|
+
id: 2,
|
|
373
|
+
ok: true,
|
|
374
|
+
result: {
|
|
375
|
+
supported: false,
|
|
376
|
+
runtime: null,
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
test("passes the step, action and args of a setupSubmit to the driver", async () => {
|
|
382
|
+
const received: {
|
|
383
|
+
step: string;
|
|
384
|
+
action: string;
|
|
385
|
+
args: BridgeValues;
|
|
386
|
+
}[] = [];
|
|
387
|
+
|
|
388
|
+
const server = createServer({
|
|
389
|
+
...baseOptions(socket),
|
|
390
|
+
onSetupSubmit: async (step, action, args) => {
|
|
391
|
+
received.push({
|
|
392
|
+
step,
|
|
393
|
+
action,
|
|
394
|
+
args,
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
return reported;
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
const response = await call(socket, {
|
|
402
|
+
id: 3,
|
|
403
|
+
token: TOKEN,
|
|
404
|
+
method: BridgeMethod.SetupSubmit,
|
|
405
|
+
module: "sign-in",
|
|
406
|
+
action: "renew",
|
|
407
|
+
args: {
|
|
408
|
+
force: true,
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
server.stop(true);
|
|
413
|
+
|
|
414
|
+
expect(received).toEqual([
|
|
415
|
+
{
|
|
416
|
+
step: "sign-in",
|
|
417
|
+
action: "renew",
|
|
418
|
+
args: {
|
|
419
|
+
force: true,
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
]);
|
|
423
|
+
expect(response).toEqual({
|
|
424
|
+
id: 3,
|
|
425
|
+
ok: true,
|
|
426
|
+
result: reported,
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
test("refuses a setupSubmit carrying no step id", async () => {
|
|
431
|
+
const server = createServer({
|
|
432
|
+
...baseOptions(socket),
|
|
433
|
+
onSetupSubmit: unreachable("setupSubmit"),
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
const response = await call(socket, {
|
|
437
|
+
id: 4,
|
|
438
|
+
token: TOKEN,
|
|
439
|
+
method: BridgeMethod.SetupSubmit,
|
|
440
|
+
action: "renew",
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
server.stop(true);
|
|
444
|
+
|
|
445
|
+
expect(response).toEqual({
|
|
446
|
+
id: 4,
|
|
447
|
+
ok: false,
|
|
448
|
+
error: "setupSubmit needs a step id",
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
test("answers a rejected setupSubmit with a failed prompt instead of a failed call", async () => {
|
|
453
|
+
const server = createServer({
|
|
454
|
+
...baseOptions(socket),
|
|
455
|
+
onSetupSubmit: async () =>
|
|
456
|
+
failedSetup(runtime, {
|
|
457
|
+
ar: "الكود ما عاد ينفع",
|
|
458
|
+
en: "this code cannot be renewed any more",
|
|
459
|
+
}),
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
const response = await call(socket, {
|
|
463
|
+
id: 5,
|
|
464
|
+
token: TOKEN,
|
|
465
|
+
method: BridgeMethod.SetupSubmit,
|
|
466
|
+
module: "sign-in",
|
|
467
|
+
action: "renew",
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
server.stop(true);
|
|
471
|
+
|
|
472
|
+
expect(response).toEqual({
|
|
473
|
+
id: 5,
|
|
474
|
+
ok: true,
|
|
475
|
+
result: {
|
|
476
|
+
supported: true,
|
|
477
|
+
runtime: {
|
|
478
|
+
steps: runtime.steps,
|
|
479
|
+
prompt: {
|
|
480
|
+
kind: BridgeSetupPromptKind.Failed,
|
|
481
|
+
message: {
|
|
482
|
+
ar: "الكود ما عاد ينفع",
|
|
483
|
+
en: "this code cannot be renewed any more",
|
|
484
|
+
},
|
|
485
|
+
actions: [
|
|
486
|
+
{
|
|
487
|
+
id: "renew",
|
|
488
|
+
label: {
|
|
489
|
+
ar: "كود جديد",
|
|
490
|
+
en: "Get a new code",
|
|
491
|
+
},
|
|
492
|
+
},
|
|
493
|
+
],
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
test("answers setupSubmit with the unsupported sentinel when the driver implements no submit", async () => {
|
|
501
|
+
const server = createServer({
|
|
502
|
+
...baseOptions(socket),
|
|
503
|
+
onSetupSubmit: async () => unsupportedSetup(),
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
const response = await call(socket, {
|
|
507
|
+
id: 6,
|
|
508
|
+
token: TOKEN,
|
|
509
|
+
method: BridgeMethod.SetupSubmit,
|
|
510
|
+
module: "sign-in",
|
|
511
|
+
action: "renew",
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
server.stop(true);
|
|
515
|
+
|
|
516
|
+
expect(response).toEqual({
|
|
517
|
+
id: 6,
|
|
518
|
+
ok: true,
|
|
519
|
+
result: {
|
|
520
|
+
supported: false,
|
|
521
|
+
runtime: null,
|
|
522
|
+
},
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
267
527
|
describe("error serialisation", () => {
|
|
268
528
|
let dir = "";
|
|
269
529
|
let socket = "";
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type BridgeQuiesceResult,
|
|
13
13
|
type BridgeResponse,
|
|
14
14
|
type BridgeSampleResult,
|
|
15
|
+
type BridgeSetupResult,
|
|
15
16
|
type BridgeStatus,
|
|
16
17
|
} from "../protocol";
|
|
17
18
|
import { type BridgeLogger, errorText } from "./bridgeLog";
|
|
@@ -33,6 +34,8 @@ export interface ServerOptions {
|
|
|
33
34
|
onAnnounce: (message: string) => Promise<BridgeAnnounceResult>;
|
|
34
35
|
onPendingList: () => Promise<BridgePendingResult>;
|
|
35
36
|
onPendingAdd: (input: string) => Promise<BridgePendingResult>;
|
|
37
|
+
onSetupStatus: () => BridgeSetupResult;
|
|
38
|
+
onSetupSubmit: (step: string, action: string, args: BridgeValues) => Promise<BridgeSetupResult>;
|
|
36
39
|
onLog: BridgeLogger;
|
|
37
40
|
}
|
|
38
41
|
|
|
@@ -162,6 +165,20 @@ export const createServer = (options: ServerOptions) => {
|
|
|
162
165
|
return await options.onPendingAdd(input);
|
|
163
166
|
}
|
|
164
167
|
|
|
168
|
+
case BridgeMethod.SetupStatus: {
|
|
169
|
+
return options.onSetupStatus();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
case BridgeMethod.SetupSubmit: {
|
|
173
|
+
const step = asText(request.module);
|
|
174
|
+
|
|
175
|
+
if (!step) {
|
|
176
|
+
throw new Error("setupSubmit needs a step id");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return await options.onSetupSubmit(step, String(request.action ?? ""), asArgs(request.args));
|
|
180
|
+
}
|
|
181
|
+
|
|
165
182
|
default: {
|
|
166
183
|
throw new Error(`unknown method "${method}"`);
|
|
167
184
|
}
|