@serverkgg/bridge 0.1.2 → 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 (93) 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 +13 -13
  9. package/src/bot/botPanel.ts +4 -4
  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 +52 -30
  30. package/src/cli/validate.ts +2 -0
  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/core/bridgePort.test.ts +6 -6
  36. package/src/core/bridgeUserError.test.ts +4 -4
  37. package/src/core/bridgeValue.test.ts +5 -5
  38. package/src/core/describeDownloadFailure.test.ts +12 -12
  39. package/src/core/describeDownloadFailure.ts +10 -10
  40. package/src/guides/markdown.test.ts +31 -31
  41. package/src/install/installStamp.test.ts +9 -9
  42. package/src/manifest/extension.ts +36 -0
  43. package/src/manifest/index.ts +1 -0
  44. package/src/manifest/manifest.test.ts +208 -90
  45. package/src/manifest/manifest.ts +34 -0
  46. package/src/net/loopback.test.ts +10 -10
  47. package/src/presence/rosterSync.test.ts +7 -7
  48. package/src/probes/a2s.test.ts +5 -5
  49. package/src/probes/minecraftPing.test.ts +17 -17
  50. package/src/probes/raknetPing.test.ts +13 -13
  51. package/src/rcon/rconAccess.test.ts +20 -20
  52. package/src/rcon/rconAccess.ts +13 -13
  53. package/src/rcon/rconClient.test.ts +49 -49
  54. package/src/rcon/rconFrame.test.ts +14 -14
  55. package/src/rcon/rconIds.test.ts +4 -4
  56. package/src/rcon/rconWriter.test.ts +6 -6
  57. package/src/runtime/bridgeActivity.test.ts +15 -15
  58. package/src/runtime/bridgeBackupLease.test.ts +9 -9
  59. package/src/runtime/bridgeConfigReader.test.ts +5 -5
  60. package/src/runtime/bridgeConsoleHandler.test.ts +8 -8
  61. package/src/runtime/bridgeContext.test.ts +5 -5
  62. package/src/runtime/bridgeDriver.test.ts +94 -94
  63. package/src/runtime/bridgeEvents.test.ts +15 -15
  64. package/src/runtime/bridgeFiles.test.ts +54 -54
  65. package/src/runtime/bridgeInstall.test.ts +10 -10
  66. package/src/runtime/bridgeLiveConfig.test.ts +6 -6
  67. package/src/runtime/bridgePending.test.ts +6 -6
  68. package/src/runtime/bridgeRedaction.test.ts +16 -16
  69. package/src/runtime/bridgeRegistry.test.ts +52 -52
  70. package/src/runtime/bridgeRegistry.ts +2 -2
  71. package/src/runtime/bridgeServer.test.ts +31 -31
  72. package/src/runtime/bridgeSetup.test.ts +27 -27
  73. package/src/runtime/bridgeSetup.ts +1 -1
  74. package/src/runtime/bridgeSetupHandlers.test.ts +13 -13
  75. package/src/runtime/bridgeSignal.test.ts +7 -7
  76. package/src/runtime/bridgeSupervisor.test.ts +42 -42
  77. package/src/runtime/serve.ts +4 -4
  78. package/src/steam/avatars.test.ts +13 -13
  79. package/src/steam/steamApp.test.ts +8 -8
  80. package/src/steam/steamcmd.test.ts +17 -17
  81. package/src/steam/steamcmd.ts +4 -4
  82. package/src/steam/steamcmdNarrator.test.ts +4 -4
  83. package/src/steam/workshop.test.ts +5 -5
  84. package/src/utils/changedSettingKeys.test.ts +5 -5
  85. package/src/utils/describeExecFailure.test.ts +4 -4
  86. package/src/utils/describeExecFailure.ts +1 -1
  87. package/src/utils/sameSettingValue.test.ts +7 -7
  88. package/src/utils/token.test.ts +7 -7
  89. package/src/wine/protonCommand.test.ts +5 -5
  90. package/src/wine/wineCommand.test.ts +6 -6
  91. package/src/wine/winePrefix.test.ts +6 -6
  92. package/src/wire/activity.test.ts +8 -8
  93. package/src/wire/panel.test.ts +28 -28
@@ -1,11 +1,11 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { GuideOpenTab } from "./blocks";
3
3
  import { parseGuideMarkdown } from "./markdown";
4
4
 
5
5
  const parse = (text: string) => parseGuideMarkdown("guides/test/en.md", text);
6
6
 
