@serverkgg/bridge 0.1.1 → 0.1.3

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.
Files changed (121) hide show
  1. package/package.json +3 -2
  2. package/rules/package.md +60 -0
  3. package/src/blog/articleFrontmatter.test.ts +10 -10
  4. package/src/blog/compile.test.ts +9 -9
  5. package/src/bot/botDeploy.test.ts +16 -16
  6. package/src/bot/botEnvironment.test.ts +8 -8
  7. package/src/bot/botIdentity.test.ts +12 -12
  8. package/src/bot/botPanel.test.ts +41 -11
  9. package/src/bot/botPanel.ts +13 -5
  10. package/src/bot/botState.test.ts +3 -3
  11. package/src/bot/botTerminal.test.ts +5 -5
  12. package/src/bot/botVariables.test.ts +8 -8
  13. package/src/bot/detect/botToken.test.ts +6 -6
  14. package/src/bot/detect/detect.test.ts +21 -21
  15. package/src/bot/detect/detectTable.test.ts +5 -5
  16. package/src/bot/detect/envExample.test.ts +2 -2
  17. package/src/bot/detect/envScan.test.ts +4 -4
  18. package/src/bot/detect/inferBotPlatform.test.ts +4 -4
  19. package/src/bot/detect/keys.test.ts +3 -3
  20. package/src/bot/detect/sensitiveKey.test.ts +5 -5
  21. package/src/bot/detect/serverkJson.test.ts +5 -5
  22. package/src/catalogs/curseforge.test.ts +35 -35
  23. package/src/catalogs/thunderstore.test.ts +9 -9
  24. package/src/cli/detectTable.test.ts +3 -3
  25. package/src/cli/link.test.ts +11 -11
  26. package/src/cli/main.ts +8 -0
  27. package/src/cli/rules.test.ts +198 -0
  28. package/src/cli/rules.ts +188 -0
  29. package/src/cli/validate.test.ts +123 -29
  30. package/src/cli/validate.ts +37 -1
  31. package/src/codecs/ini.test.ts +13 -13
  32. package/src/codecs/javaProperties.test.ts +11 -11
  33. package/src/codecs/sourceCfg.test.ts +14 -14
  34. package/src/codecs/xmlProperties.test.ts +10 -10
  35. package/src/context/bridgeContext.ts +6 -1
  36. package/src/core/bridgeAction.ts +2 -0
  37. package/src/core/bridgeActivity.ts +9 -0
  38. package/src/core/bridgeAvailability.ts +10 -0
  39. package/src/core/bridgePort.test.ts +6 -6
  40. package/src/core/bridgeUserError.test.ts +13 -3
  41. package/src/core/bridgeUserError.ts +6 -2
  42. package/src/core/bridgeValue.test.ts +5 -5
  43. package/src/core/describeDownloadFailure.test.ts +58 -0
  44. package/src/core/describeDownloadFailure.ts +69 -0
  45. package/src/core/index.ts +3 -0
  46. package/src/guides/markdown.test.ts +31 -31
  47. package/src/install/installStamp.test.ts +9 -9
  48. package/src/manifest/extension.ts +36 -0
  49. package/src/manifest/index.ts +1 -0
  50. package/src/manifest/manifest.test.ts +208 -90
  51. package/src/manifest/manifest.ts +34 -0
  52. package/src/modules/bridge.ts +8 -1
  53. package/src/modules/bridgeModule.ts +13 -1
  54. package/src/net/loopback.test.ts +10 -10
  55. package/src/panel/bridgeDetail.ts +2 -1
  56. package/src/presence/rosterSync.test.ts +7 -7
  57. package/src/probes/a2s.test.ts +5 -5
  58. package/src/probes/minecraftPing.test.ts +17 -17
  59. package/src/probes/raknetPing.test.ts +13 -13
  60. package/src/protocol/bridgeActivity.ts +54 -0
  61. package/src/protocol/bridgeEvents.ts +30 -0
  62. package/src/protocol/bridgeFrame.ts +10 -1
  63. package/src/protocol/index.ts +1 -0
  64. package/src/rcon/rconAccess.test.ts +20 -20
  65. package/src/rcon/rconAccess.ts +13 -13
  66. package/src/rcon/rconClient.test.ts +49 -49
  67. package/src/rcon/rconFrame.test.ts +14 -14
  68. package/src/rcon/rconIds.test.ts +4 -4
  69. package/src/rcon/rconWriter.test.ts +6 -6
  70. package/src/runtime/bridgeActions.ts +19 -2
  71. package/src/runtime/bridgeActivity.test.ts +318 -0
  72. package/src/runtime/bridgeActivity.ts +268 -0
  73. package/src/runtime/bridgeBackupLease.test.ts +9 -9
  74. package/src/runtime/bridgeConfigReader.test.ts +5 -5
  75. package/src/runtime/bridgeConsoleHandler.test.ts +8 -8
  76. package/src/runtime/bridgeContext.test.ts +11 -5
  77. package/src/runtime/bridgeContext.ts +8 -1
  78. package/src/runtime/bridgeDriver.test.ts +114 -93
  79. package/src/runtime/bridgeDriver.ts +10 -7
  80. package/src/runtime/bridgeEvents.test.ts +15 -15
  81. package/src/runtime/bridgeFiles.test.ts +54 -54
  82. package/src/runtime/bridgeInstall.test.ts +10 -10
  83. package/src/runtime/bridgeLiveConfig.test.ts +6 -6
  84. package/src/runtime/bridgeLog.ts +10 -0
  85. package/src/runtime/bridgePending.test.ts +6 -6
  86. package/src/runtime/bridgeRedaction.test.ts +16 -16
  87. package/src/runtime/bridgeRefusalError.ts +13 -0
  88. package/src/runtime/bridgeRegistry.test.ts +1077 -34
  89. package/src/runtime/bridgeRegistry.ts +464 -65
  90. package/src/runtime/bridgeScopedContext.ts +55 -0
  91. package/src/runtime/bridgeServer.test.ts +424 -24
  92. package/src/runtime/bridgeServer.ts +125 -35
  93. package/src/runtime/bridgeSetup.test.ts +27 -27
  94. package/src/runtime/bridgeSetup.ts +1 -1
  95. package/src/runtime/bridgeSetupHandlers.test.ts +80 -17
  96. package/src/runtime/bridgeSetupHandlers.ts +45 -10
  97. package/src/runtime/bridgeSignal.test.ts +7 -7
  98. package/src/runtime/bridgeSupervisor.test.ts +42 -42
  99. package/src/runtime/serve.ts +45 -3
  100. package/src/steam/avatars.test.ts +13 -13
  101. package/src/steam/steamApp.test.ts +8 -8
  102. package/src/steam/steamcmd.test.ts +44 -13
  103. package/src/steam/steamcmd.ts +27 -4
  104. package/src/steam/steamcmdNarrator.test.ts +4 -4
  105. package/src/steam/workshop.test.ts +5 -5
  106. package/src/utils/changedSettingKeys.test.ts +65 -0
  107. package/src/utils/changedSettingKeys.ts +6 -0
  108. package/src/utils/describeExecFailure.test.ts +34 -0
  109. package/src/utils/describeExecFailure.ts +9 -0
  110. package/src/utils/index.ts +3 -0
  111. package/src/utils/sameSettingValue.test.ts +35 -0
  112. package/src/utils/sameSettingValue.ts +40 -0
  113. package/src/utils/token.test.ts +7 -7
  114. package/src/wine/protonCommand.test.ts +5 -5
  115. package/src/wine/wineCommand.test.ts +6 -6
  116. package/src/wine/winePrefix.test.ts +6 -6
  117. package/src/wire/activity.test.ts +95 -0
  118. package/src/wire/activity.ts +41 -0
  119. package/src/wire/index.ts +1 -0
  120. package/src/wire/panel.test.ts +91 -25
  121. package/src/wire/panel.ts +11 -0
