@zhin.js/adapter-line 0.1.0

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.
@@ -0,0 +1,532 @@
1
+ /**
2
+ * LINE Endpoint 实现
3
+ *
4
+ * 使用 Webhook 模式接收消息,通过 LINE Messaging API 发送消息。
5
+ * HMAC-SHA256 签名验证确保请求来自 LINE 平台。
6
+ */
7
+ import { createHmac, timingSafeEqual } from "node:crypto";
8
+ import { Message, segment, formatCompact, } from "zhin.js";
9
+ import { registerFetchRoute } from "@zhin.js/host-router/router";
10
+ /** Type guard: narrows a LineEvent to a message event */
11
+ function isMessageEvent(e) {
12
+ return e.type === "message" && "message" in e && e.message != null;
13
+ }
14
+ /** Type guard: narrows a LineEvent to a postback event */
15
+ function isPostbackEvent(e) {
16
+ return e.type === "postback" && "postback" in e;
17
+ }
18
+ export class LineEndpoint {
19
+ adapter;
20
+ router;
21
+ $config;
22
+ $connected = false;
23
+ get pluginLogger() {
24
+ return this.adapter.plugin.logger;
25
+ }
26
+ get $id() {
27
+ return this.$config.name;
28
+ }
29
+ constructor(adapter, router, $config) {
30
+ this.adapter = adapter;
31
+ this.router = router;
32
+ this.$config = $config;
33
+ }
34
+ async $connect() {
35
+ try {
36
+ const path = this.$config.webhookPath || "/line/webhook";
37
+ const cleanPath = path.startsWith("/") ? path : `/${path}`;
38
+ registerFetchRoute(this.router, "POST", cleanPath, async (ctx) => {
39
+ await this.handleWebhook(ctx);
40
+ });
41
+ this.$connected = true;
42
+ this.pluginLogger.info(formatCompact({ op: "webhook", path: cleanPath }));
43
+ }
44
+ catch (error) {
45
+ this.pluginLogger.error("Failed to connect LINE endpoint:", error);
46
+ this.$connected = false;
47
+ throw error;
48
+ }
49
+ }
50
+ async $disconnect() {
51
+ try {
52
+ this.$connected = false;
53
+ this.replyTokenCache.clear();
54
+ this.pluginLogger.info(`LINE endpoint ${this.$config.name} disconnected`);
55
+ }
56
+ catch (error) {
57
+ this.pluginLogger.error("Error disconnecting LINE endpoint:", error);
58
+ // L02: Log and swallow instead of re-throwing
59
+ }
60
+ }
61
+ // ── Webhook 处理 ────────────────────────────────────────────────────
62
+ async handleWebhook(ctx) {
63
+ try {
64
+ // 1. 签名验证
65
+ const signature = ctx.get("x-line-signature");
66
+ if (!signature) {
67
+ ctx.status = 403;
68
+ ctx.body = { message: "Missing signature" };
69
+ return;
70
+ }
71
+ // L05: 获取原始请求体用于签名验证
72
+ // Koa ctx.req 是 Node.js IncomingMessage,koa-body 可能已经消费了流
73
+ // 因此优先使用已解析的 body 并序列化,记录警告说明可能不精确
74
+ let rawBody;
75
+ if (typeof ctx.request.body === "string") {
76
+ rawBody = ctx.request.body;
77
+ }
78
+ else {
79
+ rawBody = JSON.stringify(ctx.request.body);
80
+ this.pluginLogger.debug("Signature verification using JSON.stringify(body) — may differ from original raw body");
81
+ }
82
+ if (!this.verifySignature(rawBody, signature)) {
83
+ this.pluginLogger.warn(formatCompact({ op: "webhook", ok: false, error: "invalid signature" }));
84
+ ctx.status = 403;
85
+ ctx.body = { message: "Invalid signature" };
86
+ return;
87
+ }
88
+ // 2. 解析事件
89
+ const body = typeof ctx.request.body === "string"
90
+ ? JSON.parse(ctx.request.body)
91
+ : ctx.request.body;
92
+ if (!body.events || !Array.isArray(body.events)) {
93
+ ctx.status = 200;
94
+ ctx.body = { message: "OK" };
95
+ return;
96
+ }
97
+ // 3. 处理每个事件
98
+ for (const event of body.events) {
99
+ await this.handleEvent(event);
100
+ }
101
+ ctx.status = 200;
102
+ ctx.body = { message: "OK" };
103
+ }
104
+ catch (error) {
105
+ this.pluginLogger.error("LINE webhook error:", error);
106
+ ctx.status = 200;
107
+ ctx.body = { message: "OK" };
108
+ }
109
+ }
110
+ // L07: Use timing-safe comparison for signature
111
+ verifySignature(body, signature) {
112
+ const channelSecret = this.$config.channelSecret;
113
+ const hmac = createHmac("sha256", channelSecret);
114
+ hmac.update(body, "utf-8");
115
+ const computedSignature = hmac.digest("base64");
116
+ const sigBuf = Buffer.from(signature);
117
+ const computedBuf = Buffer.from(computedSignature);
118
+ if (sigBuf.length !== computedBuf.length)
119
+ return false;
120
+ return timingSafeEqual(sigBuf, computedBuf);
121
+ }
122
+ // L04: Use type guards instead of "in" checks + `as any` casts
123
+ async handleEvent(event) {
124
+ switch (event.type) {
125
+ case "message":
126
+ if (isMessageEvent(event)) {
127
+ await this.handleMessageEvent(event);
128
+ }
129
+ break;
130
+ case "follow":
131
+ await this.handleFollowEvent(event);
132
+ break;
133
+ case "unfollow":
134
+ this.pluginLogger.debug(formatCompact({
135
+ op: "unfollow",
136
+ endpoint: this.$config.name,
137
+ userId: event.source.userId,
138
+ }));
139
+ break;
140
+ case "join":
141
+ await this.handleJoinEvent(event);
142
+ break;
143
+ case "leave":
144
+ this.pluginLogger.debug(formatCompact({
145
+ op: "leave",
146
+ endpoint: this.$config.name,
147
+ sourceType: event.source.type,
148
+ groupId: event.source.groupId,
149
+ roomId: event.source.roomId,
150
+ }));
151
+ break;
152
+ case "postback":
153
+ if (isPostbackEvent(event)) {
154
+ this.pluginLogger.debug(formatCompact({
155
+ op: "postback",
156
+ endpoint: this.$config.name,
157
+ data: event.postback.data,
158
+ }));
159
+ }
160
+ break;
161
+ default:
162
+ this.pluginLogger.debug(formatCompact({
163
+ op: "unknown_event",
164
+ endpoint: this.$config.name,
165
+ type: event.type,
166
+ }));
167
+ }
168
+ }
169
+ // L01: Cache replyToken from webhook events before emitting
170
+ async handleMessageEvent(event) {
171
+ const { channelId } = this.resolveChannel(event.source);
172
+ this.cacheReplyToken(channelId, event.replyToken);
173
+ const message = this.$formatMessage(event);
174
+ this.adapter.emit("message.receive", message);
175
+ this.pluginLogger.debug(formatCompact({
176
+ op: "recv",
177
+ endpoint: this.$config.name,
178
+ channel: message.$channel.type,
179
+ id: message.$channel.id,
180
+ len: segment.raw(message.$content).length,
181
+ }));
182
+ }
183
+ async handleFollowEvent(event) {
184
+ const { channelId } = this.resolveChannel(event.source);
185
+ this.cacheReplyToken(channelId, event.replyToken);
186
+ const message = this.$formatMessage(event);
187
+ this.adapter.emit("message.receive", message);
188
+ this.pluginLogger.debug(formatCompact({
189
+ op: "follow",
190
+ endpoint: this.$config.name,
191
+ userId: event.source.userId,
192
+ }));
193
+ }
194
+ async handleJoinEvent(event) {
195
+ const { channelId } = this.resolveChannel(event.source);
196
+ this.cacheReplyToken(channelId, event.replyToken);
197
+ const message = this.$formatMessage(event);
198
+ this.adapter.emit("message.receive", message);
199
+ this.pluginLogger.debug(formatCompact({
200
+ op: "join",
201
+ endpoint: this.$config.name,
202
+ sourceType: event.source.type,
203
+ groupId: event.source.groupId,
204
+ roomId: event.source.roomId,
205
+ }));
206
+ }
207
+ // ── 消息格式化 ────────────────────────────────────────────────────
208
+ $formatMessage(event) {
209
+ const { channelType, channelId } = this.resolveChannel(event.source);
210
+ const content = this.parseMessageContent(event);
211
+ const quoteId = Message.quoteIdFromContent(content);
212
+ Message.alignReplySegments(content, quoteId);
213
+ const userId = event.source.userId || "";
214
+ const timestamp = event.timestamp || Date.now();
215
+ const rawText = this.extractRawText(event);
216
+ return Message.from(event, {
217
+ $id: this.generateMessageId(event),
218
+ $adapter: "line",
219
+ $endpoint: this.$config.name,
220
+ $sender: {
221
+ id: userId,
222
+ name: userId,
223
+ },
224
+ $channel: {
225
+ id: channelId,
226
+ type: channelType,
227
+ },
228
+ $content: content,
229
+ $quote_id: quoteId,
230
+ $raw: rawText,
231
+ $timestamp: timestamp,
232
+ $recall: async () => {
233
+ // LINE 不支持消息撤回
234
+ this.pluginLogger.warn("LINE does not support message recall");
235
+ },
236
+ $reply: async (content, quote) => {
237
+ if (!Array.isArray(content))
238
+ content = [content];
239
+ if (quote) {
240
+ const replyToMessageId = typeof quote === "boolean"
241
+ ? (isMessageEvent(event) && event.message?.id) || ""
242
+ : quote;
243
+ content.unshift({ type: "reply", data: { id: replyToMessageId } });
244
+ }
245
+ return await this.adapter.sendMessage({
246
+ context: "line",
247
+ endpoint: this.$config.name,
248
+ id: channelId,
249
+ type: channelType,
250
+ content: content,
251
+ });
252
+ },
253
+ });
254
+ }
255
+ generateMessageId(event) {
256
+ if (isMessageEvent(event) && event.message?.id) {
257
+ return event.message.id;
258
+ }
259
+ return `${event.type}-${event.timestamp}`;
260
+ }
261
+ resolveChannel(source) {
262
+ switch (source.type) {
263
+ case "user":
264
+ return { channelType: "private", channelId: source.userId || "" };
265
+ case "group":
266
+ return { channelType: "group", channelId: source.groupId || "" };
267
+ case "room":
268
+ return { channelType: "channel", channelId: source.roomId || "" };
269
+ default:
270
+ return { channelType: "private", channelId: "" };
271
+ }
272
+ }
273
+ extractRawText(event) {
274
+ if (isMessageEvent(event)) {
275
+ const msg = event.message;
276
+ if (msg.type === "text" && msg.text)
277
+ return msg.text;
278
+ if (msg.type === "location" && msg.address)
279
+ return msg.address;
280
+ return `[${msg.type}]`;
281
+ }
282
+ if (event.type === "follow")
283
+ return "[follow]";
284
+ if (event.type === "join")
285
+ return "[join]";
286
+ return "";
287
+ }
288
+ parseMessageContent(event) {
289
+ const segments = [];
290
+ if (isMessageEvent(event)) {
291
+ const msg = event.message;
292
+ switch (msg.type) {
293
+ case "text":
294
+ if (msg.text) {
295
+ segments.push({ type: "text", data: { text: msg.text } });
296
+ }
297
+ break;
298
+ case "image":
299
+ segments.push({
300
+ type: "image",
301
+ data: {
302
+ message_id: msg.id,
303
+ platform: "line",
304
+ },
305
+ });
306
+ break;
307
+ case "video":
308
+ segments.push({
309
+ type: "video",
310
+ data: {
311
+ message_id: msg.id,
312
+ platform: "line",
313
+ },
314
+ });
315
+ break;
316
+ case "audio":
317
+ segments.push({
318
+ type: "audio",
319
+ data: {
320
+ message_id: msg.id,
321
+ duration: msg.duration || 0,
322
+ platform: "line",
323
+ },
324
+ });
325
+ break;
326
+ case "file":
327
+ segments.push({
328
+ type: "file",
329
+ data: {
330
+ message_id: msg.id,
331
+ file_name: msg.fileName,
332
+ file_size: msg.fileSize,
333
+ platform: "line",
334
+ },
335
+ });
336
+ break;
337
+ case "location":
338
+ segments.push({
339
+ type: "location",
340
+ data: {
341
+ title: msg.title,
342
+ address: msg.address,
343
+ latitude: msg.latitude,
344
+ longitude: msg.longitude,
345
+ },
346
+ });
347
+ break;
348
+ case "sticker":
349
+ segments.push({
350
+ type: "sticker",
351
+ data: {
352
+ package_id: msg.packageId,
353
+ sticker_id: msg.stickerId,
354
+ resource_type: msg.stickerResourceType,
355
+ },
356
+ });
357
+ break;
358
+ default:
359
+ segments.push({ type: "text", data: { text: `[unsupported message type]` } });
360
+ }
361
+ }
362
+ else {
363
+ // 系统事件(follow/unfollow/join/leave)
364
+ const text = event.type === "follow" ? "[follow event]"
365
+ : event.type === "join" ? "[join event]"
366
+ : event.type === "unfollow" ? "[unfollow event]"
367
+ : event.type === "leave" ? "[leave event]"
368
+ : `[${event.type} event]`;
369
+ segments.push({ type: "text", data: { text } });
370
+ }
371
+ return segments.length > 0 ? segments : [{ type: "text", data: { text: "" } }];
372
+ }
373
+ // ── 发送消息 ──────────────────────────────────────────────────────
374
+ async $sendMessage(options) {
375
+ try {
376
+ const messages = this.buildLineMessages(options.content);
377
+ if (messages.length === 0) {
378
+ throw new Error("No valid LINE messages to send");
379
+ }
380
+ // 优先使用 Reply API(如果存在 replyToken)
381
+ const replyToken = this.replyTokenCache.get(options.id);
382
+ if (replyToken) {
383
+ this.replyTokenCache.delete(options.id);
384
+ return await this.replyMessage(replyToken, messages);
385
+ }
386
+ // L06: Validate Push API `to` field
387
+ if (!/^[UGR]/.test(options.id)) {
388
+ throw new Error(`Invalid LINE recipient ID "${options.id}": must start with U (user), G (group), or R (room)`);
389
+ }
390
+ // 使用 Push API
391
+ return await this.pushMessage(options.id, messages);
392
+ }
393
+ catch (error) {
394
+ this.pluginLogger.error("Failed to send LINE message:", error);
395
+ throw error;
396
+ }
397
+ }
398
+ replyTokenCache = new Map();
399
+ /**
400
+ * 缓存 replyToken,用于后续发送回复消息
401
+ */
402
+ cacheReplyToken(channelId, replyToken) {
403
+ this.replyTokenCache.set(channelId, replyToken);
404
+ }
405
+ // L15: Parse Reply API response for message ID
406
+ async replyMessage(replyToken, messages) {
407
+ const baseUrl = this.$config.apiBaseUrl || "https://api.line.me";
408
+ const request = { replyToken, messages };
409
+ const response = await fetch(`${baseUrl}/v2/bot/message/reply`, {
410
+ method: "POST",
411
+ headers: {
412
+ "Content-Type": "application/json",
413
+ "Authorization": `Bearer ${this.$config.channelAccessToken}`,
414
+ },
415
+ body: JSON.stringify(request),
416
+ });
417
+ if (!response.ok) {
418
+ const errorText = await response.text();
419
+ throw new Error(`LINE Reply API error ${response.status}: ${errorText}`);
420
+ }
421
+ // Reply API now returns sentMessages in the response body
422
+ const result = await response.json();
423
+ return result.sentMessages?.[0]?.id || `reply-${Date.now()}`;
424
+ }
425
+ async pushMessage(to, messages) {
426
+ const baseUrl = this.$config.apiBaseUrl || "https://api.line.me";
427
+ const request = { to, messages };
428
+ const response = await fetch(`${baseUrl}/v2/bot/message/push`, {
429
+ method: "POST",
430
+ headers: {
431
+ "Content-Type": "application/json",
432
+ "Authorization": `Bearer ${this.$config.channelAccessToken}`,
433
+ },
434
+ body: JSON.stringify(request),
435
+ });
436
+ if (!response.ok) {
437
+ const errorText = await response.text();
438
+ throw new Error(`LINE Push API error ${response.status}: ${errorText}`);
439
+ }
440
+ const result = await response.json();
441
+ return result.sentMessages?.[0]?.id || `push-${Date.now()}`;
442
+ }
443
+ buildLineMessages(content) {
444
+ if (!Array.isArray(content))
445
+ content = [content];
446
+ const messages = [];
447
+ for (const item of content) {
448
+ if (typeof item === "string") {
449
+ messages.push(this.buildTextMessage(item));
450
+ continue;
451
+ }
452
+ const seg = item;
453
+ switch (seg.type) {
454
+ case "text":
455
+ messages.push(this.buildTextMessage(seg.data.text || ""));
456
+ break;
457
+ case "at":
458
+ // LINE 没有 @ 语法,转为文本
459
+ if (seg.data.id) {
460
+ messages.push(this.buildTextMessage(`@${seg.data.name || seg.data.id}`));
461
+ }
462
+ break;
463
+ case "image":
464
+ if (seg.data.url) {
465
+ messages.push({
466
+ type: "image",
467
+ originalContentUrl: seg.data.url,
468
+ previewImageUrl: seg.data.url,
469
+ });
470
+ }
471
+ break;
472
+ case "video":
473
+ if (seg.data.url) {
474
+ messages.push({
475
+ type: "video",
476
+ originalContentUrl: seg.data.url,
477
+ previewImageUrl: seg.data.previewUrl || seg.data.url,
478
+ });
479
+ }
480
+ break;
481
+ case "audio":
482
+ if (seg.data.url) {
483
+ messages.push({
484
+ type: "audio",
485
+ originalContentUrl: seg.data.url,
486
+ duration: seg.data.duration || 0,
487
+ });
488
+ }
489
+ break;
490
+ case "location":
491
+ messages.push({
492
+ type: "location",
493
+ title: seg.data.title || "Location",
494
+ address: seg.data.address || "",
495
+ latitude: seg.data.latitude || 0,
496
+ longitude: seg.data.longitude || 0,
497
+ });
498
+ break;
499
+ case "sticker":
500
+ messages.push({
501
+ type: "sticker",
502
+ packageId: seg.data.package_id || "1",
503
+ stickerId: seg.data.sticker_id || "1",
504
+ });
505
+ break;
506
+ default:
507
+ messages.push(this.buildTextMessage(`[${seg.type}]`));
508
+ }
509
+ }
510
+ // L14: Log warning when messages are sliced to 5 (LINE limit)
511
+ if (messages.length > 5) {
512
+ this.pluginLogger.warn(`LINE messages truncated from ${messages.length} to 5 (platform limit)`);
513
+ }
514
+ // LINE 单次最多发送 5 条消息
515
+ return messages.slice(0, 5);
516
+ }
517
+ buildTextMessage(text) {
518
+ // L13: Log warning on text truncation
519
+ if (text.length > 5000) {
520
+ this.pluginLogger.warn(`LINE text message truncated from ${text.length} to 5000 characters`);
521
+ }
522
+ // LINE 消息文本限制 5000 字符
523
+ const truncated = text.length > 5000 ? text.slice(0, 4997) + "..." : text;
524
+ return { type: "text", text: truncated };
525
+ }
526
+ // ── 消息撤回 ──────────────────────────────────────────────────────
527
+ // L16: Log warning and return gracefully (matching WeCom/DingTalk pattern)
528
+ async $recallMessage(_id) {
529
+ this.pluginLogger.warn(formatCompact({ op: "recall", ok: false, error: "LINE Messaging API does not support message recall" }));
530
+ }
531
+ }
532
+ //# sourceMappingURL=endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { LineAdapter } from './adapter.js';
2
+ declare module 'zhin.js' {
3
+ namespace Plugin {
4
+ interface Contexts {
5
+ router: import('@zhin.js/host-router').Router;
6
+ }
7
+ }
8
+ interface Adapters {
9
+ line: LineAdapter;
10
+ }
11
+ }
12
+ export * from './types.js';
13
+ export { LineEndpoint } from './endpoint.js';
14
+ export { LineAdapter } from './adapter.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,MAAM,CAAC;QACf,UAAU,QAAQ;YAChB,MAAM,EAAE,OAAO,sBAAsB,EAAE,MAAM,CAAC;SAC/C;KACF;IACD,UAAU,QAAQ;QAChB,IAAI,EAAE,WAAW,CAAC;KACnB;CACF;AAED,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * LINE Messaging API 适配器入口:类型扩展、导出、注册
3
+ */
4
+ import { usePlugin } from 'zhin.js';
5
+ import { LineAdapter } from './adapter.js';
6
+ export * from './types.js';
7
+ export { LineEndpoint } from './endpoint.js';
8
+ export { LineAdapter } from './adapter.js';
9
+ const plugin = usePlugin();
10
+ const { provide, useContext } = plugin;
11
+ useContext('router', (router) => {
12
+ provide({
13
+ name: 'line',
14
+ description: 'LINE Messaging API Endpoint Adapter',
15
+ mounted: async (p) => {
16
+ const adapter = new LineAdapter(p, router);
17
+ await adapter.start();
18
+ return adapter;
19
+ },
20
+ dispose: async (adapter) => {
21
+ await adapter.stop();
22
+ },
23
+ });
24
+ });
25
+ // L11: Register LINE-specific tools
26
+ useContext('tool', 'line', (toolService, lineAdapter) => {
27
+ const accessToken = lineAdapter.endpoints.values().next().value?.$config?.channelAccessToken;
28
+ const apiBaseUrl = lineAdapter.endpoints.values().next().value?.$config?.apiBaseUrl || 'https://api.line.me';
29
+ const disposers = [];
30
+ disposers.push(toolService.addTool({
31
+ name: 'line_get_profile',
32
+ description: 'Get LINE user profile by userId',
33
+ parameters: {
34
+ type: 'object',
35
+ properties: {
36
+ userId: { type: 'string', description: 'LINE user ID (starts with U)' },
37
+ },
38
+ required: ['userId'],
39
+ },
40
+ execute: async ({ userId }) => {
41
+ if (!userId.startsWith('U')) {
42
+ throw new Error(`Invalid userId "${userId}": must start with U`);
43
+ }
44
+ const response = await fetch(`${apiBaseUrl}/v2/profile/${userId}`, {
45
+ headers: { 'Authorization': `Bearer ${accessToken}` },
46
+ });
47
+ if (!response.ok) {
48
+ const errorText = await response.text();
49
+ throw new Error(`LINE Profile API error ${response.status}: ${errorText}`);
50
+ }
51
+ return await response.json();
52
+ },
53
+ }));
54
+ disposers.push(toolService.addTool({
55
+ name: 'line_get_group_members',
56
+ description: 'Get LINE group member IDs',
57
+ parameters: {
58
+ type: 'object',
59
+ properties: {
60
+ groupId: { type: 'string', description: 'LINE group ID (starts with G)' },
61
+ },
62
+ required: ['groupId'],
63
+ },
64
+ execute: async ({ groupId }) => {
65
+ if (!groupId.startsWith('G')) {
66
+ throw new Error(`Invalid groupId "${groupId}": must start with G`);
67
+ }
68
+ const response = await fetch(`${apiBaseUrl}/v2/bot/group/${groupId}/members/ids`, {
69
+ headers: { 'Authorization': `Bearer ${accessToken}` },
70
+ });
71
+ if (!response.ok) {
72
+ const errorText = await response.text();
73
+ throw new Error(`LINE Group Members API error ${response.status}: ${errorText}`);
74
+ }
75
+ return await response.json();
76
+ },
77
+ }));
78
+ return () => {
79
+ for (const disposer of disposers)
80
+ disposer();
81
+ };
82
+ });
83
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}