@kodelyth/line 2026.5.39 → 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.
@@ -0,0 +1,282 @@
1
+ import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-CD4A1FE7.js";
2
+ import { normalizeOptionalString } from "klaw/plugin-sdk/string-coerce-runtime";
3
+ import { DEFAULT_ACCOUNT_ID, createAllowFromSection, createSetupInputPresenceValidator, createSetupTranslator, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, setSetupChannelEnabled, splitSetupEntries } from "klaw/plugin-sdk/setup";
4
+ //#region extensions/line/src/account-helpers.ts
5
+ function hasLineCredentials(account) {
6
+ return Boolean(account.channelAccessToken?.trim() && account.channelSecret?.trim());
7
+ }
8
+ function parseLineAllowFromId(raw) {
9
+ const trimmed = raw.trim().replace(/^line:(?:user:)?/i, "");
10
+ if (!/^U[a-f0-9]{32}$/i.test(trimmed)) return null;
11
+ return trimmed;
12
+ }
13
+ //#endregion
14
+ //#region extensions/line/src/setup-core.ts
15
+ function patchLineAccountConfig(params) {
16
+ const accountId = normalizeAccountId(params.accountId);
17
+ const lineConfig = params.cfg.channels?.line ?? {};
18
+ const clearFields = params.clearFields ?? [];
19
+ if (accountId === DEFAULT_ACCOUNT_ID) {
20
+ const nextLine = { ...lineConfig };
21
+ for (const field of clearFields) delete nextLine[field];
22
+ return {
23
+ ...params.cfg,
24
+ channels: {
25
+ ...params.cfg.channels,
26
+ line: {
27
+ ...nextLine,
28
+ ...params.enabled ? { enabled: true } : {},
29
+ ...params.patch
30
+ }
31
+ }
32
+ };
33
+ }
34
+ const nextAccount = { ...lineConfig.accounts?.[accountId] };
35
+ for (const field of clearFields) delete nextAccount[field];
36
+ return {
37
+ ...params.cfg,
38
+ channels: {
39
+ ...params.cfg.channels,
40
+ line: {
41
+ ...lineConfig,
42
+ ...params.enabled ? { enabled: true } : {},
43
+ accounts: {
44
+ ...lineConfig.accounts,
45
+ [accountId]: {
46
+ ...nextAccount,
47
+ ...params.enabled ? { enabled: true } : {},
48
+ ...params.patch
49
+ }
50
+ }
51
+ }
52
+ }
53
+ };
54
+ }
55
+ function isLineConfigured(cfg, accountId) {
56
+ return hasLineCredentials(resolveLineAccount({
57
+ cfg,
58
+ accountId
59
+ }));
60
+ }
61
+ const lineSetupAdapter = {
62
+ resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
63
+ applyAccountName: ({ cfg, accountId, name }) => patchLineAccountConfig({
64
+ cfg,
65
+ accountId,
66
+ patch: name?.trim() ? { name: name.trim() } : {}
67
+ }),
68
+ validateInput: createSetupInputPresenceValidator({
69
+ defaultAccountOnlyEnvError: "LINE_CHANNEL_ACCESS_TOKEN can only be used for the default account.",
70
+ whenNotUseEnv: [{
71
+ someOf: ["channelAccessToken", "tokenFile"],
72
+ message: "LINE requires channelAccessToken or --token-file (or --use-env)."
73
+ }, {
74
+ someOf: ["channelSecret", "secretFile"],
75
+ message: "LINE requires channelSecret or --secret-file (or --use-env)."
76
+ }]
77
+ }),
78
+ applyAccountConfig: ({ cfg, accountId, input }) => {
79
+ const typedInput = input;
80
+ const normalizedAccountId = normalizeAccountId(accountId);
81
+ if (normalizedAccountId === DEFAULT_ACCOUNT_ID) return patchLineAccountConfig({
82
+ cfg,
83
+ accountId: normalizedAccountId,
84
+ enabled: true,
85
+ clearFields: typedInput.useEnv ? [
86
+ "channelAccessToken",
87
+ "channelSecret",
88
+ "tokenFile",
89
+ "secretFile"
90
+ ] : void 0,
91
+ patch: typedInput.useEnv ? {} : {
92
+ ...typedInput.tokenFile ? { tokenFile: typedInput.tokenFile } : typedInput.channelAccessToken ? { channelAccessToken: typedInput.channelAccessToken } : {},
93
+ ...typedInput.secretFile ? { secretFile: typedInput.secretFile } : typedInput.channelSecret ? { channelSecret: typedInput.channelSecret } : {}
94
+ }
95
+ });
96
+ return patchLineAccountConfig({
97
+ cfg,
98
+ accountId: normalizedAccountId,
99
+ enabled: true,
100
+ patch: {
101
+ ...typedInput.tokenFile ? { tokenFile: typedInput.tokenFile } : typedInput.channelAccessToken ? { channelAccessToken: typedInput.channelAccessToken } : {},
102
+ ...typedInput.secretFile ? { secretFile: typedInput.secretFile } : typedInput.channelSecret ? { channelSecret: typedInput.channelSecret } : {}
103
+ }
104
+ });
105
+ }
106
+ };
107
+ //#endregion
108
+ //#region extensions/line/src/setup-surface.ts
109
+ const t = createSetupTranslator();
110
+ const channel = "line";
111
+ const LINE_SETUP_HELP_LINES = [
112
+ t("wizard.line.helpOpenConsole"),
113
+ t("wizard.line.helpCopyCredentials"),
114
+ t("wizard.line.helpEnableWebhook"),
115
+ t("wizard.line.helpWebhookUrl"),
116
+ t("wizard.channels.docs", { link: formatDocsLink("/channels/line", "channels/line") })
117
+ ];
118
+ const LINE_ALLOW_FROM_HELP_LINES = [
119
+ t("wizard.line.allowlistIntro"),
120
+ t("wizard.line.idsCaseSensitive"),
121
+ t("wizard.line.examples"),
122
+ "- U1234567890abcdef1234567890abcdef",
123
+ "- line:user:U1234567890abcdef1234567890abcdef",
124
+ t("wizard.line.multipleEntries"),
125
+ t("wizard.channels.docs", { link: formatDocsLink("/channels/line", "channels/line") })
126
+ ];
127
+ const lineDmPolicy = {
128
+ label: "LINE",
129
+ channel,
130
+ policyKey: "channels.line.dmPolicy",
131
+ allowFromKey: "channels.line.allowFrom",
132
+ resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultLineAccountId(cfg)) !== DEFAULT_ACCOUNT_ID ? {
133
+ policyKey: `channels.line.accounts.${accountId ?? resolveDefaultLineAccountId(cfg)}.dmPolicy`,
134
+ allowFromKey: `channels.line.accounts.${accountId ?? resolveDefaultLineAccountId(cfg)}.allowFrom`
135
+ } : {
136
+ policyKey: "channels.line.dmPolicy",
137
+ allowFromKey: "channels.line.allowFrom"
138
+ },
139
+ getCurrent: (cfg, accountId) => resolveLineAccount({
140
+ cfg,
141
+ accountId: accountId ?? resolveDefaultLineAccountId(cfg)
142
+ }).config.dmPolicy ?? "pairing",
143
+ setPolicy: (cfg, policy, accountId) => patchLineAccountConfig({
144
+ cfg,
145
+ accountId: accountId ?? resolveDefaultLineAccountId(cfg),
146
+ enabled: true,
147
+ patch: policy === "open" ? {
148
+ dmPolicy: "open",
149
+ allowFrom: mergeAllowFromEntries(resolveLineAccount({
150
+ cfg,
151
+ accountId: accountId ?? resolveDefaultLineAccountId(cfg)
152
+ }).config.allowFrom, ["*"])
153
+ } : { dmPolicy: policy },
154
+ clearFields: policy === "pairing" || policy === "disabled" ? ["allowFrom"] : void 0
155
+ })
156
+ };
157
+ const lineSetupWizard = {
158
+ channel,
159
+ status: createStandardChannelSetupStatus({
160
+ channelLabel: "LINE",
161
+ configuredLabel: t("wizard.channels.statusConfigured"),
162
+ unconfiguredLabel: t("wizard.channels.statusNeedsTokenSecret"),
163
+ configuredHint: t("wizard.channels.statusConfigured"),
164
+ unconfiguredHint: t("wizard.channels.statusNeedsTokenSecret"),
165
+ configuredScore: 1,
166
+ unconfiguredScore: 0,
167
+ includeStatusLine: true,
168
+ resolveConfigured: ({ cfg, accountId }) => isLineConfigured(cfg, accountId ?? resolveDefaultLineAccountId(cfg)),
169
+ resolveExtraStatusLines: ({ cfg }) => [`Accounts: ${listLineAccountIds(cfg).length || 0}`]
170
+ }),
171
+ introNote: {
172
+ title: t("wizard.line.messagingApiTitle"),
173
+ lines: LINE_SETUP_HELP_LINES,
174
+ shouldShow: ({ cfg, accountId }) => !isLineConfigured(cfg, accountId ?? resolveDefaultLineAccountId(cfg))
175
+ },
176
+ credentials: [{
177
+ inputKey: "token",
178
+ providerHint: channel,
179
+ credentialLabel: t("wizard.line.channelAccessToken"),
180
+ preferredEnvVar: "LINE_CHANNEL_ACCESS_TOKEN",
181
+ helpTitle: t("wizard.line.messagingApiTitle"),
182
+ helpLines: LINE_SETUP_HELP_LINES,
183
+ envPrompt: t("wizard.line.tokenEnvPrompt"),
184
+ keepPrompt: t("wizard.line.tokenKeepPrompt"),
185
+ inputPrompt: t("wizard.line.tokenInputPrompt"),
186
+ allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
187
+ inspect: ({ cfg, accountId }) => {
188
+ const resolved = resolveLineAccount({
189
+ cfg,
190
+ accountId
191
+ });
192
+ return {
193
+ accountConfigured: Boolean(normalizeOptionalString(resolved.channelAccessToken) && normalizeOptionalString(resolved.channelSecret)),
194
+ hasConfiguredValue: Boolean(normalizeOptionalString(resolved.config.channelAccessToken) ?? normalizeOptionalString(resolved.config.tokenFile)),
195
+ resolvedValue: normalizeOptionalString(resolved.channelAccessToken),
196
+ envValue: accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_ACCESS_TOKEN) : void 0
197
+ };
198
+ },
199
+ applyUseEnv: ({ cfg, accountId }) => patchLineAccountConfig({
200
+ cfg,
201
+ accountId,
202
+ enabled: true,
203
+ clearFields: ["channelAccessToken", "tokenFile"],
204
+ patch: {}
205
+ }),
206
+ applySet: ({ cfg, accountId, resolvedValue }) => patchLineAccountConfig({
207
+ cfg,
208
+ accountId,
209
+ enabled: true,
210
+ clearFields: ["tokenFile"],
211
+ patch: { channelAccessToken: resolvedValue }
212
+ })
213
+ }, {
214
+ inputKey: "password",
215
+ providerHint: "line-secret",
216
+ credentialLabel: t("wizard.line.channelSecret"),
217
+ preferredEnvVar: "LINE_CHANNEL_SECRET",
218
+ helpTitle: t("wizard.line.messagingApiTitle"),
219
+ helpLines: LINE_SETUP_HELP_LINES,
220
+ envPrompt: t("wizard.line.secretEnvPrompt"),
221
+ keepPrompt: t("wizard.line.secretKeepPrompt"),
222
+ inputPrompt: t("wizard.line.secretInputPrompt"),
223
+ allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
224
+ inspect: ({ cfg, accountId }) => {
225
+ const resolved = resolveLineAccount({
226
+ cfg,
227
+ accountId
228
+ });
229
+ return {
230
+ accountConfigured: Boolean(normalizeOptionalString(resolved.channelAccessToken) && normalizeOptionalString(resolved.channelSecret)),
231
+ hasConfiguredValue: Boolean(normalizeOptionalString(resolved.config.channelSecret) ?? normalizeOptionalString(resolved.config.secretFile)),
232
+ resolvedValue: normalizeOptionalString(resolved.channelSecret),
233
+ envValue: accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_SECRET) : void 0
234
+ };
235
+ },
236
+ applyUseEnv: ({ cfg, accountId }) => patchLineAccountConfig({
237
+ cfg,
238
+ accountId,
239
+ enabled: true,
240
+ clearFields: ["channelSecret", "secretFile"],
241
+ patch: {}
242
+ }),
243
+ applySet: ({ cfg, accountId, resolvedValue }) => patchLineAccountConfig({
244
+ cfg,
245
+ accountId,
246
+ enabled: true,
247
+ clearFields: ["secretFile"],
248
+ patch: { channelSecret: resolvedValue }
249
+ })
250
+ }],
251
+ allowFrom: createAllowFromSection({
252
+ helpTitle: t("wizard.line.allowlistTitle"),
253
+ helpLines: LINE_ALLOW_FROM_HELP_LINES,
254
+ message: t("wizard.line.allowFromPrompt"),
255
+ placeholder: "U1234567890abcdef1234567890abcdef",
256
+ invalidWithoutCredentialNote: t("wizard.line.allowFromInvalid"),
257
+ parseInputs: splitSetupEntries,
258
+ parseId: parseLineAllowFromId,
259
+ apply: ({ cfg, accountId, allowFrom }) => patchLineAccountConfig({
260
+ cfg,
261
+ accountId,
262
+ enabled: true,
263
+ patch: {
264
+ dmPolicy: "allowlist",
265
+ allowFrom
266
+ }
267
+ })
268
+ }),
269
+ dmPolicy: lineDmPolicy,
270
+ completionNote: {
271
+ title: t("wizard.line.webhookTitle"),
272
+ lines: [
273
+ t("wizard.line.completionEnableWebhook"),
274
+ t("wizard.line.completionDefaultWebhook"),
275
+ t("wizard.line.completionWebhookPath"),
276
+ t("wizard.channels.docs", { link: formatDocsLink("/channels/line", "channels/line") })
277
+ ]
278
+ },
279
+ disable: (cfg) => setSetupChannelEnabled(cfg, channel, false)
280
+ };
281
+ //#endregion
282
+ export { lineSetupAdapter as n, hasLineCredentials as r, lineSetupWizard as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kodelyth/line",
3
- "version": "2026.5.39",
3
+ "version": "2026.6.1",
4
4
  "description": "Klaw LINE channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,21 +13,25 @@
13
13
  },
