@kodelyth/line 2026.5.42 → 2026.6.1

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 (90) hide show
  1. package/klaw.plugin.json +329 -2
  2. package/package.json +16 -4
  3. package/api.ts +0 -11
  4. package/channel-plugin-api.ts +0 -1
  5. package/contract-api.ts +0 -5
  6. package/index.ts +0 -53
  7. package/runtime-api.ts +0 -179
  8. package/secret-contract-api.ts +0 -4
  9. package/setup-api.ts +0 -2
  10. package/setup-entry.ts +0 -9
  11. package/src/account-helpers.ts +0 -16
  12. package/src/accounts.test.ts +0 -288
  13. package/src/accounts.ts +0 -187
  14. package/src/actions.ts +0 -61
  15. package/src/auto-reply-delivery.test.ts +0 -253
  16. package/src/auto-reply-delivery.ts +0 -200
  17. package/src/bindings.ts +0 -65
  18. package/src/bot-access.ts +0 -30
  19. package/src/bot-handlers.test.ts +0 -1094
  20. package/src/bot-handlers.ts +0 -620
  21. package/src/bot-message-context.test.ts +0 -420
  22. package/src/bot-message-context.ts +0 -586
  23. package/src/bot.ts +0 -66
  24. package/src/card-command.ts +0 -347
  25. package/src/channel-access-token.ts +0 -14
  26. package/src/channel-api.ts +0 -17
  27. package/src/channel-setup-status.contract.test.ts +0 -70
  28. package/src/channel-shared.ts +0 -48
  29. package/src/channel.logout.test.ts +0 -145
  30. package/src/channel.runtime.ts +0 -3
  31. package/src/channel.sendPayload.test.ts +0 -659
  32. package/src/channel.setup.ts +0 -11
  33. package/src/channel.status.test.ts +0 -63
  34. package/src/channel.ts +0 -155
  35. package/src/config-adapter.ts +0 -29
  36. package/src/config-schema.test.ts +0 -53
  37. package/src/config-schema.ts +0 -81
  38. package/src/download.test.ts +0 -164
  39. package/src/download.ts +0 -34
  40. package/src/flex-templates/basic-cards.ts +0 -395
  41. package/src/flex-templates/common.ts +0 -20
  42. package/src/flex-templates/media-control-cards.ts +0 -555
  43. package/src/flex-templates/message.ts +0 -13
  44. package/src/flex-templates/schedule-cards.ts +0 -467
  45. package/src/flex-templates/types.ts +0 -22
  46. package/src/flex-templates.ts +0 -32
  47. package/src/gateway.ts +0 -129
  48. package/src/group-keys.test.ts +0 -123
  49. package/src/group-keys.ts +0 -65
  50. package/src/group-policy.ts +0 -22
  51. package/src/markdown-to-line.test.ts +0 -348
  52. package/src/markdown-to-line.ts +0 -416
  53. package/src/message-cards.test.ts +0 -204
  54. package/src/monitor-durable.test.ts +0 -57
  55. package/src/monitor-durable.ts +0 -37
  56. package/src/monitor.lifecycle.test.ts +0 -499
  57. package/src/monitor.runtime.ts +0 -1
  58. package/src/monitor.ts +0 -507
  59. package/src/outbound-media.test.ts +0 -194
  60. package/src/outbound-media.ts +0 -120
  61. package/src/outbound.runtime.ts +0 -12
  62. package/src/outbound.ts +0 -427
  63. package/src/probe.contract.test.ts +0 -9
  64. package/src/probe.runtime.ts +0 -1
  65. package/src/probe.ts +0 -34
  66. package/src/quick-reply-fallback.ts +0 -10
  67. package/src/reply-chunks.test.ts +0 -180
  68. package/src/reply-chunks.ts +0 -110
  69. package/src/reply-payload-transform.test.ts +0 -392
  70. package/src/reply-payload-transform.ts +0 -317
  71. package/src/rich-menu.test.ts +0 -315
  72. package/src/rich-menu.ts +0 -326
  73. package/src/runtime.ts +0 -32
  74. package/src/send-receipt.ts +0 -32
  75. package/src/send.test.ts +0 -453
  76. package/src/send.ts +0 -531
  77. package/src/setup-core.ts +0 -149
  78. package/src/setup-runtime-api.ts +0 -9
  79. package/src/setup-surface.test.ts +0 -481
  80. package/src/setup-surface.ts +0 -229
  81. package/src/signature.test.ts +0 -34
  82. package/src/signature.ts +0 -24
  83. package/src/status.ts +0 -37
  84. package/src/template-messages.ts +0 -333
  85. package/src/types.ts +0 -130
  86. package/src/webhook-node.test.ts +0 -598
  87. package/src/webhook-node.ts +0 -155
  88. package/src/webhook-utils.ts +0 -10
  89. package/src/webhook.ts +0 -135
  90. package/tsconfig.json +0 -16