@@ -1,23 +1,53 @@
1
1
  export enum BridgeEventName {
2
+ AccessGranted = "AccessGranted",
3
+ AccessRevoked = "AccessRevoked",
4
+ BroadcastSent = "BroadcastSent",
5
+ GameInstalled = "GameInstalled",
2
6
  GameModeChanged = "GameModeChanged",
7
+ GameplayChanged = "GameplayChanged",
8
+ InstallFailed = "InstallFailed",
3
9
  MemoryUndersized = "MemoryUndersized",
4
10
  MissingDependency = "MissingDependency",
5
11
  ModCrashed = "ModCrashed",
12
+ ModDisabled = "ModDisabled",
13
+ ModEnabled = "ModEnabled",
14
+ ModInstalled = "ModInstalled",
6
15
  ModLoaded = "ModLoaded",
16
+ ModLoaderInstalled = "ModLoaderInstalled",
17
+ ModLoaderRemoved = "ModLoaderRemoved",
18
+ ModRemoved = "ModRemoved",
19
+ ModpackInstalled = "ModpackInstalled",
20
+ ModpackRemoved = "ModpackRemoved",
21
+ ModpackSelected = "ModpackSelected",
7
22
  PlayerAdvanced = "PlayerAdvanced",
8
23
  PlayerBanned = "PlayerBanned",
24
+ PlayerChanged = "PlayerChanged",
9
25
  PlayerDied = "PlayerDied",
10
26
  PlayerJoined = "PlayerJoined",
11
27
  PlayerKicked = "PlayerKicked",
12
28
  PlayerLeft = "PlayerLeft",
29
+ PlayerUnbanned = "PlayerUnbanned",
13
30
  PortBindFailed = "PortBindFailed",
31
+ SecretRotated = "SecretRotated",
14
32
  ServerCrashed = "ServerCrashed",
15
33
  ServerStarted = "ServerStarted",
16
34
  ServerStopping = "ServerStopping",
17
35
  ServerUpdated = "ServerUpdated",
36
+ SettingsApplied = "SettingsApplied",
37
+ SettingsChanged = "SettingsChanged",
38
+ SetupAction = "SetupAction",
39
+ SetupCompleted = "SetupCompleted",
40
+ SetupRejected = "SetupRejected",
41
+ SignInExpired = "SignInExpired",
18
42
  TickLagging = "TickLagging",
43
+ WorldActivated = "WorldActivated",
44
+ WorldCloned = "WorldCloned",
19
45
  WorldCorrupt = "WorldCorrupt",
46
+ WorldCreated = "WorldCreated",
47
+ WorldDeleted = "WorldDeleted",
48
+ WorldImported = "WorldImported",
20
49
  WorldSaved = "WorldSaved",
50
+ WorldWiped = "WorldWiped",
21
51
  WrongJavaVersion = "WrongJavaVersion",
22
52
  }