14
14
  "devDependencies": {
15
15
  "@kodelyth/plugin-sdk": "1.0.1",
16
- "@kodelyth/klaw": "2026.5.41"
16
+ "@kodelyth/klaw": "2026.5.42"
17
17
  },
18
18
  "peerDependencies": {
19
- "@kodelyth/klaw": ">=2026.5.19"
19
+ "@kodelyth/klaw": ">=2026.5.19",
20
+ "klaw": ">=2026.5.39"
20
21
  },
21
22
  "peerDependenciesMeta": {
22
23
  "@kodelyth/klaw": {
23
24
  "optional": true
25
+ },
26
+ "klaw": {
27
+ "optional": true
24
28
  }
25
29
  },
26
30
  "klaw": {
27
31
  "extensions": [
28
- "./index.js"
32
+ "./index.ts"
29
33
  ],
30
- "setupEntry": "./setup-entry.js",
34
+ "setupEntry": "./setup-entry.ts",
31
35
  "channel": {
32
36
  "id": "line",
33
37
  "label": "LINE",
@@ -54,6 +58,14 @@
54
58
  "release": {
55
59
  "publishToClawHub": true,
56
60
  "publishToNpm": true
57
- }
58
- }
61
+ },
62
+ "runtimeExtensions": [
63
+ "./dist/index.js"
64
+ ],
65
+ "runtimeSetupEntry": "./dist/setup-entry.js"
66
+ },
67
+ "files": [
68
+ "dist/**",
69
+ "klaw.plugin.json"
70
+ ]
59
71
  }
