@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
@@ -23,12 +23,12 @@ export enum BotDeployAction {
23
23
  export const BOT_IDENTITY_REFRESH_SECONDS = 60;
24
24
 
25
25
  const DEPLOY_PENDING: LocalizedText = {
26
- ar: "فيه نشر شغّال الحين. انتظر لين يخلص وجرّب بعدها.",
26
+ ar: "يوجد نشر قيد التنفيذ، عطه لحظة حتى يكتمل وجرب مرة ثانية.",
27
27
  en: "A deploy is already running. Wait for it to finish, then try again.",
28
28
  };
29
29
 
30
30
  const INVALID_DEPLOY: LocalizedText = {
31
- ar: "طلب النشر هذا ناقص أو غلط. جرّب النشر من صفحة البوت.",
31
+ ar: "طلب النشر هذا ناقص أو غير صحيح. جرب النشر من صفحة البوت.",
32
32
  en: "This deploy request is incomplete or malformed. Try deploying from the bot page.",
33
33
  };
34
34
 
@@ -51,8 +51,8 @@ export const createBotPanel = (): BridgeTab => {
51
51
  en: "Your bot",
52
52
  },
53
53
  empty: {
54
- ar: "بنعرف بوتك أول ما يشتغل ويسجّل دخوله.",
55
- en: "We learn who your bot is once it runs and logs in.",
54
+ ar: "نتعرف على بوتك بمجرد تشغيله وتسجيل دخوله.",
55
+ en: "We learn who your bot is once it starts and signs in.",
56
56
  },
57
57
  },
58
58
  ],
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BotDeploymentOutcome, BotDeploymentSource, DEPLOYMENT_STATE_FILE, readDeploymentState } from "./botState";
3
3
 
