@ch4p/cli 0.1.6 → 0.2.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.
- package/dist/canvas-GNDHSAGO.js +313 -0
- package/dist/canvas-QHWTRFYK.js +313 -0
- package/dist/chunk-3CYOOHMM.js +4412 -0
- package/dist/chunk-F7E5NKMH.js +1835 -0
- package/dist/chunk-QDH3EMTH.js +4406 -0
- package/dist/chunk-WYXCGS55.js +1845 -0
- package/dist/gateway-4EXQDINT.js +2259 -0
- package/dist/gateway-GCLV27HQ.js +2255 -0
- package/dist/index.js +4 -4
- package/dist/message-LTVKYQKB.js +189 -0
- package/dist/message-RLOYZWHL.js +189 -0
- package/dist/pairing-73HTMAVW.js +147 -0
- package/dist/pairing-GVBOSGP7.js +147 -0
- package/package.json +17 -17
package/dist/index.js
CHANGED
|
@@ -111,7 +111,7 @@ async function main() {
|
|
|
111
111
|
break;
|
|
112
112
|
}
|
|
113
113
|
case "gateway": {
|
|
114
|
-
const { gateway } = await import("./gateway-
|
|
114
|
+
const { gateway } = await import("./gateway-4EXQDINT.js");
|
|
115
115
|
await gateway(rest);
|
|
116
116
|
break;
|
|
117
117
|
}
|
|
@@ -141,12 +141,12 @@ async function main() {
|
|
|
141
141
|
break;
|
|
142
142
|
}
|
|
143
143
|
case "pairing": {
|
|
144
|
-
const { pairing } = await import("./pairing-
|
|
144
|
+
const { pairing } = await import("./pairing-73HTMAVW.js");
|
|
145
145
|
await pairing(rest);
|
|
146
146
|
break;
|
|
147
147
|
}
|
|
148
148
|
case "message": {
|
|
149
|
-
const { message } = await import("./message-
|
|
149
|
+
const { message } = await import("./message-LTVKYQKB.js");
|
|
150
150
|
await message(rest);
|
|
151
151
|
break;
|
|
152
152
|
}
|
|
@@ -156,7 +156,7 @@ async function main() {
|
|
|
156
156
|
break;
|
|
157
157
|
}
|
|
158
158
|
case "canvas": {
|
|
159
|
-
const { canvas } = await import("./canvas-
|
|
159
|
+
const { canvas } = await import("./canvas-GNDHSAGO.js");
|
|
160
160
|
await canvas(rest);
|
|
161
161
|
break;
|
|
162
162
|
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliChannel,
|
|
3
|
+
DiscordChannel,
|
|
4
|
+
IMessageChannel,
|
|
5
|
+
MatrixChannel,
|
|
6
|
+
SignalChannel,
|
|
7
|
+
SlackChannel,
|
|
8
|
+
TelegramChannel,
|
|
9
|
+
WhatsAppChannel
|
|
10
|
+
} from "./chunk-3CYOOHMM.js";
|
|
11
|
+
import "./chunk-YSCX2QQQ.js";
|
|
12
|
+
import {
|
|
13
|
+
loadConfig
|
|
14
|
+
} from "./chunk-AORLXQHZ.js";
|
|
15
|
+
import {
|
|
16
|
+
BOLD,
|
|
17
|
+
DIM,
|
|
18
|
+
GREEN,
|
|
19
|
+
RED,
|
|
20
|
+
RESET,
|
|
21
|
+
TEAL,
|
|
22
|
+
separator
|
|
23
|
+
} from "./chunk-NMGPBPNU.js";
|
|
24
|
+
|
|
25
|
+
// src/commands/message.ts
|
|
26
|
+
function createChannelInstance(channelName) {
|
|
27
|
+
switch (channelName) {
|
|
28
|
+
case "telegram":
|
|
29
|
+
return new TelegramChannel();
|
|
30
|
+
case "discord":
|
|
31
|
+
return new DiscordChannel();
|
|
32
|
+
case "slack":
|
|
33
|
+
return new SlackChannel();
|
|
34
|
+
case "cli":
|
|
35
|
+
return new CliChannel();
|
|
36
|
+
case "matrix":
|
|
37
|
+
return new MatrixChannel();
|
|
38
|
+
case "whatsapp":
|
|
39
|
+
return new WhatsAppChannel();
|
|
40
|
+
case "signal":
|
|
41
|
+
return new SignalChannel();
|
|
42
|
+
case "imessage":
|
|
43
|
+
return new IMessageChannel();
|
|
44
|
+
default:
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function parseMessageArgs(args) {
|
|
49
|
+
let channel = null;
|
|
50
|
+
let threadId = null;
|
|
51
|
+
let text = null;
|
|
52
|
+
const textParts = [];
|
|
53
|
+
for (let i = 0; i < args.length; i++) {
|
|
54
|
+
const arg = args[i];
|
|
55
|
+
if (arg === "-c" || arg === "--channel") {
|
|
56
|
+
channel = args[i + 1] ?? null;
|
|
57
|
+
i++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (arg === "-t" || arg === "--thread") {
|
|
61
|
+
threadId = args[i + 1] ?? null;
|
|
62
|
+
i++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
textParts.push(arg);
|
|
66
|
+
}
|
|
67
|
+
if (textParts.length > 0) {
|
|
68
|
+
text = textParts.join(" ");
|
|
69
|
+
}
|
|
70
|
+
return { channel, threadId, text };
|
|
71
|
+
}
|
|
72
|
+
async function message(args) {
|
|
73
|
+
const parsed = parseMessageArgs(args);
|
|
74
|
+
if (!parsed.channel) {
|
|
75
|
+
console.error(`
|
|
76
|
+
${RED}Error:${RESET} Channel is required.`);
|
|
77
|
+
console.error(` ${DIM}Usage: ch4p message -c <channel> "message text"${RESET}`);
|
|
78
|
+
console.error(` ${DIM}Example: ch4p message -c telegram "Hello!"${RESET}
|
|
79
|
+
`);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!parsed.text) {
|
|
84
|
+
console.error(`
|
|
85
|
+
${RED}Error:${RESET} Message text is required.`);
|
|
86
|
+
console.error(` ${DIM}Usage: ch4p message -c ${parsed.channel} "message text"${RESET}
|
|
87
|
+
`);
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
let config;
|
|
92
|
+
try {
|
|
93
|
+
config = loadConfig();
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
96
|
+
console.error(`
|
|
97
|
+
${RED}Failed to load config:${RESET} ${errMessage}`);
|
|
98
|
+
console.error(` ${DIM}Run ${TEAL}ch4p onboard${DIM} to set up ch4p.${RESET}
|
|
99
|
+
`);
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const channelConfig = config.channels[parsed.channel];
|
|
104
|
+
if (!channelConfig) {
|
|
105
|
+
const availableChannels = Object.keys(config.channels);
|
|
106
|
+
console.error(`
|
|
107
|
+
${RED}Error:${RESET} Channel "${parsed.channel}" is not configured.`);
|
|
108
|
+
if (availableChannels.length > 0) {
|
|
109
|
+
console.error(` ${DIM}Available channels: ${availableChannels.join(", ")}${RESET}`);
|
|
110
|
+
} else {
|
|
111
|
+
console.error(` ${DIM}No channels configured. Add channels to ~/.ch4p/config.json.${RESET}`);
|
|
112
|
+
console.error(` ${DIM}Example for Telegram:${RESET}`);
|
|
113
|
+
console.error(` ${DIM} "channels": { "telegram": { "token": "BOT_TOKEN" } }${RESET}`);
|
|
114
|
+
}
|
|
115
|
+
console.error("");
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const channel = createChannelInstance(parsed.channel);
|
|
120
|
+
if (!channel) {
|
|
121
|
+
console.error(`
|
|
122
|
+
${RED}Error:${RESET} Unknown channel type "${parsed.channel}".`);
|
|
123
|
+
console.error(` ${DIM}Supported channels: telegram, discord, slack, cli${RESET}
|
|
124
|
+
`);
|
|
125
|
+
process.exitCode = 1;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
console.log(`
|
|
129
|
+
${TEAL}${BOLD}ch4p Message${RESET}`);
|
|
130
|
+
console.log(separator());
|
|
131
|
+
console.log("");
|
|
132
|
+
console.log(` ${BOLD}Channel${RESET} ${parsed.channel}`);
|
|
133
|
+
if (parsed.threadId) {
|
|
134
|
+
console.log(` ${BOLD}Thread${RESET} ${parsed.threadId}`);
|
|
135
|
+
}
|
|
136
|
+
console.log(` ${BOLD}Message${RESET} ${parsed.text}`);
|
|
137
|
+
console.log("");
|
|
138
|
+
try {
|
|
139
|
+
console.log(` ${DIM}Starting ${parsed.channel} channel...${RESET}`);
|
|
140
|
+
await channel.start(channelConfig);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
143
|
+
console.error(` ${RED}Failed to start channel:${RESET} ${errMessage}
|
|
144
|
+
`);
|
|
145
|
+
process.exitCode = 1;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const outbound = {
|
|
149
|
+
text: parsed.text,
|
|
150
|
+
format: "text"
|
|
151
|
+
};
|
|
152
|
+
const recipient = {
|
|
153
|
+
channelId: parsed.channel,
|
|
154
|
+
userId: channelConfig["chatId"] ?? channelConfig["defaultChatId"] ?? void 0,
|
|
155
|
+
groupId: channelConfig["channelId"] ?? channelConfig["defaultChannelId"] ?? void 0,
|
|
156
|
+
threadId: parsed.threadId ?? void 0
|
|
157
|
+
};
|
|
158
|
+
if (!recipient.userId && !recipient.groupId) {
|
|
159
|
+
console.error(` ${RED}Error:${RESET} No recipient specified.`);
|
|
160
|
+
console.error(` ${DIM}Add "chatId" or "defaultChatId" to your ${parsed.channel} channel config.${RESET}`);
|
|
161
|
+
console.error(` ${DIM}Example: "channels": { "${parsed.channel}": { "token": "...", "chatId": "123" } }${RESET}
|
|
162
|
+
`);
|
|
163
|
+
await channel.stop();
|
|
164
|
+
process.exitCode = 1;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const result = await channel.send(recipient, outbound);
|
|
169
|
+
if (result.success) {
|
|
170
|
+
console.log(` ${GREEN}${BOLD}Sent!${RESET}`);
|
|
171
|
+
if (result.messageId) {
|
|
172
|
+
console.log(` ${DIM}Message ID: ${result.messageId}${RESET}`);
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
console.error(` ${RED}Failed to send:${RESET} ${result.error ?? "Unknown error"}`);
|
|
176
|
+
process.exitCode = 1;
|
|
177
|
+
}
|
|
178
|
+
} catch (err) {
|
|
179
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
180
|
+
console.error(` ${RED}Send error:${RESET} ${errMessage}`);
|
|
181
|
+
process.exitCode = 1;
|
|
182
|
+
} finally {
|
|
183
|
+
await channel.stop();
|
|
184
|
+
}
|
|
185
|
+
console.log("");
|
|
186
|
+
}
|
|
187
|
+
export {
|
|
188
|
+
message
|
|
189
|
+
};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliChannel,
|
|
3
|
+
DiscordChannel,
|
|
4
|
+
IMessageChannel,
|
|
5
|
+
MatrixChannel,
|
|
6
|
+
SignalChannel,
|
|
7
|
+
SlackChannel,
|
|
8
|
+
TelegramChannel,
|
|
9
|
+
WhatsAppChannel
|
|
10
|
+
} from "./chunk-QDH3EMTH.js";
|
|
11
|
+
import "./chunk-YSCX2QQQ.js";
|
|
12
|
+
import {
|
|
13
|
+
loadConfig
|
|
14
|
+
} from "./chunk-AORLXQHZ.js";
|
|
15
|
+
import {
|
|
16
|
+
BOLD,
|
|
17
|
+
DIM,
|
|
18
|
+
GREEN,
|
|
19
|
+
RED,
|
|
20
|
+
RESET,
|
|
21
|
+
TEAL,
|
|
22
|
+
separator
|
|
23
|
+
} from "./chunk-NMGPBPNU.js";
|
|
24
|
+
|
|
25
|
+
// src/commands/message.ts
|
|
26
|
+
function createChannelInstance(channelName) {
|
|
27
|
+
switch (channelName) {
|
|
28
|
+
case "telegram":
|
|
29
|
+
return new TelegramChannel();
|
|
30
|
+
case "discord":
|
|
31
|
+
return new DiscordChannel();
|
|
32
|
+
case "slack":
|
|
33
|
+
return new SlackChannel();
|
|
34
|
+
case "cli":
|
|
35
|
+
return new CliChannel();
|
|
36
|
+
case "matrix":
|
|
37
|
+
return new MatrixChannel();
|
|
38
|
+
case "whatsapp":
|
|
39
|
+
return new WhatsAppChannel();
|
|
40
|
+
case "signal":
|
|
41
|
+
return new SignalChannel();
|
|
42
|
+
case "imessage":
|
|
43
|
+
return new IMessageChannel();
|
|
44
|
+
default:
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function parseMessageArgs(args) {
|
|
49
|
+
let channel = null;
|
|
50
|
+
let threadId = null;
|
|
51
|
+
let text = null;
|
|
52
|
+
const textParts = [];
|
|
53
|
+
for (let i = 0; i < args.length; i++) {
|
|
54
|
+
const arg = args[i];
|
|
55
|
+
if (arg === "-c" || arg === "--channel") {
|
|
56
|
+
channel = args[i + 1] ?? null;
|
|
57
|
+
i++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (arg === "-t" || arg === "--thread") {
|
|
61
|
+
threadId = args[i + 1] ?? null;
|
|
62
|
+
i++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
textParts.push(arg);
|
|
66
|
+
}
|
|
67
|
+
if (textParts.length > 0) {
|
|
68
|
+
text = textParts.join(" ");
|
|
69
|
+
}
|
|
70
|
+
return { channel, threadId, text };
|
|
71
|
+
}
|
|
72
|
+
async function message(args) {
|
|
73
|
+
const parsed = parseMessageArgs(args);
|
|
74
|
+
if (!parsed.channel) {
|
|
75
|
+
console.error(`
|
|
76
|
+
${RED}Error:${RESET} Channel is required.`);
|
|
77
|
+
console.error(` ${DIM}Usage: ch4p message -c <channel> "message text"${RESET}`);
|
|
78
|
+
console.error(` ${DIM}Example: ch4p message -c telegram "Hello!"${RESET}
|
|
79
|
+
`);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!parsed.text) {
|
|
84
|
+
console.error(`
|
|
85
|
+
${RED}Error:${RESET} Message text is required.`);
|
|
86
|
+
console.error(` ${DIM}Usage: ch4p message -c ${parsed.channel} "message text"${RESET}
|
|
87
|
+
`);
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
let config;
|
|
92
|
+
try {
|
|
93
|
+
config = loadConfig();
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
96
|
+
console.error(`
|
|
97
|
+
${RED}Failed to load config:${RESET} ${errMessage}`);
|
|
98
|
+
console.error(` ${DIM}Run ${TEAL}ch4p onboard${DIM} to set up ch4p.${RESET}
|
|
99
|
+
`);
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const channelConfig = config.channels[parsed.channel];
|
|
104
|
+
if (!channelConfig) {
|
|
105
|
+
const availableChannels = Object.keys(config.channels);
|
|
106
|
+
console.error(`
|
|
107
|
+
${RED}Error:${RESET} Channel "${parsed.channel}" is not configured.`);
|
|
108
|
+
if (availableChannels.length > 0) {
|
|
109
|
+
console.error(` ${DIM}Available channels: ${availableChannels.join(", ")}${RESET}`);
|
|
110
|
+
} else {
|
|
111
|
+
console.error(` ${DIM}No channels configured. Add channels to ~/.ch4p/config.json.${RESET}`);
|
|
112
|
+
console.error(` ${DIM}Example for Telegram:${RESET}`);
|
|
113
|
+
console.error(` ${DIM} "channels": { "telegram": { "token": "BOT_TOKEN" } }${RESET}`);
|
|
114
|
+
}
|
|
115
|
+
console.error("");
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const channel = createChannelInstance(parsed.channel);
|
|
120
|
+
if (!channel) {
|
|
121
|
+
console.error(`
|
|
122
|
+
${RED}Error:${RESET} Unknown channel type "${parsed.channel}".`);
|
|
123
|
+
console.error(` ${DIM}Supported channels: telegram, discord, slack, cli${RESET}
|
|
124
|
+
`);
|
|
125
|
+
process.exitCode = 1;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
console.log(`
|
|
129
|
+
${TEAL}${BOLD}ch4p Message${RESET}`);
|
|
130
|
+
console.log(separator());
|
|
131
|
+
console.log("");
|
|
132
|
+
console.log(` ${BOLD}Channel${RESET} ${parsed.channel}`);
|
|
133
|
+
if (parsed.threadId) {
|
|
134
|
+
console.log(` ${BOLD}Thread${RESET} ${parsed.threadId}`);
|
|
135
|
+
}
|
|
136
|
+
console.log(` ${BOLD}Message${RESET} ${parsed.text}`);
|
|
137
|
+
console.log("");
|
|
138
|
+
try {
|
|
139
|
+
console.log(` ${DIM}Starting ${parsed.channel} channel...${RESET}`);
|
|
140
|
+
await channel.start(channelConfig);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
143
|
+
console.error(` ${RED}Failed to start channel:${RESET} ${errMessage}
|
|
144
|
+
`);
|
|
145
|
+
process.exitCode = 1;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const outbound = {
|
|
149
|
+
text: parsed.text,
|
|
150
|
+
format: "text"
|
|
151
|
+
};
|
|
152
|
+
const recipient = {
|
|
153
|
+
channelId: parsed.channel,
|
|
154
|
+
userId: channelConfig["chatId"] ?? channelConfig["defaultChatId"] ?? void 0,
|
|
155
|
+
groupId: channelConfig["channelId"] ?? channelConfig["defaultChannelId"] ?? void 0,
|
|
156
|
+
threadId: parsed.threadId ?? void 0
|
|
157
|
+
};
|
|
158
|
+
if (!recipient.userId && !recipient.groupId) {
|
|
159
|
+
console.error(` ${RED}Error:${RESET} No recipient specified.`);
|
|
160
|
+
console.error(` ${DIM}Add "chatId" or "defaultChatId" to your ${parsed.channel} channel config.${RESET}`);
|
|
161
|
+
console.error(` ${DIM}Example: "channels": { "${parsed.channel}": { "token": "...", "chatId": "123" } }${RESET}
|
|
162
|
+
`);
|
|
163
|
+
await channel.stop();
|
|
164
|
+
process.exitCode = 1;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const result = await channel.send(recipient, outbound);
|
|
169
|
+
if (result.success) {
|
|
170
|
+
console.log(` ${GREEN}${BOLD}Sent!${RESET}`);
|
|
171
|
+
if (result.messageId) {
|
|
172
|
+
console.log(` ${DIM}Message ID: ${result.messageId}${RESET}`);
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
console.error(` ${RED}Failed to send:${RESET} ${result.error ?? "Unknown error"}`);
|
|
176
|
+
process.exitCode = 1;
|
|
177
|
+
}
|
|
178
|
+
} catch (err) {
|
|
179
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
180
|
+
console.error(` ${RED}Send error:${RESET} ${errMessage}`);
|
|
181
|
+
process.exitCode = 1;
|
|
182
|
+
} finally {
|
|
183
|
+
await channel.stop();
|
|
184
|
+
}
|
|
185
|
+
console.log("");
|
|
186
|
+
}
|
|
187
|
+
export {
|
|
188
|
+
message
|
|
189
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PairingManager
|
|
3
|
+
} from "./chunk-WYXCGS55.js";
|
|
4
|
+
import "./chunk-YSCX2QQQ.js";
|
|
5
|
+
import {
|
|
6
|
+
loadConfig
|
|
7
|
+
} from "./chunk-AORLXQHZ.js";
|
|
8
|
+
import {
|
|
9
|
+
BOLD,
|
|
10
|
+
DIM,
|
|
11
|
+
GREEN,
|
|
12
|
+
RED,
|
|
13
|
+
RESET,
|
|
14
|
+
TEAL,
|
|
15
|
+
YELLOW,
|
|
16
|
+
separator
|
|
17
|
+
} from "./chunk-NMGPBPNU.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/pairing.ts
|
|
20
|
+
var manager = null;
|
|
21
|
+
function getManager() {
|
|
22
|
+
if (!manager) {
|
|
23
|
+
manager = new PairingManager();
|
|
24
|
+
}
|
|
25
|
+
return manager;
|
|
26
|
+
}
|
|
27
|
+
function handleGenerate(args) {
|
|
28
|
+
const label = args[0] ?? "CLI";
|
|
29
|
+
const pm = getManager();
|
|
30
|
+
try {
|
|
31
|
+
const code = pm.generateCode(label);
|
|
32
|
+
console.log(` ${GREEN}${BOLD}Pairing code generated${RESET}
|
|
33
|
+
`);
|
|
34
|
+
console.log(` ${BOLD}Code${RESET} ${TEAL}${BOLD}${code.code}${RESET}`);
|
|
35
|
+
console.log(` ${BOLD}Label${RESET} ${code.label ?? DIM + "none" + RESET}`);
|
|
36
|
+
console.log(` ${BOLD}Expires${RESET} ${code.expiresAt.toLocaleTimeString()}`);
|
|
37
|
+
console.log("");
|
|
38
|
+
console.log(` ${DIM}Share this code with the client. It can only be used once.${RESET}`);
|
|
39
|
+
console.log(` ${DIM}Exchange via: POST /pair { "code": "${code.code}" }${RESET}`);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
42
|
+
console.log(` ${RED}Failed to generate code:${RESET} ${message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function handleList() {
|
|
46
|
+
const pm = getManager();
|
|
47
|
+
const codes = pm.listCodes();
|
|
48
|
+
const clients = pm.listClients();
|
|
49
|
+
const stats = pm.stats();
|
|
50
|
+
console.log(` ${BOLD}Active Codes${RESET} ${DIM}(${stats.activeCodes})${RESET}`);
|
|
51
|
+
if (codes.length === 0) {
|
|
52
|
+
console.log(` ${DIM}No active pairing codes.${RESET}`);
|
|
53
|
+
} else {
|
|
54
|
+
for (const code of codes) {
|
|
55
|
+
const remaining = Math.max(0, Math.ceil((code.expiresAt.getTime() - Date.now()) / 1e3));
|
|
56
|
+
console.log(
|
|
57
|
+
` ${TEAL}${code.code}${RESET} ${DIM}label=${code.label ?? "none"} expires in ${remaining}s${RESET}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
console.log("");
|
|
62
|
+
console.log(` ${BOLD}Paired Clients${RESET} ${DIM}(${stats.pairedClients})${RESET}`);
|
|
63
|
+
if (clients.length === 0) {
|
|
64
|
+
console.log(` ${DIM}No paired clients.${RESET}`);
|
|
65
|
+
} else {
|
|
66
|
+
for (const client of clients) {
|
|
67
|
+
console.log(
|
|
68
|
+
` ${GREEN}${client.tokenPreview}${RESET} ${DIM}label=${client.label ?? "none"} paired=${client.pairedAt.toLocaleTimeString()} seen=${client.lastSeenAt.toLocaleTimeString()}${RESET}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function handleRevoke(args) {
|
|
74
|
+
const target = args[0];
|
|
75
|
+
if (!target) {
|
|
76
|
+
console.log(` ${RED}Usage:${RESET} ch4p pairing revoke <code-or-token-hash>`);
|
|
77
|
+
console.log(` ${DIM}Use 'ch4p pairing list' to see active codes and clients.${RESET}`);
|
|
78
|
+
process.exitCode = 1;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const pm = getManager();
|
|
82
|
+
if (pm.revokeCode(target)) {
|
|
83
|
+
console.log(` ${GREEN}Revoked pairing code:${RESET} ${target}`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (pm.revokeClient(target)) {
|
|
87
|
+
console.log(` ${GREEN}Revoked paired client:${RESET} ${target.slice(0, 16)}...`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
console.log(` ${YELLOW}Not found:${RESET} ${target}`);
|
|
91
|
+
console.log(` ${DIM}No active code or client matched. Use 'ch4p pairing list' to see current state.${RESET}`);
|
|
92
|
+
}
|
|
93
|
+
function handleStatus(requirePairing, port) {
|
|
94
|
+
const pm = getManager();
|
|
95
|
+
const stats = pm.stats();
|
|
96
|
+
console.log(` ${BOLD}Configuration${RESET}`);
|
|
97
|
+
console.log(` ${BOLD} Pairing required${RESET} ${requirePairing ? `${GREEN}yes${RESET}` : `${YELLOW}no${RESET}`}`);
|
|
98
|
+
console.log(` ${BOLD} Gateway port${RESET} ${port}`);
|
|
99
|
+
console.log("");
|
|
100
|
+
console.log(` ${BOLD}Local State${RESET}`);
|
|
101
|
+
console.log(` ${BOLD} Active codes${RESET} ${stats.activeCodes}`);
|
|
102
|
+
console.log(` ${BOLD} Paired clients${RESET} ${stats.pairedClients}`);
|
|
103
|
+
console.log("");
|
|
104
|
+
console.log(` ${DIM}Subcommands: generate [label], list, revoke <target>, status${RESET}`);
|
|
105
|
+
}
|
|
106
|
+
async function pairing(args) {
|
|
107
|
+
let config;
|
|
108
|
+
try {
|
|
109
|
+
config = loadConfig();
|
|
110
|
+
} catch (err) {
|
|
111
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
112
|
+
console.error(`
|
|
113
|
+
${RED}Failed to load config:${RESET} ${message}`);
|
|
114
|
+
console.error(` ${DIM}Run ${TEAL}ch4p onboard${DIM} to set up ch4p.${RESET}
|
|
115
|
+
`);
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const subcommand = args[0] ?? "status";
|
|
120
|
+
const subArgs = args.slice(1);
|
|
121
|
+
console.log(`
|
|
122
|
+
${TEAL}${BOLD}ch4p Pairing${RESET}`);
|
|
123
|
+
console.log(separator());
|
|
124
|
+
console.log("");
|
|
125
|
+
switch (subcommand) {
|
|
126
|
+
case "generate":
|
|
127
|
+
handleGenerate(subArgs);
|
|
128
|
+
break;
|
|
129
|
+
case "list":
|
|
130
|
+
handleList();
|
|
131
|
+
break;
|
|
132
|
+
case "revoke":
|
|
133
|
+
handleRevoke(subArgs);
|
|
134
|
+
break;
|
|
135
|
+
case "status":
|
|
136
|
+
handleStatus(config.gateway.requirePairing, config.gateway.port);
|
|
137
|
+
break;
|
|
138
|
+
default:
|
|
139
|
+
console.log(` ${RED}Unknown subcommand: ${subcommand}${RESET}`);
|
|
140
|
+
console.log(` ${DIM}Available: generate, list, revoke, status${RESET}`);
|
|
141
|
+
process.exitCode = 1;
|
|
142
|
+
}
|
|
143
|
+
console.log("");
|
|
144
|
+
}
|
|
145
|
+
export {
|
|
146
|
+
pairing
|
|
147
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PairingManager
|
|
3
|
+
} from "./chunk-F7E5NKMH.js";
|
|
4
|
+
import "./chunk-YSCX2QQQ.js";
|
|
5
|
+
import {
|
|
6
|
+
loadConfig
|
|
7
|
+
} from "./chunk-AORLXQHZ.js";
|
|
8
|
+
import {
|
|
9
|
+
BOLD,
|
|
10
|
+
DIM,
|
|
11
|
+
GREEN,
|
|
12
|
+
RED,
|
|
13
|
+
RESET,
|
|
14
|
+
TEAL,
|
|
15
|
+
YELLOW,
|
|
16
|
+
separator
|
|
17
|
+
} from "./chunk-NMGPBPNU.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/pairing.ts
|
|
20
|
+
var manager = null;
|
|
21
|
+
function getManager() {
|
|
22
|
+
if (!manager) {
|
|
23
|
+
manager = new PairingManager();
|
|
24
|
+
}
|
|
25
|
+
return manager;
|
|
26
|
+
}
|
|
27
|
+
function handleGenerate(args) {
|
|
28
|
+
const label = args[0] ?? "CLI";
|
|
29
|
+
const pm = getManager();
|
|
30
|
+
try {
|
|
31
|
+
const code = pm.generateCode(label);
|
|
32
|
+
console.log(` ${GREEN}${BOLD}Pairing code generated${RESET}
|
|
33
|
+
`);
|
|
34
|
+
console.log(` ${BOLD}Code${RESET} ${TEAL}${BOLD}${code.code}${RESET}`);
|
|
35
|
+
console.log(` ${BOLD}Label${RESET} ${code.label ?? DIM + "none" + RESET}`);
|
|
36
|
+
console.log(` ${BOLD}Expires${RESET} ${code.expiresAt.toLocaleTimeString()}`);
|
|
37
|
+
console.log("");
|
|
38
|
+
console.log(` ${DIM}Share this code with the client. It can only be used once.${RESET}`);
|
|
39
|
+
console.log(` ${DIM}Exchange via: POST /pair { "code": "${code.code}" }${RESET}`);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
42
|
+
console.log(` ${RED}Failed to generate code:${RESET} ${message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function handleList() {
|
|
46
|
+
const pm = getManager();
|
|
47
|
+
const codes = pm.listCodes();
|
|
48
|
+
const clients = pm.listClients();
|
|
49
|
+
const stats = pm.stats();
|
|
50
|
+
console.log(` ${BOLD}Active Codes${RESET} ${DIM}(${stats.activeCodes})${RESET}`);
|
|
51
|
+
if (codes.length === 0) {
|
|
52
|
+
console.log(` ${DIM}No active pairing codes.${RESET}`);
|
|
53
|
+
} else {
|
|
54
|
+
for (const code of codes) {
|
|
55
|
+
const remaining = Math.max(0, Math.ceil((code.expiresAt.getTime() - Date.now()) / 1e3));
|
|
56
|
+
console.log(
|
|
57
|
+
` ${TEAL}${code.code}${RESET} ${DIM}label=${code.label ?? "none"} expires in ${remaining}s${RESET}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
console.log("");
|
|
62
|
+
console.log(` ${BOLD}Paired Clients${RESET} ${DIM}(${stats.pairedClients})${RESET}`);
|
|
63
|
+
if (clients.length === 0) {
|
|
64
|
+
console.log(` ${DIM}No paired clients.${RESET}`);
|
|
65
|
+
} else {
|
|
66
|
+
for (const client of clients) {
|
|
67
|
+
console.log(
|
|
68
|
+
` ${GREEN}${client.tokenPreview}${RESET} ${DIM}label=${client.label ?? "none"} paired=${client.pairedAt.toLocaleTimeString()} seen=${client.lastSeenAt.toLocaleTimeString()}${RESET}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function handleRevoke(args) {
|
|
74
|
+
const target = args[0];
|
|
75
|
+
if (!target) {
|
|
76
|
+
console.log(` ${RED}Usage:${RESET} ch4p pairing revoke <code-or-token-hash>`);
|
|
77
|
+
console.log(` ${DIM}Use 'ch4p pairing list' to see active codes and clients.${RESET}`);
|
|
78
|
+
process.exitCode = 1;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const pm = getManager();
|
|
82
|
+
if (pm.revokeCode(target)) {
|
|
83
|
+
console.log(` ${GREEN}Revoked pairing code:${RESET} ${target}`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (pm.revokeClient(target)) {
|
|
87
|
+
console.log(` ${GREEN}Revoked paired client:${RESET} ${target.slice(0, 16)}...`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
console.log(` ${YELLOW}Not found:${RESET} ${target}`);
|
|
91
|
+
console.log(` ${DIM}No active code or client matched. Use 'ch4p pairing list' to see current state.${RESET}`);
|
|
92
|
+
}
|
|
93
|
+
function handleStatus(requirePairing, port) {
|
|
94
|
+
const pm = getManager();
|
|
95
|
+
const stats = pm.stats();
|
|
96
|
+
console.log(` ${BOLD}Configuration${RESET}`);
|
|
97
|
+
console.log(` ${BOLD} Pairing required${RESET} ${requirePairing ? `${GREEN}yes${RESET}` : `${YELLOW}no${RESET}`}`);
|
|
98
|
+
console.log(` ${BOLD} Gateway port${RESET} ${port}`);
|
|
99
|
+
console.log("");
|
|
100
|
+
console.log(` ${BOLD}Local State${RESET}`);
|
|
101
|
+
console.log(` ${BOLD} Active codes${RESET} ${stats.activeCodes}`);
|
|
102
|
+
console.log(` ${BOLD} Paired clients${RESET} ${stats.pairedClients}`);
|
|
103
|
+
console.log("");
|
|
104
|
+
console.log(` ${DIM}Subcommands: generate [label], list, revoke <target>, status${RESET}`);
|
|
105
|
+
}
|
|
106
|
+
async function pairing(args) {
|
|
107
|
+
let config;
|
|
108
|
+
try {
|
|
109
|
+
config = loadConfig();
|
|
110
|
+
} catch (err) {
|
|
111
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
112
|
+
console.error(`
|
|
113
|
+
${RED}Failed to load config:${RESET} ${message}`);
|
|
114
|
+
console.error(` ${DIM}Run ${TEAL}ch4p onboard${DIM} to set up ch4p.${RESET}
|
|
115
|
+
`);
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const subcommand = args[0] ?? "status";
|
|
120
|
+
const subArgs = args.slice(1);
|
|
121
|
+
console.log(`
|
|
122
|
+
${TEAL}${BOLD}ch4p Pairing${RESET}`);
|
|
123
|
+
console.log(separator());
|
|
124
|
+
console.log("");
|
|
125
|
+
switch (subcommand) {
|
|
126
|
+
case "generate":
|
|
127
|
+
handleGenerate(subArgs);
|
|
128
|
+
break;
|
|
129
|
+
case "list":
|
|
130
|
+
handleList();
|
|
131
|
+
break;
|
|
132
|
+
case "revoke":
|
|
133
|
+
handleRevoke(subArgs);
|
|
134
|
+
break;
|
|
135
|
+
case "status":
|
|
136
|
+
handleStatus(config.gateway.requirePairing, config.gateway.port);
|
|
137
|
+
break;
|
|
138
|
+
default:
|
|
139
|
+
console.log(` ${RED}Unknown subcommand: ${subcommand}${RESET}`);
|
|
140
|
+
console.log(` ${DIM}Available: generate, list, revoke, status${RESET}`);
|
|
141
|
+
process.exitCode = 1;
|
|
142
|
+
}
|
|
143
|
+
console.log("");
|
|
144
|
+
}
|
|
145
|
+
export {
|
|
146
|
+
pairing
|
|
147
|
+
};
|