package/api.js DELETED
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/api.js";
2
- import * as module from "../../../dist/extensions/line/api.js";
3
- let defaultExport = "default" in module ? module.default : module;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/channel-plugin-api.js";
2
- import * as module from "../../../dist/extensions/line/channel-plugin-api.js";
3
- let defaultExport = "default" in module ? module.default : module;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };
package/contract-api.js DELETED
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/contract-api.js";
2
- import * as module from "../../../dist/extensions/line/contract-api.js";
3
- let defaultExport = "default" in module ? module.default : module;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };
package/index.js DELETED
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/index.js";
2
- import defaultModule from "../../../dist/extensions/line/index.js";
3
- let defaultExport = defaultModule;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };
package/runtime-api.js DELETED
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/runtime-api.js";
2
- import * as module from "../../../dist/extensions/line/runtime-api.js";
3
- let defaultExport = "default" in module ? module.default : module;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/secret-contract-api.js";
2
- import * as module from "../../../dist/extensions/line/secret-contract-api.js";
3
- let defaultExport = "default" in module ? module.default : module;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };
package/setup-api.js DELETED
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/setup-api.js";
2
- import * as module from "../../../dist/extensions/line/setup-api.js";
3
- let defaultExport = "default" in module ? module.default : module;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };
package/setup-entry.js DELETED
@@ -1,7 +0,0 @@
1
- export * from "../../../dist/extensions/line/setup-entry.js";
2
- import defaultModule from "../../../dist/extensions/line/setup-entry.js";
3
- let defaultExport = defaultModule;
4
- for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
5
- defaultExport = defaultExport.default;
6
- }
7
- export { defaultExport as default };