@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,5 +1,12 @@
1
1
  import { timingSafeEqual } from "node:crypto";
2
- import { BridgeFailureError, BridgeSecretError, BridgeUserError, type BridgeValues } from "../core";
2
+ import type { Socket } from "bun";
3
+ import {
4
+ type BridgeActivity,
5
+ BridgeFailureError,
6
+ BridgeSecretError,
7
+ BridgeUserError,
8
+ type BridgeValues,
9
+ } from "../core";
3
10
  import {
4
11
  BRIDGE_FRAME_LIMIT,
5
12
  type BridgeAnnounceResult,
@@ -15,8 +22,10 @@ import {
15
22
  type BridgeSetupResult,
16
23
  type BridgeStatus,
17
24
  } from "../protocol";
18
- import { type BridgeLogger, errorText } from "./bridgeLog";
25
+ import type { BridgeActivityAnswer } from "./bridgeActivity";
26
+ import { type BridgeLogger, errorDetail } from "./bridgeLog";
19
27
  import { redactLocalized } from "./bridgeRedaction";
28
+ import { BridgeRefusalError } from "./bridgeRefusalError";
20
29
 
21
30
  export interface ServerOptions {
22
31
  socket: string;
@@ -26,7 +35,12 @@ export interface ServerOptions {
26
35
  onStart: () => Promise<void>;
27
36
  onStop: () => Promise<void>;
28
37
  onCommand: (input: string, expect: string | undefined, timeoutMs: number | undefined) => Promise<BridgeCommandResult>;
29
- onInvoke: (module: string, action: string, args: BridgeValues, recoveryOperationId?: string) => Promise<unknown>;
38
+ onInvoke: (
39
+ module: string,
40
+ action: string,
41
+ args: BridgeValues,
42
+ recoveryOperationId?: string,
43
+ ) => Promise<BridgeActivityAnswer<unknown>>;
30
44
  onEvents: (cursor: number) => BridgeEventsResult;
31
45
  onSample: () => Promise<BridgeSampleResult>;
32
46
  onQuiesce: (supportsSnapshot: boolean, leaseId?: string) => Promise<BridgeQuiesceResult>;
@@ -36,11 +50,17 @@ export interface ServerOptions {
36
50
  onPendingList: () => Promise<BridgePendingResult>;
37
51
  onPendingAdd: (input: string) => Promise<BridgePendingResult>;
38
52
  onSetupStatus: () => BridgeSetupResult;
39
- onSetupSubmit: (step: string, action: string, args: BridgeValues) => Promise<BridgeSetupResult>;
53
+ onSetupSubmit: (step: string, action: string, args: BridgeValues) => Promise<BridgeActivityAnswer<BridgeSetupResult>>;
54
+ onUndelivered: (activity: BridgeActivity[]) => void;
40
55
  onLog: BridgeLogger;
41
56
  redact?: (text: string) => string;
42
57
  }
43
58
 
59
+ interface SocketState {
60
+ buffer: string;
61
+ closed: boolean;
62
+ }
63
+
44
64
  interface IncomingFrame {
45
65
  leaseId?: unknown;
46
66
  supportsSnapshot?: unknown;
@@ -73,6 +93,23 @@ const encode = (response: BridgeResponse) => {
73
93
  return `${JSON.stringify(response)}\n`;
74
94
  };
75
95
 
96
+ interface PlainAnswer {
97
+ result: unknown;
98
+ activity: null;
99
+ }
100
+
101
+ const deliver = (socket: Socket<SocketState>, frame: string): boolean => {
102
+ if (socket.data.closed) {
103
+ return false;
104
+ }
105
+
106
+ try {
107
+ return socket.write(frame) === Buffer.byteLength(frame);
108
+ } catch {
109
+ return false;
110
+ }
111
+ };
112
+
76
113
  const asArgs = (value: unknown): BridgeValues => {
77
114
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
78
115
  return {};
@@ -90,10 +127,10 @@ const asArgs = (value: unknown): BridgeValues => {
90
127
  };
91
128
 
92
129
  const logFailure = (onLog: BridgeLogger, method: string, error: unknown) => {
93
- if (error instanceof BridgeUserError) {
130
+ if (error instanceof BridgeUserError || error instanceof BridgeRefusalError) {
94
131
  onLog("bridge call refused", {
95
132
  method,
96
- error: error.message,
133
+ error: errorDetail(error),
97
134
  });
98
135
 
99
136
  return;
@@ -101,7 +138,7 @@ const logFailure = (onLog: BridgeLogger, method: string, error: unknown) => {
101
138
 
102
139
  onLog("bridge call failed", {
103
140
  method,
104
- error: errorText(error),
141
+ error: errorDetail(error),
105
142
  stack: error instanceof Error ? (error.stack ?? null) : null,
106
143
  });
107
144
  };
@@ -137,15 +174,6 @@ export const createServer = (options: ServerOptions) => {
137
174
  );
138
175
  }
139
176
 
140
- case BridgeMethod.Invoke: {
141
- return await options.onInvoke(
142
- String(request.module ?? ""),
143
- String(request.action ?? ""),
144
- asArgs(request.args),
145
- asText(request.recoveryOperationId) ?? undefined,
146
- );
147
- }
148
-
149
177
  case BridgeMethod.Events: {
150
178
  return options.onEvents(typeof request.cursor === "number" ? request.cursor : 0);
151
179
  }
@@ -196,33 +224,68 @@ export const createServer = (options: ServerOptions) => {
196
224
  return options.onSetupStatus();
197
225
  }
198
226
 
199
- case BridgeMethod.SetupSubmit: {
200
- const step = asText(request.module);
227
+ default: {
228
+ throw new Error(`unknown method "${method}"`);
229
+ }
230
+ }
231
+ };
201
232
 
202
- if (!step) {
203
- throw new Error("setupSubmit needs a step id");
204
- }
233
+ const answer = async (
234
+ method: string,
235
+ request: IncomingFrame,
236
+ ): Promise<BridgeActivityAnswer<unknown> | PlainAnswer> => {
237
+ if (method === BridgeMethod.Invoke) {
238
+ return await options.onInvoke(
239
+ String(request.module ?? ""),
240
+ String(request.action ?? ""),
241
+ asArgs(request.args),
242
+ asText(request.recoveryOperationId) ?? undefined,
243
+ );
244
+ }
205
245
 
206
- return await options.onSetupSubmit(step, String(request.action ?? ""), asArgs(request.args));
207
- }
246
+ if (method === BridgeMethod.SetupSubmit) {
247
+ const step = asText(request.module);
208
248
 
209
- default: {
210
- throw new Error(`unknown method "${method}"`);
249
+ if (!step) {
250
+ throw new Error("setupSubmit needs a step id");
211
251
  }
252
+
253
+ return await options.onSetupSubmit(step, String(request.action ?? ""), asArgs(request.args));
212
254
  }
255
+
256
+ return {
257
+ result: await handle(method, request),
258
+ activity: null,
259
+ };
213
260
  };
214
261
 
215
- return Bun.listen<{
216
- buffer: string;
217
- }>({
262
+ const undelivered = (method: string, activity: BridgeActivity[]) => {
263
+ if (activity.length === 0) {
264
+ return;
265
+ }
266
+
267
+ options.onLog("answer not delivered, its activity goes to the events ring", {
268
+ method,
269
+ entries: activity.length,
270
+ });
271
+
272
+ options.onUndelivered(activity);
273
+ };
274
+
275
+ return Bun.listen<SocketState>({
218
276
  unix: options.socket,
219
277
  socket: {
220
278
  open(socket) {
221
279
  socket.data = {
222
280
  buffer: "",
281
+ closed: false,
223
282
  };
224
283
  },
225
284
 
285
+ close(socket) {
286
+ socket.data.closed = true;
287
+ },
288
+
226
289
  data(socket, chunk) {
227
290
  socket.data.buffer += chunk.toString();
228
291
 
@@ -278,15 +341,32 @@ export const createServer = (options: ServerOptions) => {
278
341
  continue;
279
342
  }
280
343
 
281
- void handle(String(request.method ?? ""), request)
282
- .then((result) => {
283
- socket.write(
284
- encode({
344
+ void answer(String(request.method ?? ""), request)
345
+ .then(({ result, activity }) => {
346
+ const method = String(request.method ?? "");
347
+
348
+ let frame: string;
349
+
350
+ try {
351
+ frame = encode({
285
352
  id,
286
353
  ok: true,
287
354
  result,
288
- }),
289
- );
355
+ ...(activity === null
356
+ ? {}
357
+ : {
358
+ activity,
359
+ }),
360
+ });
361
+ } catch (error) {
362
+ undelivered(method, activity ?? []);
363
+
364
+ throw error;
365
+ }
366
+
367
+ if (!deliver(socket, frame)) {
368
+ undelivered(method, activity ?? []);
369
+ }
290
370
  })
291
371
  .catch((error: unknown) => {
292
372
  logFailure(options.onLog, String(request.method ?? ""), error);
@@ -297,7 +377,7 @@ export const createServer = (options: ServerOptions) => {
297
377
  encode({
298
378
  id,
299
379
  ok: false,
300
- error: redact(errorText(error)),
380
+ error: redact(errorDetail(error)),
301
381
  ...(error instanceof BridgeSecretError
302
382
  ? {
303
383
  secret: error.key,
@@ -313,6 +393,16 @@ export const createServer = (options: ServerOptions) => {
313
393
  text: redactLocalized(error.text, redact),
314
394
  }
315
395
  : {}),
396
+ ...(error instanceof BridgeRefusalError
397
+ ? {
398
+ unchanged: true,
399
+ ...(error.text
400
+ ? {
401
+ text: redactLocalized(error.text, redact),
402
+ }
403
+ : {}),
404
+ }
405
+ : {}),
316
406
  }),
317
407
  );
318
408
  });
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { describe, expect, it } from "bun:test";
2
2
  import { BridgeSetupPromptKind, BridgeSetupStepState } from "../core";
3
3
  import type { BridgeSetupRuntime } from "../protocol";
4
4
  import { failedSetup, normalizeSetupRuntime, setupSummaryOf, unsupportedSetup } from "./bridgeSetup";
@@ -23,11 +23,11 @@ const runtimeWith = (prompt: BridgeSetupRuntime["prompt"]): BridgeSetupRuntime =
23
23
  });
24
24
 
25
25
  describe("the setup summary", () => {
26
- test("has nothing to summarise while the driver reported no runtime", () => {
26
+ it("has nothing to summarise while the driver reported no runtime", () => {
27
27
  expect(setupSummaryOf(null)).toBeNull();
28
28
  });
29
29
 
30
- test("names the active driver step", () => {
30
+ it("names the active driver step", () => {
31
31
  expect(
32
32
  setupSummaryOf(
33
33
  runtimeWith({
@@ -41,7 +41,7 @@ describe("the setup summary", () => {
41
41
  });
42
42
  });
43
43
 
44
- test("names no step once every driver step is done", () => {
44
+ it("names no step once every driver step is done", () => {
45
45
  expect(
46
46
  setupSummaryOf({
47
47
  steps: [
@@ -58,7 +58,7 @@ describe("the setup summary", () => {
58
58
  });
59
59
  });
60
60
 
61
- test("asks for attention while a link prompt waits on the customer", () => {
61
+ it("asks for attention while a link prompt waits on the customer", () => {
62
62
  expect(
63
63
  setupSummaryOf(
64
64
  runtimeWith({
@@ -73,7 +73,7 @@ describe("the setup summary", () => {
73
73
  ).toBe(true);
74
74
  });
75
75
 
76
- test("asks for attention on an action prompt and on a failed one", () => {
76
+ it("asks for attention on an action prompt and on a failed one", () => {
77
77
  expect(
78
78
  setupSummaryOf(
79
79
  runtimeWith({
@@ -95,7 +95,7 @@ describe("the setup summary", () => {
95
95
  ).toBe(true);
96
96
  });
97
97
 
98
- test("waits quietly while a progress prompt runs", () => {
98
+ it("waits quietly while a progress prompt runs", () => {
99
99
  expect(
100
100
  setupSummaryOf(
101
101
  runtimeWith({
@@ -110,7 +110,7 @@ describe("the setup summary", () => {
110
110
  });
111
111
 
112
112
  describe("the unsupported sentinel", () => {
113
- test("answers a driver that declares no setup", () => {
113
+ it("answers a driver that declares no setup", () => {
114
114
  expect(unsupportedSetup()).toEqual({
115
115
  supported: false,
116
116
  runtime: null,
@@ -119,7 +119,7 @@ describe("the unsupported sentinel", () => {
119
119
  });
120
120
 
121
121
  describe("a rejected submit", () => {
122
- test("turns the user error into a failed prompt keeping the previous actions", () => {
122
+ it("turns the user error into a failed prompt keeping the previous actions", () => {
123
123
  const result = failedSetup(
124
124
  runtimeWith({
125
125
  kind: BridgeSetupPromptKind.Link,
@@ -164,7 +164,7 @@ describe("a rejected submit", () => {
164
164
  });
165
165
  });
166
166
 
167
- test("carries no actions over from a prompt that had none", () => {
167
+ it("carries no actions over from a prompt that had none", () => {
168
168
  const result = failedSetup(
169
169
  runtimeWith({
170
170
  kind: BridgeSetupPromptKind.Wait,
@@ -180,7 +180,7 @@ describe("a rejected submit", () => {
180
180
  });
181
181
  });
182
182
 
183
- test("stays empty when the driver never reported a runtime", () => {
183
+ it("stays empty when the driver never reported a runtime", () => {
184
184
  expect(failedSetup(null, text("nothing to fail"))).toEqual({
185
185
  supported: true,
186
186
  runtime: null,
@@ -236,7 +236,7 @@ const link = (
236
236
  };
237
237
 
238
238
  describe("normalizing a reported runtime", () => {
239
- test("has nothing to normalize while the driver reported no runtime", () => {
239
+ it("has nothing to normalize while the driver reported no runtime", () => {
240
240
  expect(
241
241
  normalizeSetupRuntime(null, {
242
242
  declared,
@@ -247,7 +247,7 @@ describe("normalizing a reported runtime", () => {
247
247
  ).toBeNull();
248
248
  });
249
249
 
250
- test("drops a step the driver never declared", () => {
250
+ it("drops a step the driver never declared", () => {
251
251
  const { normalized, reasons } = normalizing(
252
252
  withSteps([
253
253
  {
@@ -272,7 +272,7 @@ describe("normalizing a reported runtime", () => {
272
272
  ]);
273
273
  });
274
274
 
275
- test("drops the second report of the same step", () => {
275
+ it("drops the second report of the same step", () => {
276
276
  const { normalized, reasons } = normalizing(
277
277
  withSteps([
278
278
  {
@@ -297,7 +297,7 @@ describe("normalizing a reported runtime", () => {
297
297
  ]);
298
298
  });
299
299
 
300
- test("keeps the first active step and pends the rest", () => {
300
+ it("keeps the first active step and pends the rest", () => {
301
301
  const { normalized, reasons } = normalizing(
302
302
  withSteps([
303
303
  {
@@ -326,7 +326,7 @@ describe("normalizing a reported runtime", () => {
326
326
  ]);
327
327
  });
328
328
 
329
- test("clamps a percent that left the scale", () => {
329
+ it("clamps a percent that left the scale", () => {
330
330
  expect(
331
331
  normalizing(
332
332
  runtimeWith({
@@ -361,7 +361,7 @@ describe("normalizing a reported runtime", () => {
361
361
  });
362
362
  });
363
363
 
364
- test("drops a percent that is not a number", () => {
364
+ it("drops a percent that is not a number", () => {
365
365
  const { normalized, reasons } = normalizing(
366
366
  runtimeWith({
367
367
  kind: BridgeSetupPromptKind.Progress,
@@ -382,7 +382,7 @@ describe("normalizing a reported runtime", () => {
382
382
  ]);
383
383
  });
384
384
 
385
- test("cuts a detail line to the length the platform takes", () => {
385
+ it("cuts a detail line to the length the platform takes", () => {
386
386
  const { normalized, reasons } = normalizing(
387
387
  runtimeWith({
388
388
  kind: BridgeSetupPromptKind.Progress,
@@ -403,7 +403,7 @@ describe("normalizing a reported runtime", () => {
403
403
  ]);
404
404
  });
405
405
 
406
- test("drops an empty detail line", () => {
406
+ it("drops an empty detail line", () => {
407
407
  const { normalized, reasons } = normalizing(
408
408
  runtimeWith({
409
409
  kind: BridgeSetupPromptKind.Progress,
@@ -421,7 +421,7 @@ describe("normalizing a reported runtime", () => {
421
421
  ]);
422
422
  });
423
423
 
424
- test("drops an action whose id is not kebab-case and the duplicate beside it", () => {
424
+ it("drops an action whose id is not kebab-case and the duplicate beside it", () => {
425
425
  const { normalized, reasons } = normalizing(
426
426
  runtimeWith({
427
427
  kind: BridgeSetupPromptKind.Action,
@@ -459,7 +459,7 @@ describe("normalizing a reported runtime", () => {
459
459
  ]);
460
460
  });
461
461
 
462
- test("keeps only as many actions as the platform renders", () => {
462
+ it("keeps only as many actions as the platform renders", () => {
463
463
  const { normalized, reasons } = normalizing(
464
464
  runtimeWith({
465
465
  kind: BridgeSetupPromptKind.Failed,
@@ -480,7 +480,7 @@ describe("normalizing a reported runtime", () => {
480
480
  ]);
481
481
  });
482
482
 
483
- test("cuts a long code and drops an empty one", () => {
483
+ it("cuts a long code and drops an empty one", () => {
484
484
  expect(
485
485
  normalizing(
486
486
  link({
@@ -502,7 +502,7 @@ describe("normalizing a reported runtime", () => {
502
502
  ]);
503
503
  });
504
504
 
505
- test("re-emits an expiry as an iso stamp and drops one it cannot read", () => {
505
+ it("re-emits an expiry as an iso stamp and drops one it cannot read", () => {
506
506
  expect(
507
507
  normalizing(
508
508
  link({
@@ -524,7 +524,7 @@ describe("normalizing a reported runtime", () => {
524
524
  ]);
525
525
  });
526
526
 
527
- test("turns a link the browser cannot open into a failed prompt keeping its actions", () => {
527
+ it("turns a link the browser cannot open into a failed prompt keeping its actions", () => {
528
528
  const { normalized, reasons } = normalizing(
529
529
  link({
530
530
  url: "javascript:alert(1)",
@@ -540,7 +540,7 @@ describe("normalizing a reported runtime", () => {
540
540
  expect(normalized?.prompt).toEqual({
541
541
  kind: BridgeSetupPromptKind.Failed,
542
542
  message: {
543
- ar: "اللعبة رجّعت رابط دخول ما يشتغل. جرّب مرة ثانية.",
543
+ ar: "أعادت اللعبة رابط تسجيل دخول غير صالح، جرب مرة ثانية.",
544
544
  en: "The game reported a broken sign-in link. Try again.",
545
545
  },
546
546
  actions: [
@@ -555,7 +555,7 @@ describe("normalizing a reported runtime", () => {
555
555
  ]);
556
556
  });
557
557
 
558
- test("turns a url it cannot parse into a failed prompt", () => {
558
+ it("turns a url it cannot parse into a failed prompt", () => {
559
559
  expect(
560
560
  normalizing(
561
561
  link({
@@ -565,7 +565,7 @@ describe("normalizing a reported runtime", () => {
565
565
  ).toBe(BridgeSetupPromptKind.Failed);
566
566
  });
567
567
 
568
- test("leaves a healthy runtime exactly as the driver reported it", () => {
568
+ it("leaves a healthy runtime exactly as the driver reported it", () => {
569
569
  const source = link({});
570
570
  const { normalized, reasons } = normalizing(source);
571
571
 
@@ -68,7 +68,7 @@ export const failedSetup = (runtime: BridgeSetupRuntime | null, text: LocalizedT
68
68
  };
69
69
 
70
70
  const BROKEN_LINK_TEXT: LocalizedText = {
71
- ar: "اللعبة رجّعت رابط دخول ما يشتغل. جرّب مرة ثانية.",
71
+ ar: "أعادت اللعبة رابط تسجيل دخول غير صالح، جرب مرة ثانية.",
72
72
  en: "The game reported a broken sign-in link. Try again.",
73
73
  };
74
74