@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,4 +1,4 @@
1
- import { afterEach, beforeEach, describe, expect, test } from "bun:test";
1
+ import { afterEach, beforeEach, describe, expect, it } from "bun:test";
2
2
  import { mkdtemp, rm, writeFile } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
@@ -45,7 +45,7 @@ afterEach(async () => {
45
45
  });
46
46
 
47
47
  describe("the bridge live config reader", () => {
48
- test("answers from the boot snapshot", async () => {
48
+ it("answers from the boot snapshot", async () => {
49
49
  const config = configWith({
50
50
  CURSEFORGE_API_KEY: "boot",
51
51
  });
@@ -58,7 +58,7 @@ describe("the bridge live config reader", () => {
58
58
  expect(secrets.secret("MODRINTH_API_KEY")).toBeNull();
59
59
  });
60
60
 
61
- test("sees a value the agent rewrote into the config", async () => {
61
+ it("sees a value the agent rewrote into the config", async () => {
62
62
  const config = configWith({
63
63
  CURSEFORGE_API_KEY: "boot",
64
64
  });
@@ -80,7 +80,7 @@ describe("the bridge live config reader", () => {
80
80
  expect(secrets.secret("MODRINTH_API_KEY")).toBe("added");
81
81
  });
82
82
 
83
- test("keeps the last good values while the config is mid-write", async () => {
83
+ it("keeps the last good values while the config is mid-write", async () => {
84
84
  const config = configWith({
85
85
  CURSEFORGE_API_KEY: "boot",
86
86
  });
@@ -100,7 +100,7 @@ describe("the bridge live config reader", () => {
100
100
  expect(secrets.secret("CURSEFORGE_API_KEY")).toBe("boot");
101
101
  });
102
102
 
103
- test("re-reads the file at most once per refresh window", async () => {
103
+ it("re-reads the file at most once per refresh window", async () => {
104
104
  const config = configWith({
105
105
  CURSEFORGE_API_KEY: "boot",
106
106
  });
@@ -120,7 +120,7 @@ describe("the bridge live config reader", () => {
120
120
  expect(secrets.secret("CURSEFORGE_API_KEY")).toBe("boot");
121
121
  });
122
122
 
123
- test("sees a variable the customer changed after boot, and the new plan resources", async () => {
123
+ it("sees a variable the customer changed after boot, and the new plan resources", async () => {
124
124
  const config = configWith({});
125
125
 
126
126
  await write(config);
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BRIDGE_PENDING_FILES_LIMIT, type BridgePendingFile } from "../protocol";
3
3
  import type { BridgeLeveledLogger } from "./bridgeLog";
4
4
  import { pendingResult, rejectedPending, unsupportedPending } from "./bridgePending";
@@ -46,7 +46,7 @@ const recorder = () => {
46
46
  };
47
47
 
48
48
  describe("unsupportedPending", () => {
49
- test("answers the sentinel a driver without a pending module gets", () => {
49
+ it("answers the sentinel a driver without a pending module gets", () => {
50
50
  expect(unsupportedPending()).toEqual({
51
51
  supported: false,
52
52
  staging: "",
@@ -58,7 +58,7 @@ describe("unsupportedPending", () => {
58
58
  });
59
59
 
60
60
  describe("pendingResult", () => {
61
- test("carries the staging path, the extensions and the files the driver listed", () => {
61
+ it("carries the staging path, the extensions and the files the driver listed", () => {
62
62
  const { onLog, warnings } = recorder();
63
63
 
64
64
  expect(
@@ -83,7 +83,7 @@ describe("pendingResult", () => {
83
83
  expect(warnings).toEqual([]);
84
84
  });
85
85
 
86
- test("truncates a list longer than the platform takes and warns instead of throwing", () => {
86
+ it("truncates a list longer than the platform takes and warns instead of throwing", () => {
87
87
  const { onLog, warnings } = recorder();
88
88
 
89
89
  const result = pendingResult(
@@ -104,7 +104,7 @@ describe("pendingResult", () => {
104
104
  });
105
105
 
106
106
  describe("rejectedPending", () => {
107
- test("names every file still pending as what the upload was expected to be", () => {
107
+ it("names every file still pending as what the upload was expected to be", () => {
108
108
  const { onLog } = recorder();
109
109
 
110
110
  const result = rejectedPending(
@@ -127,7 +127,7 @@ describe("rejectedPending", () => {
127
127
  expect(result.files).toHaveLength(2);
128
128
  });
129
129
 
130
- test("leaves an empty expectation when the driver has nothing pending left", () => {
130
+ it("leaves an empty expectation when the driver has nothing pending left", () => {
131
131
  const { onLog } = recorder();
132
132
 
133
133
  expect(
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, describe, expect, test } from "bun:test";
1
+ import { afterEach, beforeEach, describe, expect, it } from "bun:test";
2
2
  import { mkdtemp, rm, writeFile } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
@@ -93,7 +93,7 @@ const sourceOf = (initial: Record<string, string>, secrets: Record<string, strin
93
93
  };
94
94
 
95
95
  describe("secretFieldKeys", () => {
96
- test("collects every secret form field once and nothing else", () => {
96
+ it("collects every secret form field once and nothing else", () => {
97
97
  expect(
98
98
  secretFieldKeys(
99
99
  driverWith([
@@ -106,13 +106,13 @@ describe("secretFieldKeys", () => {
106
106
  ]);
107
107
  });
108
108
 
109
- test("finds nothing in a driver with no secret fields", () => {
109
+ it("finds nothing in a driver with no secret fields", () => {
110
110
  expect(secretFieldKeys(driverWith([]))).toEqual([]);
111
111
  });
112
112
  });
113
113
 
114
114
  describe("createBridgeRedaction", () => {
115
- test("is built for every driver and leaves text alone until a secret exists", () => {
115
+ it("is built for every driver and leaves text alone until a secret exists", () => {
116
116
  const { source, seal } = sourceOf({});
117
117
  const redact = createBridgeRedaction([], source);
118
118
 
@@ -125,7 +125,7 @@ describe("createBridgeRedaction", () => {
125
125
  expect(redact(`token ${TOKEN}`)).toBe(`token ${REDACTED}`);
126
126
  });
127
127
 
128
- test("blanks the platform secrets the manifest declares, with the same length floor", () => {
128
+ it("blanks the platform secrets the manifest declares, with the same length floor", () => {
129
129
  const redact = createBridgeRedaction(
130
130
  [],
131
131
  sourceOf(
@@ -140,7 +140,7 @@ describe("createBridgeRedaction", () => {
140
140
  expect(redact("key cf-api-key-0123456789 and short")).toBe(`key ${REDACTED} and short`);
141
141
  });
142
142
 
143
- test("blanks secret fields and platform secrets together", () => {
143
+ it("blanks secret fields and platform secrets together", () => {
144
144
  const redact = createBridgeRedaction(
145
145
  [
146
146
  "BOT_TOKEN",
@@ -158,7 +158,7 @@ describe("createBridgeRedaction", () => {
158
158
  expect(redact(`${TOKEN} cf-api-key-0123456789`)).toBe(`${REDACTED} ${REDACTED}`);
159
159
  });
160
160
 
161
- test("replaces every occurrence of a secret value", () => {
161
+ it("replaces every occurrence of a secret value", () => {
162
162
  const redact = createBridgeRedaction(
163
163
  [
164
164
  "BOT_TOKEN",
@@ -173,7 +173,7 @@ describe("createBridgeRedaction", () => {
173
173
  );
174
174
  });
175
175
 
176
- test("blanks every line of a multi-line secret the process prints one line at a time", () => {
176
+ it("blanks every line of a multi-line secret the process prints one line at a time", () => {
177
177
  const key = [
178
178
  "-----BEGIN PRIVATE KEY-----",
179
179
  "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7",
@@ -198,7 +198,7 @@ describe("createBridgeRedaction", () => {
198
198
  expect(redact(`whole ${key}`)).toBe(`whole ${REDACTED}`);
199
199
  });
200
200
 
201
- test("leaves a value under eight characters alone", () => {
201
+ it("leaves a value under eight characters alone", () => {
202
202
  const redact = createBridgeRedaction(
203
203
  [
204
204
  "RCON_PASSWORD",
@@ -211,7 +211,7 @@ describe("createBridgeRedaction", () => {
211
211
  expect(redact("the password is hunter2")).toBe("the password is hunter2");
212
212
  });
213
213
 
214
- test("escapes values that look like patterns and prefers the longest overlapping value", () => {
214
+ it("escapes values that look like patterns and prefers the longest overlapping value", () => {
215
215
  const redact = createBridgeRedaction(
216
216
  [
217
217
  "SHORT",
@@ -226,7 +226,7 @@ describe("createBridgeRedaction", () => {
226
226
  expect(redact("x a.b+c*d?-and-more y a.b+c*d? z aXb+c*d?")).toBe(`x ${REDACTED} y ${REDACTED} z aXb+c*d?`);
227
227
  });
228
228
 
229
- test("follows a value saved after it was built and forgets the old one", () => {
229
+ it("follows a value saved after it was built and forgets the old one", () => {
230
230
  const { source, save } = sourceOf({
231
231
  BOT_TOKEN: "old-token-value",
232
232
  });
@@ -250,11 +250,11 @@ describe("createBridgeRedaction", () => {
250
250
  describe("redacting what the bridge reports", () => {
251
251
  const redact = (value: string) => value.split(TOKEN).join(REDACTED);
252
252
 
253
- test("covers both languages of a customer-facing message", () => {
253
+ it("covers both languages of a customer-facing message", () => {
254
254
  expect(redactLocalized(text(`bad ${TOKEN}`), redact)).toEqual(text(`bad ${REDACTED}`));
255
255
  });
256
256
 
257
- test("covers the message and every string field of a log line", () => {
257
+ it("covers the message and every string field of a log line", () => {
258
258
  const lines: unknown[] = [];
259
259
  const record = (level: string) => (message: string, fields?: Record<string, unknown>) => {
260
260
  lines.push({
@@ -345,7 +345,7 @@ describe("redaction over the live config", () => {
345
345
  });
346
346
  });
347
347
 
348
- test("reads the platform secrets from the config the agent wrote", async () => {
348
+ it("reads the platform secrets from the config the agent wrote", async () => {
349
349
  const boot = {
350
350
  ...configWith({}),
351
351
  secrets: {
@@ -360,7 +360,7 @@ describe("redaction over the live config", () => {
360
360
  expect(redact("cf-api-key-0123456789")).toBe(REDACTED);
361
361
  });
362
362
 
363
- test("starts as the identity with no secret anywhere and blanks a secret written after boot", async () => {
363
+ it("starts as the identity with no secret anywhere and blanks a secret written after boot", async () => {
364
364
  const boot = configWith({});
365
365
 
366
366
  await write(boot);
@@ -382,7 +382,7 @@ describe("redaction over the live config", () => {
382
382
  expect(redact(`key ${TOKEN}`)).toBe(`key ${REDACTED}`);
383
383
  });
384
384
 
385
- test("picks up a token the agent writes into the config after boot", async () => {
385
+ it("picks up a token the agent writes into the config after boot", async () => {
386
386
  const boot = configWith({});
387
387
 
388
388
  await write(boot);
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { tmpdir } from "node:os";
3
3
  import {
4
4
  BridgeAction,
@@ -116,7 +116,7 @@ const registryFor = (driver: BridgeDriver, variables: Record<string, string> = {
116
116
  };
117
117
 
118
118
  describe("actions modules", () => {
119
- test("lists its action ids in the manifest", () => {
119
+ it("lists its action ids in the manifest", () => {
120
120
  const registry = registryFor({
121
121
  ...baseDriver(),
122
122
  modules: {
@@ -151,7 +151,7 @@ describe("actions modules", () => {
151
151
  ]);
152
152
  });
153
153
 
154
- test("hands the whole argument bag to the handler", async () => {
154
+ it("hands the whole argument bag to the handler", async () => {
155
155
  const received: BridgeValues[] = [];
156
156
 
157
157
  const registry = registryFor({
@@ -179,7 +179,7 @@ describe("actions modules", () => {
179
179
  ]);
180
180
  });
181
181
 
182
- test("refuses to run while the game is stopped", async () => {
182
+ it("refuses to run while the game is stopped", async () => {
183
183
  const registry = registryFor({
184
184
  ...baseDriver(),
185
185
  modules: {
@@ -202,7 +202,7 @@ describe("actions modules", () => {
202
202
  ).rejects.toThrow('module "broadcast" needs the game to be running');
203
203
  });
204
204
 
205
- test("rejects a driver that reuses a read action id", () => {
205
+ it("rejects a driver that reuses a read action id", () => {
206
206
  expect(() =>
207
207
  registryFor({
208
208
  ...baseDriver(),
@@ -222,7 +222,7 @@ describe("actions modules", () => {
222
222
  });
223
223
 
224
224
  describe("manifest events", () => {
225
- test("lists the log patterns and the names the driver raises itself", () => {
225
+ it("lists the log patterns and the names the driver raises itself", () => {
226
226
  const registry = registryFor({
227
227
  ...baseDriver(),
228
228
  events: {
@@ -252,7 +252,7 @@ describe("manifest events", () => {
252
252
  ]);
253
253
  });
254
254
 
255
- test("stays on the log patterns when the driver raises nothing itself", () => {
255
+ it("stays on the log patterns when the driver raises nothing itself", () => {
256
256
  const registry = registryFor({
257
257
  ...baseDriver(),
258
258
  events: {
@@ -273,7 +273,7 @@ describe("manifest events", () => {
273
273
  });
274
274
 
275
275
  describe("collection row actions", () => {
276
- test("passes the row and the arguments without the row id", async () => {
276
+ it("passes the row and the arguments without the row id", async () => {
277
277
  const seen: {
278
278
  row: BridgeRow;
279
279
  args: BridgeValues;
@@ -318,7 +318,7 @@ describe("collection row actions", () => {
318
318
  ]);
319
319
  });
320
320
 
321
- test("keeps listing the built-in actions beside the row actions", () => {
321
+ it("keeps listing the built-in actions beside the row actions", () => {
322
322
  const registry = registryFor({
323
323
  ...baseDriver(),
324
324
  modules: {
@@ -398,7 +398,7 @@ describe("offline row actions", () => {
398
398
  },
399
399
  });
400
400
 
401
- test("hands an offline action the id alone when the row is not listed", async () => {
401
+ it("hands an offline action the id alone when the row is not listed", async () => {
402
402
  const seen: BridgeRow[] = [];
403
403
  const registry = registryFor(
404
404
  rosterDriver(
@@ -419,7 +419,7 @@ describe("offline row actions", () => {
419
419
  ]);
420
420
  });
421
421
 
422
- test("still refuses an unlisted row for an action that is not offline", async () => {
422
+ it("still refuses an unlisted row for an action that is not offline", async () => {
423
423
  const registry = registryFor(
424
424
  rosterDriver(
425
425
  false,
@@ -437,7 +437,7 @@ describe("offline row actions", () => {
437
437
  });
438
438
 
439
439
  describe("preview modules", () => {
440
- test("lists the preview action in the manifest", () => {
440
+ it("lists the preview action in the manifest", () => {
441
441
  const registry = registryFor({
442
442
  ...baseDriver(),
443
443
  modules: {
@@ -466,7 +466,7 @@ describe("preview modules", () => {
466
466
  ]);
467
467
  });
468
468
 
469
- test("shows the module the pending values as variables and leaves the rest as they are stored", async () => {
469
+ it("shows the module the pending values as variables and leaves the rest as they are stored", async () => {
470
470
  const seen: {
471
471
  version: string | null;
472
472
  count: string | null;
@@ -520,7 +520,7 @@ describe("preview modules", () => {
520
520
  ]);
521
521
  });
522
522
 
523
- test("returns what the module answers", async () => {
523
+ it("returns what the module answers", async () => {
524
524
  const registry = registryFor({
525
525
  ...baseDriver(),
526
526
  modules: {
@@ -550,7 +550,7 @@ describe("preview modules", () => {
550
550
  });
551
551
  });
552
552
 
553
- test("refuses an action a preview module does not answer", async () => {
553
+ it("refuses an action a preview module does not answer", async () => {
554
554
  const registry = registryFor({
555
555
  ...baseDriver(),
556
556
  modules: {
@@ -571,7 +571,7 @@ describe("preview modules", () => {
571
571
  });
572
572
 
573
573
  describe("detail modules", () => {
574
- test("lists read and its own action ids in the manifest", () => {
574
+ it("lists read and its own action ids in the manifest", () => {
575
575
  const registry = registryFor({
576
576
  ...baseDriver(),
577
577
  modules: {
@@ -602,7 +602,7 @@ describe("detail modules", () => {
602
602
  ]);
603
603
  });
604
604
 
605
- test("returns what read answers", async () => {
605
+ it("returns what read answers", async () => {
606
606
  const registry = registryFor({
607
607
  ...baseDriver(),
608
608
  modules: {
@@ -630,7 +630,7 @@ describe("detail modules", () => {
630
630
  });
631
631
  });
632
632
 
633
- test("hands the argument bag to an action and returns its outcome", async () => {
633
+ it("hands the argument bag to an action and returns its outcome", async () => {
634
634
  const received: BridgeValues[] = [];
635
635
 
636
636
  const registry = registryFor({
@@ -673,7 +673,7 @@ describe("detail modules", () => {
673
673
  ]);
674
674
  });
675
675
 
676
- test("refuses an action named after a read", () => {
676
+ it("refuses an action named after a read", () => {
677
677
  expect(() =>
678
678
  registryFor({
679
679
  ...baseDriver(),
@@ -690,7 +690,7 @@ describe("detail modules", () => {
690
690
  ).toThrow('module "modpackStatus" declares action "read", which is reserved for reads');
691
691
  });
692
692
 
693
- test("refuses an action the module does not answer", async () => {
693
+ it("refuses an action the module does not answer", async () => {
694
694
  const registry = registryFor({
695
695
  ...baseDriver(),
696
696
  modules: {
@@ -708,7 +708,7 @@ describe("detail modules", () => {
708
708
  });
709
709
 
710
710
  describe("the setup singleton", () => {
711
- test("rides the manifest as its own block and never joins the panel modules", () => {
711
+ it("rides the manifest as its own block and never joins the panel modules", () => {
712
712
  const steps = [
713
713
  {
714
714
  kind: BridgeSetupStepKind.Driver as const,
@@ -736,13 +736,13 @@ describe("the setup singleton", () => {
736
736
  expect(manifest.modules.some((module) => module.kind === BridgeKind.Setup)).toBe(false);
737
737
  });
738
738
 
739
- test("leaves the manifest block empty for a driver that declares no setup", () => {
739
+ it("leaves the manifest block empty for a driver that declares no setup", () => {
740
740
  expect(registryFor(baseDriver()).manifest().setup).toBeNull();
741
741
  });
742
742
  });
743
743
 
744
744
  describe("protected action dispatch", () => {
745
- test("advertises protection and refuses old callers before touching files", async () => {
745
+ it("advertises protection and refuses old callers before touching files", async () => {
746
746
  let calls = 0;
747
747
  const registry = registryFor({
748
748
  ...baseDriver(),
@@ -768,7 +768,7 @@ describe("protected action dispatch", () => {
768
768
  await registry.invoke("world", "replace", {}, "01993720-0000-7000-8000-000000000001");
769
769
  expect(calls).toBe(1);
770
770
  });
771
- test("rejects protection metadata for unknown actions or running-only modules", () => {
771
+ it("rejects protection metadata for unknown actions or running-only modules", () => {
772
772
  for (const module of [
773
773
  {
774
774
  kind: BridgeKind.Actions as const,
@@ -830,7 +830,7 @@ describe("activity", () => {
830
830
  },
831
831
  });
832
832
 
833
- test("answers an invoke with its result and the entries the handler reported", async () => {
833
+ it("answers an invoke with its result and the entries the handler reported", async () => {
834
834
  const { registry, ring } = harnessFor(whitelistDriver());
835
835
 
836
836
  expect(await registry.invoke("whitelist", "add")).toEqual({
@@ -842,7 +842,7 @@ describe("activity", () => {
842
842
  expect(ring.drain(0).events).toEqual([]);
843
843
  });
844
844
 
845
- test("answers an empty list when the handler reported nothing", async () => {
845
+ it("answers an empty list when the handler reported nothing", async () => {
846
846
  const { registry } = harnessFor({
847
847
  ...baseDriver(),
848
848
  modules: {
@@ -863,7 +863,7 @@ describe("activity", () => {
863
863
  });
864
864
  });
865
865
 
866
- test("sends what a failing handler reported to the events ring", async () => {
866
+ it("sends what a failing handler reported to the events ring", async () => {
867
867
  const { registry, ring } = harnessFor(whitelistDriver(true));
868
868
 
869
869
  await expect(registry.invoke("whitelist", "add")).rejects.toThrow("read-only");
@@ -946,7 +946,7 @@ describe("activity", () => {
946
946
  },
947
947
  });
948
948
 
949
- test("reports the keys whose value changed when the handler reported nothing", async () => {
949
+ it("reports the keys whose value changed when the handler reported nothing", async () => {
950
950
  const { registry } = harnessFor(
951
951
  settingsDriver({
952
952
  stored: {
@@ -980,7 +980,7 @@ describe("activity", () => {
980
980
  ]);
981
981
  });
982
982
 
983
- test("finishes the write even when a stored value cannot be compared", async () => {
983
+ it("finishes the write even when a stored value cannot be compared", async () => {
984
984
  const { registry } = harnessFor(
985
985
  settingsDriver({
986
986
  stored: {},
@@ -1005,7 +1005,7 @@ describe("activity", () => {
1005
1005
  });
1006
1006
  });
1007
1007
 
1008
- test("reports nothing when no value changed", async () => {
1008
+ it("reports nothing when no value changed", async () => {
1009
1009
  const { registry } = harnessFor(
1010
1010
  settingsDriver({
1011
1011
  stored: {
@@ -1023,7 +1023,7 @@ describe("activity", () => {
1023
1023
  ).toEqual([]);
1024
1024
  });
1025
1025
 
1026
- test("keeps the handler's own entry instead of the default", async () => {
1026
+ it("keeps the handler's own entry instead of the default", async () => {
1027
1027
  const { registry } = harnessFor(
1028
1028
  settingsDriver({
1029
1029
  stored: {
@@ -1042,7 +1042,7 @@ describe("activity", () => {
1042
1042
  ]);
1043
1043
  });
1044
1044
 
1045
- test("reports every written key when the settings could not be read first", async () => {
1045
+ it("reports every written key when the settings could not be read first", async () => {
1046
1046
  const { registry } = harnessFor(
1047
1047
  settingsDriver({
1048
1048
  stored: {},
@@ -1063,7 +1063,7 @@ describe("activity", () => {
1063
1063
  });
1064
1064
  });
1065
1065
 
1066
- test("never carries the value of a secret field", async () => {
1066
+ it("never carries the value of a secret field", async () => {
1067
1067
  const secret = "hunter22hunter22";
1068
1068
 
1069
1069
  const { registry } = harnessFor(
@@ -1085,7 +1085,7 @@ describe("activity", () => {
1085
1085
  expect(JSON.stringify(activity)).not.toContain(secret);
1086
1086
  });
1087
1087
 
1088
- test("drops a detail a handler keyed by a secret field", async () => {
1088
+ it("drops a detail a handler keyed by a secret field", async () => {
1089
1089
  const { registry } = harnessFor({
1090
1090
  ...settingsDriver({
1091
1091
  stored: {},
@@ -1126,7 +1126,7 @@ describe("activity", () => {
1126
1126
  });
1127
1127
  });
1128
1128
 
1129
- test("reports no default for a catalog install", async () => {
1129
+ it("reports no default for a catalog install", async () => {
1130
1130
  const { registry } = harnessFor({
1131
1131
  ...baseDriver(),
1132
1132
  modules: {
@@ -1234,7 +1234,7 @@ describe("availability", () => {
1234
1234
  throw new Error("the invoke did not refuse");
1235
1235
  };
1236
1236
 
1237
- test("advertises availability only for a collection that declares the hook", () => {
1237
+ it("advertises availability only for a collection that declares the hook", () => {
1238
1238
  const registry = registryFor({
1239
1239
  ...baseDriver(),
1240
1240
  modules: {
@@ -1273,7 +1273,7 @@ describe("availability", () => {
1273
1273
  ]);
1274
1274
  });
1275
1275
 
1276
- test("answers the reasons per row and leaves available rows out", async () => {
1276
+ it("answers the reasons per row and leaves available rows out", async () => {
1277
1277
  const registry = registryFor(
1278
1278
  worldsDriver({
1279
1279
  listed: 0,
@@ -1292,7 +1292,7 @@ describe("availability", () => {
1292
1292
  });
1293
1293
  });
1294
1294
 
1295
- test("narrows the answer to one row when asked for its id", async () => {
1295
+ it("narrows the answer to one row when asked for its id", async () => {
1296
1296
  const registry = registryFor(
1297
1297
  worldsDriver({
1298
1298
  listed: 0,
@@ -1312,7 +1312,7 @@ describe("availability", () => {
1312
1312
  });
1313
1313
  });
1314
1314
 
1315
- test("refuses an unavailable row action before the driver is entered", async () => {
1315
+ it("refuses an unavailable row action before the driver is entered", async () => {
1316
1316
  const spies = {
1317
1317
  listed: 0,
1318
1318
  deleted: [] as string[],
@@ -1338,7 +1338,7 @@ describe("availability", () => {
1338
1338
  ]);
1339
1339
  });
1340
1340
 
1341
- test("lets the action run when the hook itself fails", async () => {
1341
+ it("lets the action run when the hook itself fails", async () => {
1342
1342
  const spies = {
1343
1343
  listed: 0,
1344
1344
  deleted: [] as string[],
@@ -1355,7 +1355,7 @@ describe("availability", () => {
1355
1355
  ]);
1356
1356
  });
1357
1357
 
1358
- test("lets an availability read join a list already in flight and never reuses a settled one", async () => {
1358
+ it("lets an availability read join a list already in flight and never reuses a settled one", async () => {
1359
1359
  const spies = {
1360
1360
  listed: 0,
1361
1361
  deleted: [] as string[],
@@ -1375,7 +1375,7 @@ describe("availability", () => {
1375
1375
  expect(spies.listed).toBe(3);
1376
1376
  });
1377
1377
 
1378
- test("lists fresh for every list read and every action", async () => {
1378
+ it("lists fresh for every list read and every action", async () => {
1379
1379
  const spies = {
1380
1380
  listed: 0,
1381
1381
  deleted: [] as string[],
@@ -1393,7 +1393,7 @@ describe("availability", () => {
1393
1393
  expect(spies.listed).toBe(3);
1394
1394
  });
1395
1395
 
1396
- test("forgets a list in flight when any module mutates", async () => {
1396
+ it("forgets a list in flight when any module mutates", async () => {
1397
1397
  let listed = 0;
1398
1398
  let release = () => {};
1399
1399
  const gate = new Promise<void>((resolve) => {
@@ -1444,7 +1444,7 @@ describe("availability", () => {
1444
1444
  await first;
1445
1445
  });
1446
1446
 
1447
- test("drops reasons for actions the module cannot refuse and clamps long ones", async () => {
1447
+ it("drops reasons for actions the module cannot refuse and clamps long ones", async () => {
1448
1448
  const registry = registryFor({
1449
1449
  ...baseDriver(),
1450
1450
  modules: {
@@ -1485,7 +1485,7 @@ describe("availability", () => {
1485
1485
  });
1486
1486
  });
1487
1487
 
1488
- test("drops entries the wire would refuse so the answer always validates", async () => {
1488
+ it("drops entries the wire would refuse so the answer always validates", async () => {
1489
1489
  const registry = registryFor({
1490
1490
  ...baseDriver(),
1491
1491
  modules: {
@@ -1528,7 +1528,7 @@ describe("availability", () => {
1528
1528
  expect(bridgeAvailabilitySchema.safeParse(result).success).toBe(true);
1529
1529
  });
1530
1530
 
1531
- test("enforces the allow-list of a detail and answers its reasons", async () => {
1531
+ it("enforces the allow-list of a detail and answers its reasons", async () => {
1532
1532
  const updates: BridgeValues[] = [];
1533
1533
  let pressable: string[] = [];
1534
1534
  const stale: LocalizedText = {
@@ -1572,8 +1572,8 @@ describe("availability", () => {
1572
1572
  module: {
1573
1573
  update: stale,
1574
1574
  repair: {
1575
- ar: "هذا الإجراء مو متاح الحين",
1576
- en: "This action is not available right now",
1575
+ ar: "هذا الإجراء غير متاح حاليًا",
1576
+ en: "This action isn't available right now",
1577
1577
  },
1578
1578
  },
1579
1579
  subjects: {},
@@ -1594,7 +1594,7 @@ describe("availability", () => {
1594
1594
  expect(updates).toHaveLength(1);
1595
1595
  });
1596
1596
 
1597
- test("refuses an actions module, a settings write and a catalog removal through their hooks", async () => {
1597
+ it("refuses an actions module, a settings write and a catalog removal through their hooks", async () => {
1598
1598
  const closed: LocalizedText = {
1599
1599
  ar: "مقفل الحين",
1600
1600
  en: "Closed right now",
@@ -1713,7 +1713,7 @@ describe("availability", () => {
1713
1713
  });
1714
1714
  });
1715
1715
 
1716
- test("does not answer availability for a module that declares no hook", async () => {
1716
+ it("does not answer availability for a module that declares no hook", async () => {
1717
1717
  const registry = registryFor({
1718
1718
  ...baseDriver(),
1719
1719
  modules: {
@@ -1729,7 +1729,7 @@ describe("availability", () => {
1729
1729
  );
1730
1730
  });
1731
1731
 
1732
- test("refuses a driver that names a row action availability", () => {
1732
+ it("refuses a driver that names a row action availability", () => {
1733
1733
  expect(() =>
1734
1734
  registryFor({
1735
1735
  ...baseDriver(),
@@ -1748,7 +1748,7 @@ describe("availability", () => {
1748
1748
  ).toThrow('module "worlds" declares action "availability", which is reserved for reads');
1749
1749
  });
1750
1750
 
1751
- test("turns the gates that never enter the driver into refusals without text", async () => {
1751
+ it("turns the gates that never enter the driver into refusals without text", async () => {
1752
1752
  const registry = registryFor({
1753
1753
  ...baseDriver(),
1754
1754
  modules: {
@@ -53,8 +53,8 @@ interface CacheEntry {
53
53
  }
54
54
 
55
55
  const UNAVAILABLE_TEXT: LocalizedText = {
56
- ar: "هذا الإجراء مو متاح الحين",
57
- en: "This action is not available right now",
56
+ ar: "هذا الإجراء غير متاح حاليًا",
57
+ en: "This action isn't available right now",
58
58
  };
59
59
 
60
60
  const requiresRunning = (module: BridgePanelModule) => {