@@ -1,499 +0,0 @@
1
- import crypto from "node:crypto";
2
- import { EventEmitter } from "node:events";
3
- import type { IncomingMessage, ServerResponse } from "node:http";
4
- import type { KlawConfig } from "klaw/plugin-sdk/config-contracts";
5
- import type { RuntimeEnv } from "klaw/plugin-sdk/runtime-env";
6
- import { createMockIncomingRequest } from "klaw/plugin-sdk/test-env";
7
- import { WEBHOOK_IN_FLIGHT_DEFAULTS } from "klaw/plugin-sdk/webhook-request-guards";
8
- import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
9
-
10
- type LineNodeWebhookHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
11
-
12
- const {
13
- createLineBotMock,
14
- createLineNodeWebhookHandlerMock,
15
- registerWebhookTargetWithPluginRouteMock,
16
- unregisterHttpMock,
17
- } = vi.hoisted(() => ({
18
- createLineBotMock: vi.fn(() => ({
19
- account: { accountId: "default" },
20
- handleWebhook: vi.fn(),
21
- })),
22
- createLineNodeWebhookHandlerMock: vi.fn<() => LineNodeWebhookHandler>(() =>
23
- vi.fn<LineNodeWebhookHandler>(async () => {}),
24
- ),
25
- registerWebhookTargetWithPluginRouteMock: vi.fn(),
26
- unregisterHttpMock: vi.fn(),
27
- }));
28
-
29
- let monitorLineProvider: typeof import("./monitor.js").monitorLineProvider;
30
- let getLineRuntimeState: typeof import("./monitor.js").getLineRuntimeState;
31
- let clearLineRuntimeStateForTests: typeof import("./monitor.js").clearLineRuntimeStateForTests;
32
- let innerLineWebhookHandlerMock: ReturnType<typeof vi.fn<LineNodeWebhookHandler>>;
33
-
34
- type RegisteredRoute = {
35
- accountId?: string;
36
- auth?: string;
37
- handler?: LineNodeWebhookHandler;
38
- path?: string;
39
- pluginId?: string;
40
- replaceExisting?: boolean;
41
- };
42
-
43
- type RegisteredTarget = {
44
- accountId?: string;
45
- path: string;
46
- };
47
-
48
- type WebhookRegistration = {
49
- route: RegisteredRoute;
50
- target: RegisteredTarget;
51
- };
52
-
53
- function requireWebhookRegistration(): WebhookRegistration {
54
- const registration = registerWebhookTargetWithPluginRouteMock.mock.calls[0]?.[0] as
55
- | WebhookRegistration
56
- | undefined;
57
- if (!registration) {
58
- throw new Error("expected registered LINE webhook target");
59
- }
60
- return registration;
61
- }
62
-
63
- function requireRegisteredRoute(): { handler: LineNodeWebhookHandler } {
64
- const route = requireWebhookRegistration().route;
65
- if (!route.handler) {
66
- throw new Error("expected registered LINE webhook route");
67
- }
68
- return { handler: route.handler };
69
- }
70
-
71
- vi.mock("./bot.js", () => ({
72
- createLineBot: createLineBotMock,
73
- }));
74
-
75
- vi.mock("klaw/plugin-sdk/reply-runtime", () => ({
76
- chunkMarkdownText: vi.fn(),
77
- dispatchReplyWithBufferedBlockDispatcher: vi.fn(),
78
- }));
79
-
80
- vi.mock("klaw/plugin-sdk/runtime-env", async () => {
81
- const actual = await vi.importActual<typeof import("klaw/plugin-sdk/runtime-env")>(
82
- "klaw/plugin-sdk/runtime-env",
83
- );
84
- return {
85
- ...actual,
86
- danger: (value: unknown) => String(value),
87
- logVerbose: vi.fn(),
88
- waitForAbortSignal: vi.fn(),
89
- };
90
- });
91
-
92
- vi.mock("klaw/plugin-sdk/channel-message", () => ({
93
- createChannelMessageReplyPipeline: vi.fn(() => ({})),
94
- hasFinalChannelTurnDispatch: vi.fn(() => false),
95
- }));
96
-
97
- vi.mock("klaw/plugin-sdk/webhook-ingress", async () => {
98
- const actual = await vi.importActual<typeof import("klaw/plugin-sdk/webhook-ingress")>(
99
- "klaw/plugin-sdk/webhook-ingress",
100
- );
101
- return {
102
- ...actual,
103
- normalizePluginHttpPath: (path: string | undefined, fallback: string) => path ?? fallback,
104
- registerWebhookTargetWithPluginRoute: registerWebhookTargetWithPluginRouteMock,
105
- };
106
- });
107
-
108
- vi.mock("./webhook-node.js", async () => {
109
- const actual = await vi.importActual<typeof import("./webhook-node.js")>("./webhook-node.js");
110
- return {
111
- ...actual,
112
- createLineNodeWebhookHandler: createLineNodeWebhookHandlerMock,
113
- };
114
- });
115
-
116
- vi.mock("./auto-reply-delivery.js", () => ({
117
- deliverLineAutoReply: vi.fn(),
118
- }));
119
-
120
- vi.mock("./markdown-to-line.js", () => ({
121
- processLineMessage: vi.fn(),
122
- }));
123
-
124
- vi.mock("./reply-chunks.js", () => ({
125
- sendLineReplyChunks: vi.fn(),
126
- }));
127
-
128
- vi.mock("./send.js", () => ({
129
- createFlexMessage: vi.fn(),
130
- createImageMessage: vi.fn(),
131
- createLocationMessage: vi.fn(),
132
- createQuickReplyItems: vi.fn(),
133
- createTextMessageWithQuickReplies: vi.fn(),
134
- getUserDisplayName: vi.fn(),
135
- pushMessageLine: vi.fn(),
136
- pushMessagesLine: vi.fn(),
137
- pushTextMessageWithQuickReplies: vi.fn(),
138
- replyMessageLine: vi.fn(),
139
- showLoadingAnimation: vi.fn(),
140
- }));
141
-
142
- vi.mock("./template-messages.js", () => ({
143
- buildTemplateMessageFromPayload: vi.fn(),
144
- }));
145
-
146
- describe("monitorLineProvider lifecycle", () => {
147
- beforeAll(async () => {
148
- ({ monitorLineProvider, getLineRuntimeState, clearLineRuntimeStateForTests } =
149
- await import("./monitor.js"));
150
- });
151
-
152
- afterAll(() => {
153
- vi.doUnmock("./bot.js");
154
- vi.doUnmock("klaw/plugin-sdk/reply-runtime");
155
- vi.doUnmock("klaw/plugin-sdk/runtime-env");
156
- vi.doUnmock("klaw/plugin-sdk/channel-message");
157
- vi.doUnmock("klaw/plugin-sdk/webhook-ingress");
158
- vi.doUnmock("./webhook-node.js");
159
- vi.doUnmock("./auto-reply-delivery.js");
160
- vi.doUnmock("./markdown-to-line.js");
161
- vi.doUnmock("./reply-chunks.js");
162
- vi.doUnmock("./send.js");
163
- vi.doUnmock("./template-messages.js");
164
- vi.resetModules();
165
- });
166
-
167
- beforeEach(() => {
168
- clearLineRuntimeStateForTests();
169
- createLineBotMock.mockReset();
170
- createLineBotMock.mockImplementation(() => ({
171
- account: { accountId: "default" },
172
- handleWebhook: vi.fn(),
173
- }));
174
- innerLineWebhookHandlerMock = vi.fn<LineNodeWebhookHandler>(async () => {});
175
- createLineNodeWebhookHandlerMock
176
- .mockReset()
177
- .mockImplementation(() => innerLineWebhookHandlerMock);
178
- unregisterHttpMock.mockReset();
179
- registerWebhookTargetWithPluginRouteMock.mockReset().mockImplementation((params) => {
180
- const key = params.target.path.startsWith("/")
181
- ? params.target.path
182
- : `/${params.target.path}`;
183
- const normalizedTarget = { ...params.target, path: key };
184
- const existing = params.targetsByPath.get(key) ?? [];
185
- params.targetsByPath.set(key, [...existing, normalizedTarget]);
186
- return {
187
- target: normalizedTarget,
188
- unregister: () => {
189
- unregisterHttpMock();
190
- const updated = (params.targetsByPath.get(key) ?? []).filter(
191
- (entry: unknown) => entry !== normalizedTarget,
192
- );
193
- if (updated.length > 0) {
194
- params.targetsByPath.set(key, updated);
195
- } else {
196
- params.targetsByPath.delete(key);
197
- }
198
- },
199
- };
200
- });
201
- });
202
-
203
- afterEach(() => {
204
- clearLineRuntimeStateForTests();
205
- });
206
-
207
- const createRouteResponse = () => {
208
- const resObj = {
209
- statusCode: 0,
210
- headersSent: false,
211
- setHeader: vi.fn(),
212
- end: vi.fn(() => {
213
- resObj.headersSent = true;
214
- }),
215
- };
216
- return resObj as unknown as ServerResponse & { end: ReturnType<typeof vi.fn> };
217
- };
218
-
219
- it("waits for abort before resolving", async () => {
220
- const abort = new AbortController();
221
- let resolved = false;
222
-
223
- const task = monitorLineProvider({
224
- channelAccessToken: "token",
225
- channelSecret: "secret", // pragma: allowlist secret
226
- config: {} as KlawConfig,
227
- runtime: {} as RuntimeEnv,
228
- abortSignal: abort.signal,
229
- }).then((monitor) => {
230
- resolved = true;
231
- return monitor;
232
- });
233
-
234
- expect(registerWebhookTargetWithPluginRouteMock).toHaveBeenCalledTimes(1);
235
- expect(requireWebhookRegistration().route.auth).toBe("plugin");
236
- expect(resolved).toBe(false);
237
-
238
- abort.abort();
239
- await task;
240
- expect(unregisterHttpMock).toHaveBeenCalledTimes(1);
241
- });
242
-
243
- it("registers an account target without replacing existing route ownership", async () => {
244
- const monitor = await monitorLineProvider({
245
- channelAccessToken: "token",
246
- channelSecret: "secret", // pragma: allowlist secret
247
- accountId: "work",
248
- config: {} as KlawConfig,
249
- runtime: {} as RuntimeEnv,
250
- });
251
-
252
- const registration = requireWebhookRegistration();
253
- expect(registration.target.accountId).toBe("work");
254
- expect(registration.target.path).toBe("/line/webhook");
255
- expect(registration.route.accountId).toBe("work");
256
- expect(registration.route.auth).toBe("plugin");
257
- expect(registration.route.pluginId).toBe("line");
258
- expect(registration.route).not.toHaveProperty("path");
259
- expect(registration.route).not.toHaveProperty("replaceExisting");
260
- monitor.stop();
261
- });
262
-
263
- it("stops immediately when signal is already aborted", async () => {
264
- const abort = new AbortController();
265
- abort.abort();
266
-
267
- await monitorLineProvider({
268
- channelAccessToken: "token",
269
- channelSecret: "secret", // pragma: allowlist secret
270
- config: {} as KlawConfig,
271
- runtime: {} as RuntimeEnv,
272
- abortSignal: abort.signal,
273
- });
274
-
275
- expect(unregisterHttpMock).toHaveBeenCalledTimes(1);
276
- });
277
-
278
- it("returns immediately without abort signal and stop is idempotent", async () => {
279
- const monitor = await monitorLineProvider({
280
- channelAccessToken: "token",
281
- channelSecret: "secret", // pragma: allowlist secret
282
- config: {} as KlawConfig,
283
- runtime: {} as RuntimeEnv,
284
- });
285
-
286
- expect(unregisterHttpMock).not.toHaveBeenCalled();
287
- monitor.stop();
288
- monitor.stop();
289
- expect(unregisterHttpMock).toHaveBeenCalledTimes(1);
290
- });
291
-
292
- it("records startup state under configured defaultAccount when accountId is omitted", async () => {
293
- const monitor = await monitorLineProvider({
294
- channelAccessToken: "token",
295
- channelSecret: "secret", // pragma: allowlist secret
296
- config: {
297
- channels: {
298
- line: {
299
- defaultAccount: "work",
300
- accounts: {
301
- work: {
302
- channelAccessToken: "work-token",
303
- channelSecret: "work-secret",
304
- },
305
- },
306
- },
307
- },
308
- } as KlawConfig,
309
- runtime: {} as RuntimeEnv,
310
- });
311
-
312
- expect(getLineRuntimeState("work")?.running).toBe(true);
313
- expect(getLineRuntimeState("default")).toBeUndefined();
314
-
315
- monitor.stop();
316
- });
317
-
318
- it("dispatches shared-path webhook posts to the account matching the signature", async () => {
319
- const firstMonitor = await monitorLineProvider({
320
- channelAccessToken: "first-token",
321
- channelSecret: "first-secret", // pragma: allowlist secret
322
- accountId: "first",
323
- config: {} as KlawConfig,
324
- runtime: {} as RuntimeEnv,
325
- });
326
- const secondMonitor = await monitorLineProvider({
327
- channelAccessToken: "second-token",
328
- channelSecret: "second-secret", // pragma: allowlist secret
329
- accountId: "second",
330
- config: {} as KlawConfig,
331
- runtime: {} as RuntimeEnv,
332
- });
333
-
334
- const route = requireRegisteredRoute();
335
-
336
- const payload = JSON.stringify({ events: [{ type: "message" }] });
337
- const signature = crypto.createHmac("SHA256", "second-secret").update(payload).digest("base64");
338
- const req = Object.assign(createMockIncomingRequest([payload]), {
339
- method: "POST",
340
- headers: { "x-line-signature": signature },
341
- }) as unknown as IncomingMessage;
342
- const res = createRouteResponse();
343
-
344
- await route.handler(req, res);
345
-
346
- const firstBot = createLineBotMock.mock.results[0]?.value as {
347
- handleWebhook: ReturnType<typeof vi.fn>;
348
- };
349
- const secondBot = createLineBotMock.mock.results[1]?.value as {
350
- handleWebhook: ReturnType<typeof vi.fn>;
351
- };
352
- expect(res.statusCode).toBe(200);
353
- expect(firstBot.handleWebhook).not.toHaveBeenCalled();
354
- expect(secondBot.handleWebhook).toHaveBeenCalledTimes(1);
355
-
356
- firstMonitor.stop();
357
- secondMonitor.stop();
358
- });
359
-
360
- it("acknowledges shared-path POST requests before matched event processing completes", async () => {
361
- const monitor = await monitorLineProvider({
362
- channelAccessToken: "token",
363
- channelSecret: "secret", // pragma: allowlist secret
364
- accountId: "default",
365
- config: {} as KlawConfig,
366
- runtime: {} as RuntimeEnv,
367
- });
368
-
369
- let releaseWebhook: (() => void) | undefined;
370
- const bot = createLineBotMock.mock.results[0]?.value as {
371
- handleWebhook: ReturnType<typeof vi.fn>;
372
- };
373
- bot.handleWebhook.mockImplementation(
374
- async () =>
375
- await new Promise<void>((resolve) => {
376
- releaseWebhook = resolve;
377
- }),
378
- );
379
-
380
- const route = requireRegisteredRoute();
381
- const payload = JSON.stringify({ events: [{ type: "message" }] });
382
- const signature = crypto.createHmac("SHA256", "secret").update(payload).digest("base64");
383
- const req = Object.assign(createMockIncomingRequest([payload]), {
384
- method: "POST",
385
- headers: { "x-line-signature": signature },
386
- }) as unknown as IncomingMessage;
387
- const res = createRouteResponse();
388
-
389
- await route.handler(req, res);
390
-
391
- expect(res.statusCode).toBe(200);
392
- expect(res.headersSent).toBe(true);
393
- expect(bot.handleWebhook).toHaveBeenCalledTimes(1);
394
- if (!releaseWebhook) {
395
- throw new Error("expected pending LINE webhook handler");
396
- }
397
- releaseWebhook();
398
- monitor.stop();
399
- });
400
-
401
- it("rejects ambiguous shared-path webhook signatures", async () => {
402
- const firstMonitor = await monitorLineProvider({
403
- channelAccessToken: "first-token",
404
- channelSecret: "shared-secret", // pragma: allowlist secret
405
- accountId: "first",
406
- config: {} as KlawConfig,
407
- runtime: {} as RuntimeEnv,
408
- });
409
- const secondMonitor = await monitorLineProvider({
410
- channelAccessToken: "second-token",
411
- channelSecret: "shared-secret", // pragma: allowlist secret
412
- accountId: "second",
413
- config: {} as KlawConfig,
414
- runtime: {} as RuntimeEnv,
415
- });
416
-
417
- const route = requireRegisteredRoute();
418
-
419
- const payload = JSON.stringify({ events: [{ type: "message" }] });
420
- const signature = crypto.createHmac("SHA256", "shared-secret").update(payload).digest("base64");
421
- const req = Object.assign(createMockIncomingRequest([payload]), {
422
- method: "POST",
423
- headers: { "x-line-signature": signature },
424
- }) as unknown as IncomingMessage;
425
- const res = createRouteResponse();
426
-
427
- await route.handler(req, res);
428
-
429
- const firstBot = createLineBotMock.mock.results[0]?.value as {
430
- handleWebhook: ReturnType<typeof vi.fn>;
431
- };
432
- const secondBot = createLineBotMock.mock.results[1]?.value as {
433
- handleWebhook: ReturnType<typeof vi.fn>;
434
- };
435
- expect(res.statusCode).toBe(401);
436
- expect(res.end).toHaveBeenCalledWith(JSON.stringify({ error: "Ambiguous webhook target" }));
437
- expect(firstBot.handleWebhook).not.toHaveBeenCalled();
438
- expect(secondBot.handleWebhook).not.toHaveBeenCalled();
439
-
440
- firstMonitor.stop();
441
- secondMonitor.stop();
442
- });
443
-
444
- it("rejects webhook requests above the shared in-flight limit before body handling", async () => {
445
- const limit = WEBHOOK_IN_FLIGHT_DEFAULTS.maxInFlightPerKey;
446
- const heldRequests: Array<EventEmitter & { destroy: () => void }> = [];
447
-
448
- const monitor = await monitorLineProvider({
449
- channelAccessToken: "token",
450
- channelSecret: "secret", // pragma: allowlist secret
451
- config: {} as KlawConfig,
452
- runtime: {} as RuntimeEnv,
453
- });
454
-
455
- const route = requireRegisteredRoute();
456
- const createHeldPostRequest = () => {
457
- const req = Object.assign(new EventEmitter(), {
458
- destroyed: false,
459
- destroy(this: EventEmitter & { destroyed: boolean }) {
460
- this.destroyed = true;
461
- this.emit("close");
462
- },
463
- });
464
- heldRequests.push(req);
465
- return Object.assign(req, {
466
- method: "POST",
467
- headers: { "x-line-signature": "pending" },
468
- }) as unknown as IncomingMessage;
469
- };
470
- const createSignedPostRequest = () => {
471
- const payload = JSON.stringify({ events: [{ type: "message" }] });
472
- const signature = crypto.createHmac("SHA256", "secret").update(payload).digest("base64");
473
- const req = createMockIncomingRequest([payload]);
474
- return Object.assign(req, {
475
- method: "POST",
476
- headers: { "x-line-signature": signature },
477
- }) as unknown as IncomingMessage;
478
- };
479
-
480
- const firstRequests = Array.from({ length: limit }, () =>
481
- route.handler(createHeldPostRequest(), createRouteResponse()),
482
- );
483
- await new Promise((resolve) => setImmediate(resolve));
484
-
485
- const overflowResponse = createRouteResponse();
486
- await route.handler(createSignedPostRequest(), overflowResponse);
487
-
488
- const bot = createLineBotMock.mock.results[0]?.value as {
489
- handleWebhook: ReturnType<typeof vi.fn>;
490
- };
491
- expect(bot.handleWebhook).not.toHaveBeenCalled();
492
- expect(overflowResponse.statusCode).toBe(429);
493
- expect(overflowResponse.end).toHaveBeenCalledWith("Too Many Requests");
494
-
495
- heldRequests.splice(0).forEach((req) => req.destroy());
496
- await Promise.allSettled(firstRequests);
497
- monitor.stop();
498
- });
499
- });
@@ -1 +0,0 @@
1
- export { monitorLineProvider } from "./monitor.js";