4
4
  const filesWith = (content: string | null) => {
@@ -13,7 +13,7 @@ const filesWith = (content: string | null) => {
13
13
  };
14
14
 
15
15
  describe("readDeploymentState", () => {
16
- test("reads what the launcher wrote", async () => {
16
+ it("reads what the launcher wrote", async () => {
17
17
  const state = {
18
18
  deployment: "dep_a1b2c3d4",
19
19
  source: BotDeploymentSource.Snapshot,
@@ -29,7 +29,7 @@ describe("readDeploymentState", () => {
29
29
  expect(await readDeploymentState(filesWith(JSON.stringify(state)))).toEqual(state);
30
30
  });
31
31
 
32
- test("answers null for a missing, broken or foreign file", async () => {
32
+ it("answers null for a missing, broken or foreign file", async () => {
33
33
  expect(await readDeploymentState(filesWith(null))).toBeNull();
34
34
  expect(await readDeploymentState(filesWith("{"))).toBeNull();
35
35
  expect(
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BridgeTerminalLevel, type BridgeTerminalRule } from "../terminal";
3
3
  import { bridgeTerminalRuleSchema } from "../wire";
4
4
  import { LAUNCHER_RULES, NODE_RULES, PYTHON_RULES } from "./botTerminal";
@@ -8,7 +8,7 @@ const levelOf = (rules: BridgeTerminalRule[], line: string) => {
8
8
  };
9
9
 
10
10
  describe("the bot terminal rules", () => {
11
- test("colour the launcher's own lines, failures as errors", () => {
11
+ it("colour the launcher's own lines, failures as errors", () => {
12
12
  expect(levelOf(LAUNCHER_RULES, "serverk: install failed: npm ci exited 1")).toBe(BridgeTerminalLevel.Error);
13
13
  expect(levelOf(LAUNCHER_RULES, "serverk: start failed: no bot token yet — open Setup")).toBe(
14
14
  BridgeTerminalLevel.Error,
@@ -17,7 +17,7 @@ describe("the bot terminal rules", () => {
17
17
  expect(levelOf(LAUNCHER_RULES, "Logged in as helper#0001")).toBeNull();
18
18
  });
19
19
 
20
- test("catch node errors, stack frames and warnings", () => {
20
+ it("catch node errors, stack frames and warnings", () => {
21
21
  expect(levelOf(NODE_RULES, "TypeError: Cannot read properties of undefined (reading 'id')")).toBe(
22
22
  BridgeTerminalLevel.Error,
23
23
  );
@@ -31,7 +31,7 @@ describe("the bot terminal rules", () => {
31
31
  expect(levelOf(NODE_RULES, "Ready! Logged in as helper")).toBeNull();
32
32
  });
33
33
 
34
- test("catch python tracebacks, exceptions, log levels and warnings", () => {
34
+ it("catch python tracebacks, exceptions, log levels and warnings", () => {
35
35
  expect(levelOf(PYTHON_RULES, "Traceback (most recent call last):")).toBe(BridgeTerminalLevel.Error);
36
36
  expect(levelOf(PYTHON_RULES, ' File "/home/container/bot.py", line 3, in <module>')).toBe(
37
37
  BridgeTerminalLevel.Error,
@@ -61,7 +61,7 @@ describe("the bot terminal rules", () => {
61
61
  expect(levelOf(PYTHON_RULES, "[2026-09-27 10:00:00] [INFO ] discord.client: logging in")).toBeNull();
62
62
  });
63
63
 
64
- test("cross the wire the way the panel reads them", () => {
64
+ it("cross the wire the way the panel reads them", () => {
65
65
  for (const rule of [
66
66
  ...LAUNCHER_RULES,
67
67
  ...NODE_RULES,
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import {
3
3
  DEFAULT_REPO_BRANCH,
4
4
  DEPLOYMENT_ID_PATTERN,
@@ -34,7 +34,7 @@ const contextWith = (variables: Record<string, string>, secrets: Record<string,
34
34
  };
35
35
 
36
36
  describe("readBotConfig", () => {
37
- test("reads the platform-owned keys, trims them and takes the git token from the secrets", () => {
37
+ it("reads the platform-owned keys, trims them and takes the git token from the secrets", () => {
38
38
  expect(
39
39
  readBotConfig(
40
40
  contextWith(
@@ -69,7 +69,7 @@ describe("readBotConfig", () => {
69
69
  });
70
70
  });
71
71
 
72
- test("answers nothing for empty values, main for the branch and null for an unknown platform", () => {
72
+ it("answers nothing for empty values, main for the branch and null for an unknown platform", () => {
73
73
  expect(
74
74
  readBotConfig(
75
75
  contextWith({
@@ -93,7 +93,7 @@ describe("readBotConfig", () => {
93
93
  });
94
94
 
95
95
  describe("the patterns", () => {
96
- test("pin a ref only to a full sha-1 or sha-256", () => {
96
+ it("pin a ref only to a full sha-1 or sha-256", () => {
97
97
  expect(REPO_REF_PATTERN.test(SHA)).toBe(true);
98
98
  expect(REPO_REF_PATTERN.test("a".repeat(64))).toBe(true);
99
99
  expect(REPO_REF_PATTERN.test(SHA.slice(0, 12))).toBe(false);
@@ -101,7 +101,7 @@ describe("the patterns", () => {
101
101
  expect(REPO_REF_PATTERN.test("main")).toBe(false);
102
102
  });
103
103
 
104
- test("keep deployment and snapshot ids to url-safe words", () => {
104
+ it("keep deployment and snapshot ids to url-safe words", () => {
105
105
  for (const pattern of [
106
106
  DEPLOYMENT_ID_PATTERN,
107
107
  SNAPSHOT_ID_PATTERN,
@@ -114,7 +114,7 @@ describe("the patterns", () => {
114
114
  }
115
115
  });
116
116
 
117
- test("take a root directory only as a plain relative folder path, the shape the api enforces", () => {
117
+ it("take a root directory only as a plain relative folder path, the shape the api enforces", () => {
118
118
  for (const root of [
119
119
  "bot",
120
120
  "apps/bot",
@@ -145,7 +145,7 @@ describe("the patterns", () => {
145
145
  }
146
146
  });
147
147
 
148
- test("accept https repositories and git branch names", () => {
148
+ it("accept https repositories and git branch names", () => {
149
149
  expect(REPO_URL_PATTERN.test("https://github.com/you/bot.git")).toBe(true);
150
150
  expect(REPO_URL_PATTERN.test("https://user:pass@github.com/you/bot")).toBe(false);
151
151
  expect(REPO_URL_PATTERN.test("git@github.com:you/bot.git")).toBe(false);
@@ -153,7 +153,7 @@ describe("the patterns", () => {
153
153
  expect(REPO_BRANCH_PATTERN.test("-rf")).toBe(false);
154
154
  });
155
155
 
156
- test("accept only branch names git check-ref-format accepts", () => {
156
+ it("accept only branch names git check-ref-format accepts", () => {
157
157
  for (const branch of [
158
158
  "main",
159
159
  "release-1.2",
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BotPlatform } from "./botPlatform";
3
3
  import { discordApplicationId, findBotToken, platformOfKey, platformOfToken, telegramBotId } from "./botToken";
4
4
 
@@ -9,14 +9,14 @@ const DISCORD_TOKEN = `${btoa(DISCORD_ID).replaceAll("=", "")}.GxYz12.${"a".repe
9
9
  const TELEGRAM_TOKEN = "7123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw";
10
10
 
11
11
  describe("token shapes", () => {
12
- test("read the ids hidden in each platform's token", () => {
12
+ it("read the ids hidden in each platform's token", () => {
13
13
  expect(telegramBotId(TELEGRAM_TOKEN)).toBe("7123456789");
14
14
  expect(discordApplicationId(` ${DISCORD_TOKEN} `)).toBe(DISCORD_ID);
15
15
  expect(platformOfToken(TELEGRAM_TOKEN)).toBe(BotPlatform.Telegram);
16
16
  expect(platformOfToken(DISCORD_TOKEN)).toBe(BotPlatform.Discord);
17
17
  });
18
18
 
19
- test("do not mistake a JSON web token or a random key for a bot token", () => {
19
+ it("do not mistake a JSON web token or a random key for a bot token", () => {
20
20
  const jwt = `${btoa('{"alg":"HS256"}').replaceAll("=", "")}.eyJzdWIiOiIxIn0.${"b".repeat(43)}`;
21
21
 
22
22
  expect(platformOfToken(jwt)).toBeNull();
@@ -24,7 +24,7 @@ describe("token shapes", () => {
24
24
  expect(platformOfToken("")).toBeNull();
25
25
  });
26
26
 
27
- test("read the platform a key name points at", () => {
27
+ it("read the platform a key name points at", () => {
28
28
  expect(platformOfKey("DISCORD_TOKEN")).toBe(BotPlatform.Discord);
29
29
  expect(platformOfKey("my_telegram_chat")).toBe(BotPlatform.Telegram);
30
30
  expect(platformOfKey("TOKEN")).toBeNull();
@@ -32,7 +32,7 @@ describe("token shapes", () => {
32
32
  });
33
33
 
34
34
  describe("findBotToken", () => {
35
- test("prefers the tutorial names, then any value shaped like the platform's token", () => {
35
+ it("prefers the tutorial names, then any value shaped like the platform's token", () => {
36
36
  expect(
37
37
  findBotToken(BotPlatform.Discord, {
38
38
  variables: {},
@@ -58,7 +58,7 @@ describe("findBotToken", () => {
58
58
  });
59
59
  });
60
60
 
61
- test("ignores a named key whose value is not the platform's token", () => {
61
+ it("ignores a named key whose value is not the platform's token", () => {
62
62
  expect(
63
63
  findBotToken(BotPlatform.Telegram, {
64
64
  variables: {},
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BotFramework } from "./botFramework";
3
3
  import { BotInspectWarning } from "./botInspectWarning";
4
4
  import { BotPackageManager } from "./botPackageManager";
@@ -52,7 +52,7 @@ const TELEGRAM_PYTHON = {
52
52
  };
53
53
 
54
54
  describe("detect on the templates", () => {
55
- test("reads the discord.js template end to end", () => {
55
+ it("reads the discord.js template end to end", () => {
56
56
  expect(
57
57
  project(DISCORD_NODE, [
58
58
  "package-lock.json",
@@ -85,7 +85,7 @@ describe("detect on the templates", () => {
85
85
  } satisfies DetectResult);
86
86
  });
87
87
 
88
- test("reads the python-telegram-bot template end to end", () => {
88
+ it("reads the python-telegram-bot template end to end", () => {
89
89
  expect(project(TELEGRAM_PYTHON)).toEqual({
90
90
  runtime: BotRuntime.Python,
91
91
  package: "bot-python",
@@ -113,7 +113,7 @@ describe("detect on the templates", () => {
113
113
  } satisfies DetectResult);
114
114
  });
115
115
 
116
- test("reads the lockfile a pnpm or yarn project ships", () => {
116
+ it("reads the lockfile a pnpm or yarn project ships", () => {
117
117
  expect(
118
118
  project(DISCORD_NODE, [
119
119
  "pnpm-lock.yaml",
@@ -129,7 +129,7 @@ describe("detect on the templates", () => {
129
129
  ).toBe(BotPackageManager.Yarn);
130
130
  });
131
131
 
132
- test("installs a pyproject project with pip", () => {
132
+ it("installs a pyproject project with pip", () => {
133
133
  const result = project({
134
134
  "pyproject.toml": '[project]\nname = "bot"\ndependencies = [\n "discord.py>=2.4",\n]\n',
135
135
  "bot.py": 'import discord\nimport os\nos.getenv("DISCORD_TOKEN")\n',
@@ -148,7 +148,7 @@ describe("detect on the templates", () => {
148
148
  });
149
149
 
150
150
  describe("detect start commands", () => {
151
- test("follows the launcher's order: start script, main, known files, then the Procfile", () => {
151
+ it("follows the launcher's order: start script, main, known files, then the Procfile", () => {
152
152
  expect(
153
153
  project({
154
154
  "package.json": JSON.stringify({
@@ -181,7 +181,7 @@ describe("detect start commands", () => {
181
181
  });
182
182
  });
183
183
 
184
- test("warns when nothing starts and when node would run TypeScript directly", () => {
184
+ it("warns when nothing starts and when node would run TypeScript directly", () => {
185
185
  expect(
186
186
  project({
187
187
  "package.json": "{}",
@@ -206,7 +206,7 @@ describe("detect start commands", () => {
206
206
  });
207
207
 
208
208
  describe("detect warnings", () => {
209
- test("flags a missing lockfile, loose requirements and a missing manifest", () => {
209
+ it("flags a missing lockfile, loose requirements and a missing manifest", () => {
210
210
  expect(
211
211
  project({
212
212
  "package.json": "{}",
@@ -240,7 +240,7 @@ describe("detect warnings", () => {
240
240
  ]);
241
241
  });
242
242
 
243
- test("flags committed secrets and dependency folders but not the templates for them", () => {
243
+ it("flags committed secrets and dependency folders but not the templates for them", () => {
244
244
  expect(
245
245
  project(DISCORD_NODE, [
246
246
  "package-lock.json",
@@ -258,7 +258,7 @@ describe("detect warnings", () => {
258
258
  ]);
259
259
  });
260
260
 
261
- test("flags two runtimes and picks the one whose framework it found", () => {
261
+ it("flags two runtimes and picks the one whose framework it found", () => {
262
262
  const result = project({
263
263
  ...DISCORD_NODE,
264
264
  "requirements.txt": "requests==2.32.0\n",
@@ -268,7 +268,7 @@ describe("detect warnings", () => {
268
268
  expect(result.warnings).toContain(BotInspectWarning.TwoRuntimes);
269
269
  });
270
270
 
271
- test("flags two platforms and leaves the choice to the customer", () => {
271
+ it("flags two platforms and leaves the choice to the customer", () => {
272
272
  const result = project({
273
273
  "package.json": JSON.stringify({
274
274
  dependencies: {
@@ -284,7 +284,7 @@ describe("detect warnings", () => {
284
284
  expect(result.warnings).toContain(BotInspectWarning.TwoPlatforms);
285
285
  });
286
286
 
287
- test("drops keys the platform owns and warns, but keeps quiet about keys the runtime gives anyway", () => {
287
+ it("drops keys the platform owns and warns, but keeps quiet about keys the runtime gives anyway", () => {
288
288
  const result = project({
289
289
  ...DISCORD_NODE,
290
290
  "index.js": "process.env.REPO_URL; process.env.HOME; process.env.SERVERK_BOT; process.env.GUILD_ID;",
@@ -306,7 +306,7 @@ describe("detect warnings", () => {
306
306
  });
307
307
 
308
308
  describe("detect with serverk.json", () => {
309
- test("lets the repository's own file win and says when the code disagrees", () => {
309
+ it("lets the repository's own file win and says when the code disagrees", () => {
310
310
  const result = project({
311
311
  ...DISCORD_NODE,
312
312
  "serverk.json": JSON.stringify({
@@ -336,7 +336,7 @@ describe("detect with serverk.json", () => {
336
336
  expect(result.warnings).toContain(BotInspectWarning.ManifestDisagrees);
337
337
  });
338
338
 
339
- test("installs with the file's own install command over the lockfile's", () => {
339
+ it("installs with the file's own install command over the lockfile's", () => {
340
340
  const result = project({
341
341
  ...DISCORD_NODE,
342
342
  "package-lock.json": "{}",
@@ -352,7 +352,7 @@ describe("detect with serverk.json", () => {
352
352
  expect(result.packageManager).toBe(BotPackageManager.Npm);
353
353
  });
354
354
 
355
- test("reports a broken file and falls back to the code", () => {
355
+ it("reports a broken file and falls back to the code", () => {
356
356
  const result = project({
357
357
  ...DISCORD_NODE,
358
358
  "package-lock.json": "{}",
@@ -367,7 +367,7 @@ describe("detect with serverk.json", () => {
367
367
  });
368
368
 
369
369
  describe("compareCodePoints", () => {
370
- test("orders by code point, the way Python sorts strings, whatever the locale", () => {
370
+ it("orders by code point, the way Python sorts strings, whatever the locale", () => {
371
371
  expect(
372
372
  [
373
373
  "b.js",
@@ -387,7 +387,7 @@ describe("compareCodePoints", () => {
387
387
  });
388
388
 
389
389
  describe("detect env suggestions", () => {
390
- test("reads the example file first, then every way code reads the environment", () => {
390
+ it("reads the example file first, then every way code reads the environment", () => {
391
391
  const result = project({
392
392
  "package.json": "{}",
393
393
  "index.js": [
@@ -438,7 +438,7 @@ describe("detect env suggestions", () => {
438
438
  ]);
439
439
  });
440
440
 
441
- test("names the token key the code reads for its platform", () => {
441
+ it("names the token key the code reads for its platform", () => {
442
442
  const result = project({
443
443
  "requirements.txt": "discord.py==2.7.1\n",
444
444
  "main.py": 'import os\nimport discord\nos.environ.get("MY_BOT_TOKEN")\nos.getenv("LOG_CHANNEL")\n',
@@ -450,7 +450,7 @@ describe("detect env suggestions", () => {
450
450
  });
451
451
 
452
452
  describe("detectWantedFiles", () => {
453
- test("asks for the small files the kit reads and at most forty small sources", () => {
453
+ it("asks for the small files the kit reads and at most forty small sources", () => {
454
454
  const files = [
455
455
  {
456
456
  path: "package.json",
@@ -507,7 +507,7 @@ describe("detectWantedFiles", () => {
507
507
  });
508
508
 
509
509
  describe("the dependency readers", () => {
510
- test("read requirement names and whether each one names a version", () => {
510
+ it("read requirement names and whether each one names a version", () => {
511
511
  expect(parseRequirements("Discord.py[voice]==2.7.1\n-r base.txt\n# note\naiohttp ; python_version>'3'\n")).toEqual([
512
512
  {
513
513
  name: "discord-py",
@@ -520,7 +520,7 @@ describe("the dependency readers", () => {
520
520
  ]);
521
521
  });
522
522
 
523
- test("read project and poetry dependencies from pyproject.toml", () => {
523
+ it("read project and poetry dependencies from pyproject.toml", () => {
524
524
  expect(
525
525
  parsePyprojectDependencies(
526
526
  '[project]\ndependencies = ["hikari>=2", \'aiogram\']\n[tool.poetry.dependencies]\npython = "^3.12"\ntelethon = "*"\n',
@@ -1,11 +1,11 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BotFramework } from "./botFramework";
3
3
  import { DETECT_TABLE, renderDetectTable } from "./detectTable";
4
4
  import { isEnvKey } from "./envKey";
5
5
  import { parseServerkJson } from "./serverkJson";
6
6
 
7
7
  describe("renderDetectTable", () => {
8
- test("renders the table the launchers read as stable, tab-indented JSON", () => {
8
+ it("renders the table the launchers read as stable, tab-indented JSON", () => {
9
9
  const rendered = renderDetectTable();
10
10
 
11
11
  expect(rendered.endsWith("}\n")).toBe(true);
@@ -13,7 +13,7 @@ describe("renderDetectTable", () => {
13
13
  expect(JSON.parse(rendered)).toEqual(DETECT_TABLE);
14
14
  });
15
15
 
16
- test("names an install command for every manager a lockfile or manifest points at", () => {
16
+ it("names an install command for every manager a lockfile or manifest points at", () => {
17
17
  for (const lockfile of DETECT_TABLE.node.lockfiles) {
18
18
  expect(DETECT_TABLE.node.installCommands[lockfile.manager]).toBeDefined();
19
19
  }
@@ -25,7 +25,7 @@ describe("renderDetectTable", () => {
25
25
  }
26
26
  });
27
27
 
28
- test("carries the serverk.json rules the launchers need to agree with the parser", () => {
28
+ it("carries the serverk.json rules the launchers need to agree with the parser", () => {
29
29
  const rules = DETECT_TABLE.serverkJson;
30
30
  const envKey = new RegExp(rules.envKey);
31
31
 
@@ -61,7 +61,7 @@ describe("renderDetectTable", () => {
61
61
  ).toBeNull();
62
62
  });
63
63
 
64
- test("compiles the Procfile line in both JavaScript and Python syntax", () => {
64
+ it("compiles the Procfile line in both JavaScript and Python syntax", () => {
65
65
  const line = new RegExp(DETECT_TABLE.procfile.line);
66
66
 
67
67
  expect(line.exec("worker: node bot.js")?.slice(1)).toEqual([
@@ -1,8 +1,8 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { parseEnvExample } from "./envExample";
3
3
 
4
4
  describe("parseEnvExample", () => {
5
- test("reads keys and example values the way dotenv files write them", () => {
5
+ it("reads keys and example values the way dotenv files write them", () => {
6
6
  expect(
7
7
  parseEnvExample(
8
8
  "# Discord\r\nDISCORD_TOKEN=\r\nexport PREFIX=\"!\" # command prefix\nOWNER_ID = 1234 # yours\nQUOTED='a # b'\nnot a line\n1BAD=x\n",
@@ -1,8 +1,8 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { scanEnvKeys } from "./envScan";
3
3
 
4
4
  describe("scanEnvKeys", () => {
5
- test("finds every way Node code reads a variable", () => {
5
+ it("finds every way Node code reads a variable", () => {
6
6
  expect(
7
7
  scanEnvKeys(
8
8
  "src/index.ts",
@@ -18,7 +18,7 @@ describe("scanEnvKeys", () => {
18
18
  ]);
19
19
  });
20
20
 
21
- test("finds every way Python code reads a variable", () => {
21
+ it("finds every way Python code reads a variable", () => {
22
22
  expect(
23
23
  scanEnvKeys(
24
24
  "bot/main.py",
@@ -33,7 +33,7 @@ describe("scanEnvKeys", () => {
33
33
  ]);
34
34
  });
35
35
 
36
- test("reads nothing from files that are not code", () => {
36
+ it("reads nothing from files that are not code", () => {
37
37
  expect(scanEnvKeys("README.md", "process.env.A")).toEqual([]);
38
38
  });
39
39
  });
@@ -1,11 +1,11 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BotPlatform } from "./botPlatform";
3
3
  import { inferBotPlatform } from "./inferBotPlatform";
4
4
 
5
5
  const TELEGRAM_TOKEN = "7123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw";
6
6
 
7
7
  describe("inferBotPlatform", () => {
8
- test("takes the explicit platform first", () => {
8
+ it("takes the explicit platform first", () => {
9
9
  expect(
10
10
  inferBotPlatform({
11
11
  variables: {
@@ -17,7 +17,7 @@ describe("inferBotPlatform", () => {
17
17
  ).toBe(BotPlatform.Telegram);
18
18
  });
19
19
 
20
- test("then the key names, then the token shape", () => {
20
+ it("then the key names, then the token shape", () => {
21
21
  expect(
22
22
  inferBotPlatform({
23
23
  variables: {},
@@ -36,7 +36,7 @@ describe("inferBotPlatform", () => {
36
36
  ).toBe(BotPlatform.Telegram);
37
37
  });
38
38
 
39
- test("answers null when the hints disagree or do not exist", () => {
39
+ it("answers null when the hints disagree or do not exist", () => {
40
40
  expect(
41
41
  inferBotPlatform({
42
42
  variables: {},
@@ -1,8 +1,8 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BOT_PLATFORM_KEYS, BOT_PLATFORM_SECRET_KEYS, BOT_PROTECTED_KEYS, isReservedBotKey } from "./keys";
3
3
 
4
4
  describe("isReservedBotKey", () => {
5
- test("reserves every platform-owned key, the protected runtime keys and the SERVERK_ prefix", () => {
5
+ it("reserves every platform-owned key, the protected runtime keys and the SERVERK_ prefix", () => {
6
6
  for (const key of [
7
7
  ...BOT_PLATFORM_KEYS,
8
8
  ...BOT_PLATFORM_SECRET_KEYS,
@@ -14,7 +14,7 @@ describe("isReservedBotKey", () => {
14
14
  }
15
15
  });
16
16
 
17
- test("leaves the customer's own keys alone, case included", () => {
17
+ it("leaves the customer's own keys alone, case included", () => {
18
18
  for (const key of [
19
19
  "DISCORD_TOKEN",
20
20
  "NODE_OPTIONS",
@@ -1,8 +1,8 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { isSensitiveKey, keySegments } from "./sensitiveKey";
3
3
 
4
4
  describe("isSensitiveKey", () => {
5
- test("reads a key as whole segments, split on underscores, case changes and digits", () => {
5
+ it("reads a key as whole segments, split on underscores, case changes and digits", () => {
6
6
  expect(keySegments("DISCORD_BOT_TOKEN")).toEqual([
7
7
  "DISCORD",
8
8
  "BOT",
@@ -19,7 +19,7 @@ describe("isSensitiveKey", () => {
19
19
  ]);
20
20
  });
21
21
 
22
- test("hides every key that names a secret in one of its segments", () => {
22
+ it("hides every key that names a secret in one of its segments", () => {
23
23
  for (const key of [
24
24
  "DISCORD_TOKEN",
25
25
  "TELEGRAM_BOT_TOKEN",
@@ -46,7 +46,7 @@ describe("isSensitiveKey", () => {
46
46
  }
47
47
  });
48
48
 
49
- test("hides connection strings, which carry their password inside the link", () => {
49
+ it("hides connection strings, which carry their password inside the link", () => {
50
50
  for (const key of [
51
51
  "DATABASE_URL",
52
52
  "DB_URI",
@@ -65,7 +65,7 @@ describe("isSensitiveKey", () => {
65
65
  }
66
66
  });
67
67
 
68
- test("leaves plain settings visible, including words that only contain a secret word", () => {
68
+ it("leaves plain settings visible, including words that only contain a secret word", () => {
69
69
  for (const key of [
70
70
  "AUTHOR",
71
71
  "AUTHOR_NAME",
@@ -1,11 +1,11 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BotFramework } from "./botFramework";
3
3
  import { BotPlatform } from "./botPlatform";
4
4
  import { BotRuntime } from "./botRuntime";
5
5
  import { parseServerkJson } from "./serverkJson";
6
6
 
7
7
  describe("parseServerkJson", () => {
8
- test("reads every field and ignores unknown ones", () => {
8
+ it("reads every field and ignores unknown ones", () => {
9
9
  expect(
10
10
  parseServerkJson(
11
11
  JSON.stringify({
@@ -45,7 +45,7 @@ describe("parseServerkJson", () => {
45
45
  });
46
46
  });
47
47
 
48
- test("accepts an empty object", () => {
48
+ it("accepts an empty object", () => {
49
49
  expect(parseServerkJson("{}")).toEqual({
50
50
  runtime: null,
51
51
  platform: null,
@@ -56,7 +56,7 @@ describe("parseServerkJson", () => {
56
56
  });
57
57
  });
58
58
 
59
- test("refuses a file with any field it cannot trust", () => {
59
+ it("refuses a file with any field it cannot trust", () => {
60
60
  for (const text of [
61
61
  "[]",
62
62
  "not json",
@@ -74,7 +74,7 @@ describe("parseServerkJson", () => {
74
74
  }
75
75
  });
76
76
 
77
- test("counts a command's length in characters, not UTF-16 units", () => {
77
+ it("counts a command's length in characters, not UTF-16 units", () => {
78
78
  const command = `echo ${"🤖".repeat(1019)}`;
79
79
 
80
80
  expect(