23
53
 
@@ -1,4 +1,11 @@
1
- import type { BridgeDesired, BridgeInstallHold, BridgeRuntime, BridgeValues, LocalizedText } from "../core";
1
+ import type {
2
+ BridgeActivity,
3
+ BridgeDesired,
4
+ BridgeInstallHold,
5
+ BridgeRuntime,
6
+ BridgeValues,
7
+ LocalizedText,
8
+ } from "../core";
2
9
  import type { BridgeSetupSummary } from "./bridgeSetup";
3
10
 
4
11
  export const BRIDGE_SOCKET_NAME = "bridge.sock";
@@ -59,6 +66,7 @@ export interface BridgeSuccess {
59
66
  id: number | null;
60
67
  ok: true;
61
68
  result: unknown;
69
+ activity?: BridgeActivity[];
62
70
  }
63
71
 
64
72
  export interface BridgeFailure {
@@ -68,6 +76,7 @@ export interface BridgeFailure {
68
76
  secret?: string;
69
77
  failure?: string;
70
78
  text?: LocalizedText;
79
+ unchanged?: boolean;
71
80
  }
72
81
 
73
82
  export type BridgeResponse = BridgeFailure | BridgeSuccess;
@@ -1,6 +1,7 @@
1
1
  export * from "../core";
2
2
  export * from "../panel";
3
3
  export * from "../terminal";
4
+ export * from "./bridgeActivity";
4
5
  export * from "./bridgeCatalog";
5
6
  export * from "./bridgeConfig";
6
7
  export * from "./bridgeCrash";
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import type { BridgeContext } from "../context";
3
3
  import { BridgeDetailFormat, BridgeDetailTone, BridgeFormTarget, BridgeLayout } from "../panel";
4
4
  import {
@@ -55,7 +55,7 @@ const accessWith = (password: RconAccessPassword | null, rotate?: () => Promise<
55
55
  };
56
56
 
57
57
  describe("rconExposed", () => {
58
- test("only the string true opens remote access", () => {
58
+ it("only the string true opens remote access", () => {
59
59
  expect(
60
60
  rconExposed(
61
61
  stubContext({
@@ -68,7 +68,7 @@ describe("rconExposed", () => {
68
68
  });
69
69
 
70
70
  describe("rconBindHost", () => {
71
- test("an exposed server binds every interface and a closed one stays on loopback", () => {
71
+ it("an exposed server binds every interface and a closed one stays on loopback", () => {
72
72
  expect(
73
73
  rconBindHost(
74
74
  stubContext({
@@ -81,7 +81,7 @@ describe("rconBindHost", () => {
81
81
  });
82
82
 
83
83
  describe("createRconAccess", () => {
84
- test("an exposed server reads as open", async () => {
84
+ it("an exposed server reads as open", async () => {
85
85
  const detail = await accessWith({
86
86
  value: "secret",
87
87
  pending: false,
@@ -94,7 +94,7 @@ describe("createRconAccess", () => {
94
94
 
95
95
  expect(detail?.id).toBe(RCON_ACCESS_MODULE);
96
96
  expect(detail?.badges.map((badge) => badge.label.en)).toEqual([
97
- "Open",
97
+ "On",
98
98
  ]);
99
99
  expect(detail?.badges[0]?.tone).toBe(BridgeDetailTone.Success);
100
100
  expect(detail?.actions).toEqual([
@@ -102,19 +102,19 @@ describe("createRconAccess", () => {
102
102
  ]);
103
103
  });
104
104
 
105
- test("a closed server reads as closed", async () => {
105
+ it("a closed server reads as closed", async () => {
106
106
  const detail = await accessWith({
107
107
  value: "secret",
108
108
  pending: false,
109
109
  }).read(stubContext().context);
110
110
 
111
111
  expect(detail?.badges.map((badge) => badge.label.en)).toEqual([
112
- "Closed",
112
+ "Off",
113
113
  ]);
114
114
  expect(detail?.badges[0]?.tone).toBe(BridgeDetailTone.Neutral);
115
115
  });
116
116
 
117
- test("the port and the password are the two stats", async () => {
117
+ it("the port and the password are the two stats", async () => {
118
118
  const detail = await accessWith({
119
119
  value: "secret",
120
120
  pending: false,
@@ -146,19 +146,19 @@ describe("createRconAccess", () => {
146
146
  ]);
147
147
  });
148
148
 
149
- test("a password waiting for the next restart carries the pending badge", async () => {
149
+ it("a password waiting for the next restart carries the pending badge", async () => {
150
150
  const detail = await accessWith({
151
151
  value: "next",
152
152
  pending: true,
153
153
  }).read(stubContext().context);
154
154
 
155
155
  expect(detail?.badges.map((badge) => badge.label.en)).toEqual([
156
- "Closed",
156
+ "Off",
157
157
  "Applies after restart",
158
158
  ]);
159
159
  });
160
160
 
161
- test("an inactive port leaves the port stat empty instead of failing the read", async () => {
161
+ it("an inactive port leaves the port stat empty instead of failing the read", async () => {
162
162
  const detail = await accessWith({
163
163
  value: "secret",
164
164
  pending: false,
@@ -172,11 +172,11 @@ describe("createRconAccess", () => {
172
172
  expect(detail?.stats.find((stat) => stat.key === "password")?.value).toBe("secret");
173
173
  });
174
174
 
175
- test("a server with no password yet has no detail", async () => {
175
+ it("a server with no password yet has no detail", async () => {
176
176
  expect(await accessWith(null).read(stubContext().context)).toBeNull();
177
177
  });
178
178
 
179
- test("rotating delegates to the driver, logs without the value and answers nothing", async () => {
179
+ it("rotating delegates to the driver, logs without the value and answers nothing", async () => {
180
180
  let rotated = 0;
181
181
 
182
182
  const access = accessWith(
@@ -199,7 +199,7 @@ describe("createRconAccess", () => {
199
199
  ]);
200
200
  });
201
201
 
202
- test("the protocol name names the detail and both stats", async () => {
202
+ it("the protocol name names the detail and both stats", async () => {
203
203
  const detail = await createRconAccess({
204
204
  protocol: {
205
205
  ar: "Telnet",
@@ -232,7 +232,7 @@ describe("createRconAccess", () => {
232
232
  ]);
233
233
  });
234
234
 
235
- test("a tools line joins the security copy", async () => {
235
+ it("a tools line joins the security copy", async () => {
236
236
  const detail = await createRconAccess({
237
237
  tools: {
238
238
  ar: "أدوات مثل RustAdmin.",
@@ -256,7 +256,7 @@ describe("createRconAccess", () => {
256
256
  });
257
257
 
258
258
  describe("rconAccessSections", () => {
259
- test("the form declares the variable the manifest activates the port on", () => {
259
+ it("the form declares the variable the manifest activates the port on", () => {
260
260
  const [form] = rconAccessSections();
261
261
 
262
262
  expect(form?.layout).toBe(BridgeLayout.Form);
@@ -272,7 +272,7 @@ describe("rconAccessSections", () => {
272
272
  ]);
273
273
  });
274
274
 
275
- test("the detail points at the module and offers the rotate action", () => {
275
+ it("the detail points at the module and offers the rotate action", () => {
276
276
  const [, detail] = rconAccessSections();
277
277
 
278
278
  if (detail?.layout !== BridgeLayout.Detail) {
@@ -286,7 +286,7 @@ describe("rconAccessSections", () => {
286
286
  expect(detail.empty).toBeDefined();
287
287
  });
288
288
 
289
- test("the two sections carry different titles so the panel never repeats a heading", () => {
289
+ it("the two sections carry different titles so the panel never repeats a heading", () => {
290
290
  const [form, detail] = rconAccessSections();
291
291
 
292
292
  expect(form?.title).toEqual({
@@ -300,7 +300,7 @@ describe("rconAccessSections", () => {
300
300
  expect(detail?.title).not.toEqual(form?.title);
301
301
  });
302
302
 
303
- test("the detail is visible only while remote access is on", () => {
303
+ it("the detail is visible only while remote access is on", () => {
304
304
  const [, detail] = rconAccessSections();
305
305
 
306
306
  if (detail?.layout !== BridgeLayout.Detail) {
@@ -315,7 +315,7 @@ describe("rconAccessSections", () => {
315
315
  });
316
316
  });
317
317
 
318
- test("a dedicated port opens a port and a shared one only turns access on", () => {
318
+ it("a dedicated port opens a port and a shared one only turns access on", () => {
319
319
  const [dedicated] = rconAccessSections({
320
320
  portKey: RCON_ACCESS_PORT,
321
321
  });
@@ -55,29 +55,29 @@ const ACCESS_DETAIL_TITLE: LocalizedText = {
55
55
  };
56
56
 
57
57
  const ACCESS_DESCRIPTION: LocalizedText = {
58
- ar: "الوصول عن بُعد يخلي أداة خارجية تتحكم بسيرفرك بكلمة المرور هذي. الكلمة تمشي على النت بدون تشفير، فاقفل الوصول لما ما فيه أداة تستخدمه، ولا تعطي الكلمة أحد. لو تسربت غيّرها على طول.",
58
+ ar: "الوصول عن بُعد يتيح لأداة خارجية التحكم بسيرفرك بكلمة المرور هذه. تنتقل كلمة المرور عبر الإنترنت بدون تشفير، فأوقف الوصول عن بُعد عندما لا تستخدمه أي أداة، ولا تشارك كلمة المرور مع أحد. وإذا تسربت، غيّرها فورًا.",
59
59
  en: "Remote access lets an external tool control your server with this password. The password crosses the internet in the clear, so turn remote access off when no tool is using it, and never share the password. Rotate it the moment it leaks.",
60
60
  };
61
61
 
62
62
  const OPEN_BADGE: BridgeDetailBadge = {
63
63
  label: {
64
- ar: "مفتوح",
65
- en: "Open",
64
+ ar: "مفعّل",
65
+ en: "On",
66
66
  },
67
67
  tone: BridgeDetailTone.Success,
68
68
  };
69
69
 
70
70
  const CLOSED_BADGE: BridgeDetailBadge = {
71
71
  label: {
72
- ar: "مقفول",
73
- en: "Closed",
72
+ ar: "موقوف",
73
+ en: "Off",
74
74
  },
75
75
  tone: BridgeDetailTone.Neutral,
76
76
  };
77
77
 
78
78
  const PENDING_BADGE: BridgeDetailBadge = {
79
79
  label: {
80
- ar: "يطبّق بعد إعادة التشغيل",
80
+ ar: "يُطبّق بعد الريستارت",
81
81
  en: "Applies after restart",
82
82
  },
83
83
  tone: BridgeDetailTone.Warning,
@@ -213,7 +213,7 @@ export const rconAccessSections = (options: RconAccessSectionsOptions = {}): Bri
213
213
  reinstall: false,
214
214
  confirm: BridgeConfirm.Normal,
215
215
  confirmText: {
216
- ar: "نعيد تشغيل سيرفرك عشان يشتغل التغيير.",
216
+ ar: "يتم ريستارت سيرفرك ليُطبّق التغيير.",
217
217
  en: "We restart your server so the change takes effect.",
218
218
  },
219
219
  fields: [
@@ -223,16 +223,16 @@ export const rconAccessSections = (options: RconAccessSectionsOptions = {}): Bri
223
223
  label: ACCESS_TITLE,
224
224
  help: dedicated
225
225
  ? {
226
- ar: `يفتح منفذ ${protocol.ar} عشان تتحكم بسيرفرك من أداة خارجية. المنفذ يطلع مع بقية عناوين سيرفرك بعد ما يرجع يشتغل.`,
226
+ ar: `يفتح منفذ ${protocol.ar} لتتحكم بسيرفرك من أداة خارجية. يظهر المنفذ مع بقية عناوين سيرفرك بعد عودته للتشغيل.`,
227
227
  en: `Opens the ${protocol.en} port so an external tool can control your server. The port appears with your server's other addresses once it is back up.`,
228
228
  }
229
229
  : {
230
- ar: `يشغّل الوصول عن بُعد عشان تتحكم بسيرفرك من أداة خارجية على نفس عنوان اللعبة ومنفذها.`,
230
+ ar: `يفعّل الوصول عن بُعد لتتحكم بسيرفرك من أداة خارجية عبر عنوان اللعبة ومنفذها نفسيهما.`,
231
231
  en: `Turns remote access on so an external tool can control your server over the same address and port as the game.`,
232
232
  },
233
233
  warning: {
234
- ar: "كلمة المرور تمشي على النت بدون تشفير. اقفل الوصول لما ما تستخدمه.",
235
- en: "The password crosses the internet in the clear. Turn it off when you are not using it.",
234
+ ar: "تنتقل كلمة المرور عبر الإنترنت بدون تشفير. أوقف الوصول عن بُعد عندما لا تستخدمه.",
235
+ en: "The password crosses the internet in the clear. Turn it off when you're not using it.",
236
236
  },
237
237
  },
238
238
  ],
@@ -251,13 +251,13 @@ export const rconAccessSections = (options: RconAccessSectionsOptions = {}): Bri
251
251
  },
252
252
  confirm: BridgeConfirm.Strong,
253
253
  confirmText: {
254
- ar: "كل أداة خارجية عندك بتوقف لين تحط الكلمة الجديدة فيها.",
254
+ ar: "ستتوقف كل أداة خارجية تستخدمها حتى تضيف إليها كلمة المرور الجديدة.",
255
255
  en: "Every external tool you use stops working until you paste the new password into it.",
256
256
  },
257
257
  },
258
258
  ],
259
259
  empty: {
260
- ar: "شغّل سيرفرك مرة عشان تتولد كلمة المرور.",
260
+ ar: "شغّل سيرفرك مرة واحدة لتوليد كلمة المرور.",
261
261
  en: "Start your server once to generate the password.",
262
262
  },
263
263
  visibleWhen: {