7
7
  describe("static blocks", () => {
8
- test("parses the existing block vocabulary", () => {
8
+ it("parses the existing block vocabulary", () => {
9
9
  const { blocks } = parse(
10
10
  [
11
11
  "## Join the game",
@@ -32,7 +32,7 @@ describe("static blocks", () => {
32
32
  ]);
33
33
  });
34
34
 
35
- test("still rejects what it always rejected", () => {
35
+ it("still rejects what it always rejected", () => {
36
36
  expect(() => parse("# Title")).toThrow(/h1 is not supported/);
37
37
  expect(() => parse("| a | b |")).toThrow(/tables are not supported/);
38
38
  expect(() => parse("<div>hi</div>")).toThrow(/raw HTML/);
@@ -41,7 +41,7 @@ describe("static blocks", () => {
41
41
  });
42
42
 
43
43
  describe("variables", () => {
44
- test("parses an inline variable", () => {
44
+ it("parses an inline variable", () => {
45
45
  const { blocks } = parse("Your address is {{server.address}} — paste it in.");
46
46
 
47
47
  expect(blocks[0]).toEqual({
@@ -63,7 +63,7 @@ describe("variables", () => {
63
63
  });
64
64
  });
65
65
 
66
- test("accepts a panel variable", () => {
66
+ it("accepts a panel variable", () => {
67
67
  const { blocks } = parse("The motd is {{panel.MOTD}}.");
68
68
 
69
69
  expect(blocks[0]).toMatchObject({
@@ -76,19 +76,19 @@ describe("variables", () => {
76
76
  });
77
77
  });
78
78
 
79
- test("rejects an unknown key", () => {
79
+ it("rejects an unknown key", () => {
80
80
  expect(() => parse("Your address is {{server.adress}}.")).toThrow(/unknown variable "server.adress"/);
81
81
  });
82
82
 
83
- test("rejects a lowercase panel key", () => {
83
+ it("rejects a lowercase panel key", () => {
84
84
  expect(() => parse("{{panel.motd}} is set.")).toThrow(/unknown variable/);
85
85
  });
86
86
 
87
- test("rejects an unterminated marker", () => {
87
+ it("rejects an unterminated marker", () => {
88
88
  expect(() => parse("Your address is {{server.address.")).toThrow(/unterminated \{\{ marker/);
89
89
  });
90
90
 
91
- test("rejects a variable inside a link target", () => {
91
+ it("rejects a variable inside a link target", () => {
92
92
  expect(() => parse("See [your server](/server/{{server.code}}).")).toThrow(
93
93
  /variables cannot be used inside a link target/,
94
94
  );
@@ -96,7 +96,7 @@ describe("variables", () => {
96
96
  });
97
97
 
98
98
  describe("directives", () => {
99
- test("parses a field", () => {
99
+ it("parses a field", () => {
100
100
  const { blocks } = parse("@[field](server.address)");
101
101
 
102
102
  expect(blocks[0]).toEqual({
@@ -105,11 +105,11 @@ describe("directives", () => {
105
105
  });
106
106
  });
107
107
 
108
- test("rejects a field with an unknown key", () => {
108
+ it("rejects a field with an unknown key", () => {
109
109
  expect(() => parse("@[field](server.nope)")).toThrow(/unknown variable "server.nope"/);
110
110
  });
111
111
 
112
- test("parses a command and collects it", () => {
112
+ it("parses a command and collects it", () => {
113
113
  const result = parse("@[command](whitelist on)");
114
114
 
115
115
  expect(result.blocks[0]).toEqual({
@@ -121,11 +121,11 @@ describe("directives", () => {
121
121
  ]);
122
122
  });
123
123
 
124
- test("rejects an empty command", () => {
124
+ it("rejects an empty command", () => {
125
125
  expect(() => parse("@[command]()")).toThrow(/a command must be a single line/);
126
126
  });
127
127
 
128
- test("parses every open target", () => {
128
+ it("parses every open target", () => {
129
129
  const { blocks } = parse(
130
130
  [
131
131
  "@[open](console)",
@@ -187,27 +187,27 @@ describe("directives", () => {
187
187
  ]);
188
188
  });
189
189
 
190
- test("rejects a panel target without a tab id", () => {
190
+ it("rejects a panel target without a tab id", () => {
191
191
  expect(() => parse("@[open](panel)")).toThrow(/panel target needs a tab id/);
192
192
  });
193
193
 
194
- test("rejects an unknown open target", () => {
194
+ it("rejects an unknown open target", () => {
195
195
  expect(() => parse("@[open](nowhere)")).toThrow(/unknown open target "nowhere"/);
196
196
  });
197
197
 
198
- test("rejects an argument on a target that takes none", () => {
198
+ it("rejects an argument on a target that takes none", () => {
199
199
  expect(() => parse("@[open](setup:sign-in)")).toThrow(/"setup" target does not take an argument/);
200
200
  });
201
201
 
202
- test("rejects a traversing file path", () => {
202
+ it("rejects a traversing file path", () => {
203
203
  expect(() => parse("@[open](files:../../etc/passwd)")).toThrow();
204
204
  });
205
205
 
206
- test("rejects an unknown directive", () => {
206
+ it("rejects an unknown directive", () => {
207
207
  expect(() => parse("@[embed](something)")).toThrow(/unknown directive @\[embed\]/);
208
208
  });
209
209
 
210
- test("keeps the youtube directive working", () => {
210
+ it("keeps the youtube directive working", () => {
211
211
  const { blocks } = parse("@[youtube](dQw4w9WgXcQ)");
212
212
 
213
213
  expect(blocks[0]).toEqual({
@@ -216,7 +216,7 @@ describe("directives", () => {
216
216
  });
217
217
  });
218
218
 
219
- test("does not swallow a directive into the paragraph above it", () => {
219
+ it("does not swallow a directive into the paragraph above it", () => {
220
220
  const { blocks } = parse(
221
221
  [
222
222
  "Copy your address:",
@@ -232,7 +232,7 @@ describe("directives", () => {
232
232
  });
233
233
 
234
234
  describe("conditionals", () => {
235
- test("parses both branches", () => {
235
+ it("parses both branches", () => {
236
236
  const { blocks } = parse(
237
237
  [
238
238
  ":::when server.address",
@@ -279,7 +279,7 @@ describe("conditionals", () => {
279
279
  ]);
280
280
  });
281
281
 
282
- test("allows a missing else branch", () => {
282
+ it("allows a missing else branch", () => {
283
283
  const { blocks } = parse(
284
284
  [
285
285
  ":::when server.address",
@@ -294,7 +294,7 @@ describe("conditionals", () => {
294
294
  });
295
295
  });
296
296
 
297
- test("keeps blocks around a conditional", () => {
297
+ it("keeps blocks around a conditional", () => {
298
298
  const { blocks } = parse(
299
299
  [
300
300
  "## Join the game",
@@ -314,7 +314,7 @@ describe("conditionals", () => {
314
314
  ]);
315
315
  });
316
316
 
317
- test("parses two conditionals in a row", () => {
317
+ it("parses two conditionals in a row", () => {
318
318
  const { blocks } = parse(
319
319
  [
320
320
  ":::when server.address",
@@ -332,7 +332,7 @@ describe("conditionals", () => {
332
332
  ]);
333
333
  });
334
334
 
335
- test("rejects nesting", () => {
335
+ it("rejects nesting", () => {
336
336
  expect(() =>
337
337
  parse(
338
338
  [
@@ -346,7 +346,7 @@ describe("conditionals", () => {
346
346
  ).toThrow(/conditionals cannot be nested/);
347
347
  });
348
348
 
349
- test("rejects an unterminated block", () => {
349
+ it("rejects an unterminated block", () => {
350
350
  expect(() =>
351
351
  parse(
352
352
  [
@@ -357,7 +357,7 @@ describe("conditionals", () => {
357
357
  ).toThrow(/unterminated :::when block/);
358
358
  });
359
359
 
360
- test("rejects an empty when branch", () => {
360
+ it("rejects an empty when branch", () => {
361
361
  expect(() =>
362
362
  parse(
363
363
  [
@@ -370,11 +370,11 @@ describe("conditionals", () => {
370
370
  ).toThrow(/empty :::when branch/);
371
371
  });
372
372
 
373
- test("rejects a stray close", () => {
373
+ it("rejects a stray close", () => {
374
374
  expect(() => parse(":::")).toThrow(/unexpected ::: without a matching :::when/);
375
375
  });
376
376
 
377
- test("rejects an unknown key", () => {
377
+ it("rejects an unknown key", () => {
378
378
  expect(() =>
379
379
  parse(
380
380
  [
@@ -386,7 +386,7 @@ describe("conditionals", () => {
386
386
  ).toThrow(/unknown variable "server.nope"/);
387
387
  });
388
388
 
389
- test("rejects a malformed opener", () => {
389
+ it("rejects a malformed opener", () => {
390
390
  expect(() => parse(":::if server.address")).toThrow(/conditionals open with :::when/);
391
391
  });
392
392
  });
@@ -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 { INSTALL_STAMP_FILE, parseStamp, readStamp, writeStamp } from "./installStamp";
4
4
 
@@ -31,7 +31,7 @@ const testContext = (seed: Record<string, string> = {}) => {
31
31
  };
32
32
 
33
33
  describe("parseStamp", () => {
34
- test("reads a json object", () => {
34
+ it("reads a json object", () => {
35
35
  expect(
36
36
  parseStamp<TestStamp>(
37
37
  JSON.stringify({
@@ -43,7 +43,7 @@ describe("parseStamp", () => {
43
43
  });
44
44
  });
45
45
 
46
- test("returns null for anything that is not a json object", () => {
46
+ it("returns null for anything that is not a json object", () => {
47
47
  expect(parseStamp("")).toBeNull();
48
48
  expect(parseStamp("{")).toBeNull();
49
49
  expect(parseStamp("null")).toBeNull();
@@ -53,13 +53,13 @@ describe("parseStamp", () => {
53
53
  });
54
54
 
55
55
  describe("readStamp", () => {
56
- test("returns null when the stamp file is absent", async () => {
56
+ it("returns null when the stamp file is absent", async () => {
57
57
  const { context } = testContext();
58
58
 
59
59
  expect(await readStamp(context)).toBeNull();
60
60
  });
61
61
 
62
- test("reads the stamp the writer left behind", async () => {
62
+ it("reads the stamp the writer left behind", async () => {
63
63
  const { context } = testContext();
64
64
 
65
65
  await writeStamp<TestStamp>(context, {
@@ -73,7 +73,7 @@ describe("readStamp", () => {
73
73
  });
74
74
  });
75
75
 
76
- test("writes pretty json ending in a newline", async () => {
76
+ it("writes pretty json ending in a newline", async () => {
77
77
  const { context, stored } = testContext();
78
78
 
79
79
  await writeStamp(context, {
@@ -83,7 +83,7 @@ describe("readStamp", () => {
83
83
  expect(stored.get(INSTALL_STAMP_FILE)).toBe('{\n "buildId": "1"\n}\n');
84
84
  });
85
85
 
86
- test("honours a custom stamp path", async () => {
86
+ it("honours a custom stamp path", async () => {
87
87
  const { context, stored } = testContext();
88
88
 
89
89
  await writeStamp(
@@ -100,7 +100,7 @@ describe("readStamp", () => {
100
100
  });
101
101
  });
102
102
 
103
- test("returns null when the read fails after the file was seen", async () => {
103
+ it("returns null when the read fails after the file was seen", async () => {
104
104
  const context = {
105
105
  files: {
106
106
  async exists() {
@@ -115,7 +115,7 @@ describe("readStamp", () => {
115
115
  expect(await readStamp(context)).toBeNull();
116
116
  });
117
117
 
118
- test("returns null when the stamp file is corrupt", async () => {
118
+ it("returns null when the stamp file is corrupt", async () => {
119
119
  const { context } = testContext({
120
120
  [INSTALL_STAMP_FILE]: "not json",
121
121
  });
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+
3
+ export enum ManifestExtensionKind {
4
+ Mods = "mods",
5
+ Plugins = "plugins",
6
+ Addons = "addons",
7
+ Modpacks = "modpacks",
8
+ }
9
+
10
+ export enum ManifestExtensionSource {
11
+ Modrinth = "modrinth",
12
+ CurseForge = "curseforge",
13
+ Hangar = "hangar",
14
+ Thunderstore = "thunderstore",
15
+ }
16
+
17
+ export const EXTENSIONS_LIMIT = Object.values(ManifestExtensionKind).length;
18
+
19
+ export const EXTENSION_SOURCES_LIMIT = Object.values(ManifestExtensionSource).length;
20
+
21
+ export const manifestExtensionSchema = z.object({
22
+ kind: z.enum(ManifestExtensionKind).meta({
23
+ description: "What the customer adds to the game: mods, plugins, add-ons or modpacks.",
24
+ }),
25
+ sources: z.array(z.enum(ManifestExtensionSource)).max(EXTENSION_SOURCES_LIMIT).default([]).meta({
26
+ description:
27
+ "The catalogs the panel installs this kind from. Leave it empty when the customer adds them by hand through the files.",
28
+ }),
29
+ });
30
+
31
+ export type ManifestExtension = z.infer<typeof manifestExtensionSchema>;
32
+
33
+ export const manifestExtensionsSchema = z.array(manifestExtensionSchema).max(EXTENSIONS_LIMIT).default([]).meta({
34
+ description:
35
+ "What a customer can add to this game, and from which catalogs. The public pages claim only what is declared here; declare nothing when the game takes no additions.",
36
+ });
@@ -1,6 +1,7 @@
1
1
  export * from "../utils";
2
2
  export * from "./assets";
3
3
  export * from "./category";
4
+ export * from "./extension";
4
5
  export * from "./guide";
5
6
  export * from "./image";
6
7
  export * from "./jsonSchema";