@serverkgg/bridge 0.0.21 → 0.1.2
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 +3 -1
- package/src/bot/botDeploy.test.ts +363 -0
- package/src/bot/botDeploy.ts +136 -0
- package/src/bot/botEnvironment.test.ts +189 -0
- package/src/bot/botEnvironment.ts +141 -0
- package/src/bot/botIdentity.test.ts +251 -0
- package/src/bot/botIdentity.ts +140 -0
- package/src/bot/botPanel.test.ts +246 -0
- package/src/bot/botPanel.ts +129 -0
- package/src/bot/botState.test.ts +45 -0
- package/src/bot/botState.ts +54 -0
- package/src/bot/botTerminal.test.ts +79 -0
- package/src/bot/botTerminal.ts +62 -0
- package/src/bot/botVariables.test.ts +193 -0
- package/src/bot/botVariables.ts +73 -0
- package/src/bot/detect/botFramework.ts +23 -0
- package/src/bot/detect/botFrameworks.ts +198 -0
- package/src/bot/detect/botInspectWarning.ts +15 -0
- package/src/bot/detect/botPackageManager.ts +6 -0
- package/src/bot/detect/botPlatform.ts +10 -0
- package/src/bot/detect/botRuntime.ts +15 -0
- package/src/bot/detect/botToken.test.ts +71 -0
- package/src/bot/detect/botToken.ts +126 -0
- package/src/bot/detect/detect.test.ts +543 -0
- package/src/bot/detect/detect.ts +842 -0
- package/src/bot/detect/detectResult.ts +40 -0
- package/src/bot/detect/detectTable.test.ts +72 -0
- package/src/bot/detect/detectTable.ts +166 -0
- package/src/bot/detect/envExample.test.ts +29 -0
- package/src/bot/detect/envExample.ts +48 -0
- package/src/bot/detect/envKey.ts +7 -0
- package/src/bot/detect/envScan.test.ts +39 -0
- package/src/bot/detect/envScan.ts +87 -0
- package/src/bot/detect/index.ts +17 -0
- package/src/bot/detect/inferBotPlatform.test.ts +60 -0
- package/src/bot/detect/inferBotPlatform.ts +28 -0
- package/src/bot/detect/keys.test.ts +28 -0
- package/src/bot/detect/keys.ts +64 -0
- package/src/bot/detect/sensitiveKey.test.ts +91 -0
- package/src/bot/detect/sensitiveKey.ts +44 -0
- package/src/bot/detect/serverkJson.test.ts +88 -0
- package/src/bot/detect/serverkJson.ts +174 -0
- package/src/bot/index.ts +8 -0
- package/src/cli/detectTable.test.ts +66 -0
- package/src/cli/detectTable.ts +43 -0
- package/src/cli/main.ts +12 -4
- package/src/cli/renderedFile.ts +35 -0
- package/src/cli/schema.ts +7 -26
- package/src/cli/validate.test.ts +283 -3
- package/src/cli/validate.ts +105 -7
- package/src/context/bridgeContext.ts +17 -1
- package/src/core/bridgeAction.ts +2 -0
- package/src/core/bridgeActivity.ts +9 -0
- package/src/core/bridgeAvailability.ts +10 -0
- package/src/core/bridgePort.test.ts +45 -0
- package/src/core/bridgePort.ts +26 -0
- package/src/core/bridgeUserError.test.ts +10 -0
- package/src/core/bridgeUserError.ts +6 -2
- package/src/core/describeDownloadFailure.test.ts +58 -0
- package/src/core/describeDownloadFailure.ts +69 -0
- package/src/core/index.ts +3 -0
- package/src/guides/compile.ts +2 -2
- package/src/manifest/index.ts +1 -0
- package/src/manifest/kind.ts +5 -0
- package/src/manifest/manifest.test.ts +630 -3
- package/src/manifest/manifest.ts +391 -87
- package/src/manifest/runtime.ts +2 -2
- package/src/manifest/source.ts +4 -4
- package/src/modules/bridge.ts +8 -1
- package/src/modules/bridgeLifecycleSubject.ts +8 -0
- package/src/modules/bridgeModule.ts +19 -1
- package/src/modules/bridgeStopSignal.ts +13 -0
- package/src/modules/index.ts +2 -0
- package/src/panel/bridgeDetail.ts +4 -1
- package/src/protocol/bridgeActivity.ts +54 -0
- package/src/protocol/bridgeConfig.ts +2 -0
- package/src/protocol/bridgeEvents.ts +30 -0
- package/src/protocol/bridgeFrame.ts +10 -1
- package/src/protocol/index.ts +1 -0
- package/src/runtime/bridgeActions.ts +19 -2
- package/src/runtime/bridgeActivity.test.ts +318 -0
- package/src/runtime/bridgeActivity.ts +268 -0
- package/src/runtime/bridgeConfigReader.test.ts +80 -0
- package/src/runtime/bridgeConfigReader.ts +20 -0
- package/src/runtime/bridgeContext.test.ts +247 -0
- package/src/runtime/bridgeContext.ts +43 -10
- package/src/runtime/bridgeDriver.test.ts +153 -1
- package/src/runtime/bridgeDriver.ts +64 -8
- package/src/runtime/bridgeFiles.test.ts +62 -0
- package/src/runtime/bridgeFiles.ts +12 -2
- package/src/runtime/bridgeLiveConfig.ts +18 -0
- package/src/runtime/bridgeLog.ts +10 -0
- package/src/runtime/bridgeRedaction.test.ts +410 -0
- package/src/runtime/bridgeRedaction.ts +214 -0
- package/src/runtime/bridgeRefusalError.ts +13 -0
- package/src/runtime/bridgeRegistry.test.ts +1056 -10
- package/src/runtime/bridgeRegistry.ts +464 -50
- package/src/runtime/bridgeScopedContext.ts +55 -0
- package/src/runtime/bridgeServer.test.ts +534 -4
- package/src/runtime/bridgeServer.ts +145 -38
- package/src/runtime/bridgeSetupHandlers.test.ts +156 -5
- package/src/runtime/bridgeSetupHandlers.ts +59 -14
- package/src/runtime/bridgeSupervisor.test.ts +670 -2
- package/src/runtime/bridgeSupervisor.ts +219 -67
- package/src/runtime/serve.ts +87 -11
- package/src/steam/steamcmd.test.ts +32 -1
- package/src/steam/steamcmd.ts +27 -4
- package/src/utils/changedSettingKeys.test.ts +65 -0
- package/src/utils/changedSettingKeys.ts +6 -0
- package/src/utils/describeExecFailure.test.ts +34 -0
- package/src/utils/describeExecFailure.ts +9 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/sameSettingValue.test.ts +35 -0
- package/src/utils/sameSettingValue.ts +40 -0
- package/src/wire/activity.test.ts +95 -0
- package/src/wire/activity.ts +41 -0
- package/src/wire/index.ts +1 -0
- package/src/wire/panel.test.ts +67 -1
- package/src/wire/panel.ts +11 -0
|
@@ -3,6 +3,7 @@ import { mkdtemp, rm } from "node:fs/promises";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import {
|
|
6
|
+
type BridgeActivity,
|
|
6
7
|
BridgeDesired,
|
|
7
8
|
BridgeFailureCode,
|
|
8
9
|
BridgeFailureError,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
BridgeUserError,
|
|
13
14
|
} from "../core";
|
|
14
15
|
import {
|
|
16
|
+
BridgeEventName,
|
|
15
17
|
BridgeMethod,
|
|
16
18
|
type BridgePendingResult,
|
|
17
19
|
type BridgeResponse,
|
|
@@ -19,6 +21,7 @@ import {
|
|
|
19
21
|
type BridgeSetupRuntime,
|
|
20
22
|
type BridgeValues,
|
|
21
23
|
} from "../protocol";
|
|
24
|
+
import { BridgeRefusalError } from "./bridgeRefusalError";
|
|
22
25
|
import { createServer, type ServerOptions } from "./bridgeServer";
|
|
23
26
|
import { failedSetup, unsupportedSetup } from "./bridgeSetup";
|
|
24
27
|
|
|
@@ -61,11 +64,41 @@ const baseOptions = (socket: string): ServerOptions => ({
|
|
|
61
64
|
onPendingAdd: unreachable("pendingAdd"),
|
|
62
65
|
onSetupStatus: unreachable("setupStatus"),
|
|
63
66
|
onSetupSubmit: unreachable("setupSubmit"),
|
|
67
|
+
onUndelivered: unreachable("undelivered"),
|
|
64
68
|
onLog: () => {
|
|
65
69
|
return;
|
|
66
70
|
},
|
|
67
71
|
});
|
|
68
72
|
|
|
73
|
+
const abandon = async (socket: string, frame: Record<string, unknown>) => {
|
|
74
|
+
await new Promise<void>((resolve, reject) => {
|
|
75
|
+
void Bun.connect({
|
|
76
|
+
unix: socket,
|
|
77
|
+
socket: {
|
|
78
|
+
open(connection) {
|
|
79
|
+
connection.write(`${JSON.stringify(frame)}\n`);
|
|
80
|
+
connection.end();
|
|
81
|
+
},
|
|
82
|
+
close() {
|
|
83
|
+
resolve();
|
|
84
|
+
},
|
|
85
|
+
data() {
|
|
86
|
+
return;
|
|
87
|
+
},
|
|
88
|
+
error(_connection, error) {
|
|
89
|
+
reject(error);
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
}).catch(reject);
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const until = async (check: () => boolean) => {
|
|
97
|
+
for (let attempt = 0; attempt < 100 && !check(); attempt++) {
|
|
98
|
+
await Bun.sleep(10);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
69
102
|
const call = async (socket: string, frame: Record<string, unknown>): Promise<BridgeResponse> => {
|
|
70
103
|
return await new Promise<BridgeResponse>((resolve, reject) => {
|
|
71
104
|
void Bun.connect<{
|
|
@@ -395,7 +428,10 @@ describe("setup dispatch", () => {
|
|
|
395
428
|
args,
|
|
396
429
|
});
|
|
397
430
|
|
|
398
|
-
return
|
|
431
|
+
return {
|
|
432
|
+
result: reported,
|
|
433
|
+
activity: [],
|
|
434
|
+
};
|
|
399
435
|
},
|
|
400
436
|
});
|
|
401
437
|
|
|
@@ -425,6 +461,7 @@ describe("setup dispatch", () => {
|
|
|
425
461
|
id: 3,
|
|
426
462
|
ok: true,
|
|
427
463
|
result: reported,
|
|
464
|
+
activity: [],
|
|
428
465
|
});
|
|
429
466
|
});
|
|
430
467
|
|
|
@@ -453,11 +490,13 @@ describe("setup dispatch", () => {
|
|
|
453
490
|
test("answers a rejected setupSubmit with a failed prompt instead of a failed call", async () => {
|
|
454
491
|
const server = createServer({
|
|
455
492
|
...baseOptions(socket),
|
|
456
|
-
onSetupSubmit: async () =>
|
|
457
|
-
failedSetup(runtime, {
|
|
493
|
+
onSetupSubmit: async () => ({
|
|
494
|
+
result: failedSetup(runtime, {
|
|
458
495
|
ar: "الكود ما عاد ينفع",
|
|
459
496
|
en: "this code cannot be renewed any more",
|
|
460
497
|
}),
|
|
498
|
+
activity: [],
|
|
499
|
+
}),
|
|
461
500
|
});
|
|
462
501
|
|
|
463
502
|
const response = await call(socket, {
|
|
@@ -495,13 +534,17 @@ describe("setup dispatch", () => {
|
|
|
495
534
|
},
|
|
496
535
|
},
|
|
497
536
|
},
|
|
537
|
+
activity: [],
|
|
498
538
|
});
|
|
499
539
|
});
|
|
500
540
|
|
|
501
541
|
test("answers setupSubmit with the unsupported sentinel when the driver implements no submit", async () => {
|
|
502
542
|
const server = createServer({
|
|
503
543
|
...baseOptions(socket),
|
|
504
|
-
onSetupSubmit: async () =>
|
|
544
|
+
onSetupSubmit: async () => ({
|
|
545
|
+
result: unsupportedSetup(),
|
|
546
|
+
activity: [],
|
|
547
|
+
}),
|
|
505
548
|
});
|
|
506
549
|
|
|
507
550
|
const response = await call(socket, {
|
|
@@ -521,6 +564,7 @@ describe("setup dispatch", () => {
|
|
|
521
564
|
supported: false,
|
|
522
565
|
runtime: null,
|
|
523
566
|
},
|
|
567
|
+
activity: [],
|
|
524
568
|
});
|
|
525
569
|
});
|
|
526
570
|
});
|
|
@@ -589,6 +633,35 @@ describe("error serialisation", () => {
|
|
|
589
633
|
});
|
|
590
634
|
});
|
|
591
635
|
|
|
636
|
+
test("marks a runtime refusal unchanged and carries its text", async () => {
|
|
637
|
+
expect(
|
|
638
|
+
await thrown(
|
|
639
|
+
new BridgeRefusalError('module "worlds" cannot run "delete" right now', {
|
|
640
|
+
ar: "ما تقدر تحذف العالم الشغّال",
|
|
641
|
+
en: "You cannot delete the active world",
|
|
642
|
+
}),
|
|
643
|
+
),
|
|
644
|
+
).toEqual({
|
|
645
|
+
id: 1,
|
|
646
|
+
ok: false,
|
|
647
|
+
error: 'module "worlds" cannot run "delete" right now',
|
|
648
|
+
unchanged: true,
|
|
649
|
+
text: {
|
|
650
|
+
ar: "ما تقدر تحذف العالم الشغّال",
|
|
651
|
+
en: "You cannot delete the active world",
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
test("marks a runtime refusal without text unchanged and sends no text", async () => {
|
|
657
|
+
expect(await thrown(new BridgeRefusalError('no module named "worlds"'))).toEqual({
|
|
658
|
+
id: 1,
|
|
659
|
+
ok: false,
|
|
660
|
+
error: 'no module named "worlds"',
|
|
661
|
+
unchanged: true,
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
|
|
592
665
|
test("carries the message alone for an ordinary error", async () => {
|
|
593
666
|
expect(await thrown(new Error("the file could not be read"))).toEqual({
|
|
594
667
|
id: 1,
|
|
@@ -654,3 +727,460 @@ describe("backup ownership dispatch", () => {
|
|
|
654
727
|
}
|
|
655
728
|
});
|
|
656
729
|
});
|
|
730
|
+
|
|
731
|
+
describe("error replies", () => {
|
|
732
|
+
const SECRET = "tok-1234567890-secret";
|
|
733
|
+
|
|
734
|
+
let dir = "";
|
|
735
|
+
let socket = "";
|
|
736
|
+
|
|
737
|
+
beforeEach(async () => {
|
|
738
|
+
dir = await mkdtemp(join(tmpdir(), "bridge-server-"));
|
|
739
|
+
socket = join(dir, "bridge.sock");
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
afterEach(async () => {
|
|
743
|
+
await rm(dir, {
|
|
744
|
+
force: true,
|
|
745
|
+
recursive: true,
|
|
746
|
+
});
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
test("hide a secret value from the error and the customer text", async () => {
|
|
750
|
+
const server = createServer({
|
|
751
|
+
...baseOptions(socket),
|
|
752
|
+
redact: (value) => value.split(SECRET).join("••••"),
|
|
753
|
+
onInvoke: async () => {
|
|
754
|
+
throw new BridgeUserError({
|
|
755
|
+
ar: `رفض ${SECRET}`,
|
|
756
|
+
en: `refused ${SECRET}`,
|
|
757
|
+
});
|
|
758
|
+
},
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
const response = await call(socket, {
|
|
762
|
+
id: 9,
|
|
763
|
+
token: TOKEN,
|
|
764
|
+
method: BridgeMethod.Invoke,
|
|
765
|
+
module: "botDeploy",
|
|
766
|
+
action: "redeploy",
|
|
767
|
+
args: {},
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
server.stop(true);
|
|
771
|
+
|
|
772
|
+
expect(response).toEqual({
|
|
773
|
+
id: 9,
|
|
774
|
+
ok: false,
|
|
775
|
+
error: "refused ••••",
|
|
776
|
+
text: {
|
|
777
|
+
ar: "رفض ••••",
|
|
778
|
+
en: "refused ••••",
|
|
779
|
+
},
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
describe("failure logging", () => {
|
|
785
|
+
let dir = "";
|
|
786
|
+
let socket = "";
|
|
787
|
+
|
|
788
|
+
beforeEach(async () => {
|
|
789
|
+
dir = await mkdtemp(join(tmpdir(), "bridge-server-"));
|
|
790
|
+
socket = join(dir, "bridge.sock");
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
afterEach(async () => {
|
|
794
|
+
await rm(dir, {
|
|
795
|
+
force: true,
|
|
796
|
+
recursive: true,
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
const logged = async (error: unknown) => {
|
|
801
|
+
const lines: {
|
|
802
|
+
message: string;
|
|
803
|
+
fields: Record<string, unknown>;
|
|
804
|
+
}[] = [];
|
|
805
|
+
|
|
806
|
+
const server = createServer({
|
|
807
|
+
...baseOptions(socket),
|
|
808
|
+
onLog: (message, fields = {}) => {
|
|
809
|
+
lines.push({
|
|
810
|
+
message,
|
|
811
|
+
fields,
|
|
812
|
+
});
|
|
813
|
+
},
|
|
814
|
+
onInvoke: async () => {
|
|
815
|
+
throw error;
|
|
816
|
+
},
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
await call(socket, {
|
|
820
|
+
id: 3,
|
|
821
|
+
token: TOKEN,
|
|
822
|
+
method: BridgeMethod.Invoke,
|
|
823
|
+
module: "botDeploy",
|
|
824
|
+
action: "redeploy",
|
|
825
|
+
args: {},
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
server.stop(true);
|
|
829
|
+
|
|
830
|
+
return lines;
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
test("logs a refused action as a refusal with its message and no stack", async () => {
|
|
834
|
+
expect(
|
|
835
|
+
await logged(
|
|
836
|
+
new BridgeUserError({
|
|
837
|
+
ar: "فيه نشر شغّال الحين",
|
|
838
|
+
en: "a deploy is already running",
|
|
839
|
+
}),
|
|
840
|
+
),
|
|
841
|
+
).toEqual([
|
|
842
|
+
{
|
|
843
|
+
message: "bridge call refused",
|
|
844
|
+
fields: {
|
|
845
|
+
method: BridgeMethod.Invoke,
|
|
846
|
+
error: "a deploy is already running",
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
]);
|
|
850
|
+
});
|
|
851
|
+
|
|
852
|
+
test("logs an ordinary error as a failure with its stack", async () => {
|
|
853
|
+
const [line] = await logged(new Error("the marker could not be written"));
|
|
854
|
+
|
|
855
|
+
expect(line?.message).toBe("bridge call failed");
|
|
856
|
+
expect(line?.fields.error).toBe("the marker could not be written");
|
|
857
|
+
expect(String(line?.fields.stack)).toContain("the marker could not be written");
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
test("logs a refusal with the cause the driver attached", async () => {
|
|
861
|
+
expect(
|
|
862
|
+
await logged(
|
|
863
|
+
new BridgeUserError(
|
|
864
|
+
{
|
|
865
|
+
ar: "المصدر رفض التنزيل",
|
|
866
|
+
en: "the source refused the download",
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
cause: new Error("cdn.modrinth.com answered 403"),
|
|
870
|
+
},
|
|
871
|
+
),
|
|
872
|
+
),
|
|
873
|
+
).toEqual([
|
|
874
|
+
{
|
|
875
|
+
message: "bridge call refused",
|
|
876
|
+
fields: {
|
|
877
|
+
method: BridgeMethod.Invoke,
|
|
878
|
+
error: "the source refused the download — cdn.modrinth.com answered 403",
|
|
879
|
+
},
|
|
880
|
+
},
|
|
881
|
+
]);
|
|
882
|
+
});
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
describe("activity on the answer frame", () => {
|
|
886
|
+
let dir = "";
|
|
887
|
+
let socket = "";
|
|
888
|
+
|
|
889
|
+
beforeEach(async () => {
|
|
890
|
+
dir = await mkdtemp(join(tmpdir(), "bridge-server-"));
|
|
891
|
+
socket = join(dir, "bridge.sock");
|
|
892
|
+
});
|
|
893
|
+
|
|
894
|
+
afterEach(async () => {
|
|
895
|
+
await rm(dir, {
|
|
896
|
+
force: true,
|
|
897
|
+
recursive: true,
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
const entry: BridgeActivity = {
|
|
902
|
+
name: BridgeEventName.AccessGranted,
|
|
903
|
+
text: {
|
|
904
|
+
ar: "أضفت Steve للقائمة البيضاء",
|
|
905
|
+
en: "Added Steve to the whitelist",
|
|
906
|
+
},
|
|
907
|
+
subject: "Steve",
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
test("carries the entries an invoke reported beside its result", async () => {
|
|
911
|
+
const server = createServer({
|
|
912
|
+
...baseOptions(socket),
|
|
913
|
+
onInvoke: async () => ({
|
|
914
|
+
result: null,
|
|
915
|
+
activity: [
|
|
916
|
+
entry,
|
|
917
|
+
],
|
|
918
|
+
}),
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
const response = await call(socket, {
|
|
922
|
+
id: 11,
|
|
923
|
+
token: TOKEN,
|
|
924
|
+
method: BridgeMethod.Invoke,
|
|
925
|
+
module: "whitelist",
|
|
926
|
+
action: "add",
|
|
927
|
+
args: {
|
|
928
|
+
input: "Steve",
|
|
929
|
+
},
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
server.stop(true);
|
|
933
|
+
|
|
934
|
+
expect(response).toEqual({
|
|
935
|
+
id: 11,
|
|
936
|
+
ok: true,
|
|
937
|
+
result: null,
|
|
938
|
+
activity: [
|
|
939
|
+
entry,
|
|
940
|
+
],
|
|
941
|
+
});
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
test("carries the entries a setup submit reported beside its result", async () => {
|
|
945
|
+
const server = createServer({
|
|
946
|
+
...baseOptions(socket),
|
|
947
|
+
onSetupSubmit: async () => ({
|
|
948
|
+
result: unsupportedSetup(),
|
|
949
|
+
activity: [
|
|
950
|
+
entry,
|
|
951
|
+
],
|
|
952
|
+
}),
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
const response = await call(socket, {
|
|
956
|
+
id: 12,
|
|
957
|
+
token: TOKEN,
|
|
958
|
+
method: BridgeMethod.SetupSubmit,
|
|
959
|
+
module: "sign-in",
|
|
960
|
+
action: "renew",
|
|
961
|
+
});
|
|
962
|
+
|
|
963
|
+
server.stop(true);
|
|
964
|
+
|
|
965
|
+
expect(response).toMatchObject({
|
|
966
|
+
ok: true,
|
|
967
|
+
activity: [
|
|
968
|
+
entry,
|
|
969
|
+
],
|
|
970
|
+
});
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
test("carries an empty list when nothing was reported, so the platform knows the runtime reports", async () => {
|
|
974
|
+
const server = createServer({
|
|
975
|
+
...baseOptions(socket),
|
|
976
|
+
onInvoke: async () => ({
|
|
977
|
+
result: "done",
|
|
978
|
+
activity: [],
|
|
979
|
+
}),
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
const response = await call(socket, {
|
|
983
|
+
id: 13,
|
|
984
|
+
token: TOKEN,
|
|
985
|
+
method: BridgeMethod.Invoke,
|
|
986
|
+
module: "whitelist",
|
|
987
|
+
action: "add",
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
server.stop(true);
|
|
991
|
+
|
|
992
|
+
expect(response).toEqual({
|
|
993
|
+
id: 13,
|
|
994
|
+
ok: true,
|
|
995
|
+
result: "done",
|
|
996
|
+
activity: [],
|
|
997
|
+
});
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
test("leaves the field off the answers of methods that report no activity", async () => {
|
|
1001
|
+
const server = createServer(baseOptions(socket));
|
|
1002
|
+
|
|
1003
|
+
const response = await call(socket, {
|
|
1004
|
+
id: 14,
|
|
1005
|
+
token: TOKEN,
|
|
1006
|
+
method: BridgeMethod.Status,
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
server.stop(true);
|
|
1010
|
+
|
|
1011
|
+
expect(response.ok).toBe(true);
|
|
1012
|
+
expect("activity" in response).toBe(false);
|
|
1013
|
+
});
|
|
1014
|
+
|
|
1015
|
+
const invokeFrame = {
|
|
1016
|
+
id: 21,
|
|
1017
|
+
token: TOKEN,
|
|
1018
|
+
method: BridgeMethod.Invoke,
|
|
1019
|
+
module: "whitelist",
|
|
1020
|
+
action: "add",
|
|
1021
|
+
};
|
|
1022
|
+
|
|
1023
|
+
test("sends the entries to the events ring once when the caller left before the answer", async () => {
|
|
1024
|
+
const ring: BridgeActivity[][] = [];
|
|
1025
|
+
|
|
1026
|
+
let finish: () => void = () => undefined;
|
|
1027
|
+
let started = false;
|
|
1028
|
+
let answered = false;
|
|
1029
|
+
|
|
1030
|
+
const server = createServer({
|
|
1031
|
+
...baseOptions(socket),
|
|
1032
|
+
onInvoke: async () => {
|
|
1033
|
+
started = true;
|
|
1034
|
+
|
|
1035
|
+
await new Promise<void>((resolve) => {
|
|
1036
|
+
finish = resolve;
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
answered = true;
|
|
1040
|
+
|
|
1041
|
+
return {
|
|
1042
|
+
result: null,
|
|
1043
|
+
activity: [
|
|
1044
|
+
entry,
|
|
1045
|
+
],
|
|
1046
|
+
};
|
|
1047
|
+
},
|
|
1048
|
+
onUndelivered: (activity) => {
|
|
1049
|
+
ring.push(activity);
|
|
1050
|
+
},
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
await abandon(socket, invokeFrame);
|
|
1054
|
+
await until(() => started);
|
|
1055
|
+
await Bun.sleep(20);
|
|
1056
|
+
|
|
1057
|
+
finish();
|
|
1058
|
+
|
|
1059
|
+
await until(() => answered && ring.length > 0);
|
|
1060
|
+
await Bun.sleep(20);
|
|
1061
|
+
|
|
1062
|
+
server.stop(true);
|
|
1063
|
+
|
|
1064
|
+
expect(ring).toEqual([
|
|
1065
|
+
[
|
|
1066
|
+
entry,
|
|
1067
|
+
],
|
|
1068
|
+
]);
|
|
1069
|
+
});
|
|
1070
|
+
|
|
1071
|
+
test("sends nothing to the ring when the answer reached the caller", async () => {
|
|
1072
|
+
const ring: BridgeActivity[][] = [];
|
|
1073
|
+
|
|
1074
|
+
const server = createServer({
|
|
1075
|
+
...baseOptions(socket),
|
|
1076
|
+
onInvoke: async () => ({
|
|
1077
|
+
result: null,
|
|
1078
|
+
activity: [
|
|
1079
|
+
entry,
|
|
1080
|
+
],
|
|
1081
|
+
}),
|
|
1082
|
+
onUndelivered: (activity) => {
|
|
1083
|
+
ring.push(activity);
|
|
1084
|
+
},
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
const response = await call(socket, invokeFrame);
|
|
1088
|
+
|
|
1089
|
+
await Bun.sleep(20);
|
|
1090
|
+
|
|
1091
|
+
server.stop(true);
|
|
1092
|
+
|
|
1093
|
+
expect(response).toMatchObject({
|
|
1094
|
+
ok: true,
|
|
1095
|
+
activity: [
|
|
1096
|
+
entry,
|
|
1097
|
+
],
|
|
1098
|
+
});
|
|
1099
|
+
expect(ring).toEqual([]);
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1102
|
+
test("sends the entries to the ring when the answer cannot be written", async () => {
|
|
1103
|
+
const ring: BridgeActivity[][] = [];
|
|
1104
|
+
|
|
1105
|
+
const server = createServer({
|
|
1106
|
+
...baseOptions(socket),
|
|
1107
|
+
onInvoke: async () => ({
|
|
1108
|
+
result: BigInt(1),
|
|
1109
|
+
activity: [
|
|
1110
|
+
entry,
|
|
1111
|
+
],
|
|
1112
|
+
}),
|
|
1113
|
+
onUndelivered: (activity) => {
|
|
1114
|
+
ring.push(activity);
|
|
1115
|
+
},
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
const response = await call(socket, invokeFrame);
|
|
1119
|
+
|
|
1120
|
+
server.stop(true);
|
|
1121
|
+
|
|
1122
|
+
expect(response.ok).toBe(false);
|
|
1123
|
+
expect(ring).toEqual([
|
|
1124
|
+
[
|
|
1125
|
+
entry,
|
|
1126
|
+
],
|
|
1127
|
+
]);
|
|
1128
|
+
});
|
|
1129
|
+
});
|
|
1130
|
+
|
|
1131
|
+
describe("failure frames", () => {
|
|
1132
|
+
let dir = "";
|
|
1133
|
+
let socket = "";
|
|
1134
|
+
|
|
1135
|
+
beforeEach(async () => {
|
|
1136
|
+
dir = await mkdtemp(join(tmpdir(), "bridge-server-"));
|
|
1137
|
+
socket = join(dir, "bridge.sock");
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
afterEach(async () => {
|
|
1141
|
+
await rm(dir, {
|
|
1142
|
+
force: true,
|
|
1143
|
+
recursive: true,
|
|
1144
|
+
});
|
|
1145
|
+
});
|
|
1146
|
+
|
|
1147
|
+
test("carry the cause in the staff error and keep the customer text friendly", async () => {
|
|
1148
|
+
const SECRET = "tok-1234567890-secret";
|
|
1149
|
+
|
|
1150
|
+
const server = createServer({
|
|
1151
|
+
...baseOptions(socket),
|
|
1152
|
+
redact: (value) => value.split(SECRET).join("••••"),
|
|
1153
|
+
onInvoke: async () => {
|
|
1154
|
+
throw new BridgeUserError(
|
|
1155
|
+
{
|
|
1156
|
+
ar: "المصدر رفض التنزيل",
|
|
1157
|
+
en: "the source refused the download",
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
cause: new Error(`cdn.modrinth.com answered 403 for ${SECRET}`),
|
|
1161
|
+
},
|
|
1162
|
+
);
|
|
1163
|
+
},
|
|
1164
|
+
});
|
|
1165
|
+
|
|
1166
|
+
const response = await call(socket, {
|
|
1167
|
+
id: 31,
|
|
1168
|
+
token: TOKEN,
|
|
1169
|
+
method: BridgeMethod.Invoke,
|
|
1170
|
+
module: "mods",
|
|
1171
|
+
action: "install",
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
server.stop(true);
|
|
1175
|
+
|
|
1176
|
+
expect(response).toEqual({
|
|
1177
|
+
id: 31,
|
|
1178
|
+
ok: false,
|
|
1179
|
+
error: "the source refused the download — cdn.modrinth.com answered 403 for ••••",
|
|
1180
|
+
text: {
|
|
1181
|
+
ar: "المصدر رفض التنزيل",
|
|
1182
|
+
en: "the source refused the download",
|
|
1183
|
+
},
|
|
1184
|
+
});
|
|
1185
|
+
});
|
|
1186
|
+
});
|