quvur-dev 1.0.0 → 1.0.2
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/{index.cjs → index.js} +148 -127
- package/package.json +21 -4
- package/dist/index.d.cts +0 -1
|
@@ -1,61 +1,92 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
-
mod
|
|
24
|
-
));
|
|
25
2
|
|
|
26
3
|
// src/commands/index.ts
|
|
27
|
-
|
|
4
|
+
import { Command as Command6 } from "commander";
|
|
28
5
|
|
|
29
6
|
// src/core/ws-client.ts
|
|
30
|
-
|
|
7
|
+
import { WebSocket } from "ws";
|
|
31
8
|
|
|
32
9
|
// src/utils/config.ts
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
10
|
+
import * as path from "path";
|
|
11
|
+
import * as fs from "fs";
|
|
12
|
+
import * as os from "os";
|
|
36
13
|
|
|
37
14
|
// src/utils/logger.ts
|
|
38
|
-
|
|
15
|
+
import chalk from "chalk";
|
|
39
16
|
var logger = {
|
|
40
|
-
info: (...msg) => console.log(
|
|
41
|
-
next: (...msg) => console.log(
|
|
42
|
-
success: (...msg) => console.log(
|
|
43
|
-
error: (...msg) => console.error(
|
|
44
|
-
debug: (...msg) => console.debug(
|
|
45
|
-
warn: (...msg) => console.warn(
|
|
17
|
+
info: (...msg) => console.log(chalk.blue("[\u2139]"), ...msg),
|
|
18
|
+
next: (...msg) => console.log(chalk.green("[\u2192]"), ...msg),
|
|
19
|
+
success: (...msg) => console.log(chalk.green("[\u2714]"), ...msg),
|
|
20
|
+
error: (...msg) => console.error(chalk.red("[\u2716]"), ...msg),
|
|
21
|
+
debug: (...msg) => console.debug(chalk.bgRed("[debug]"), ...msg),
|
|
22
|
+
warn: (...msg) => console.warn(chalk.bgYellowBright("[warn]"), ...msg),
|
|
46
23
|
log: (...msg) => console.log(...msg)
|
|
47
24
|
};
|
|
48
25
|
|
|
26
|
+
// src/utils/default-config.ts
|
|
27
|
+
var defaultConfig = {
|
|
28
|
+
name: "quvur",
|
|
29
|
+
description: "Quvur CLI \u2014 simple and fast HTTP/TCP tunneling tool for exposing local services to the internet.",
|
|
30
|
+
version: "1.0.2",
|
|
31
|
+
wsBaseUrl: "wss://ws.livee.uz",
|
|
32
|
+
apiBaseUrl: "https://livee.uz",
|
|
33
|
+
auth: {
|
|
34
|
+
accessToken: null,
|
|
35
|
+
refreshToken: null
|
|
36
|
+
},
|
|
37
|
+
defaults: {
|
|
38
|
+
protocol: "http",
|
|
39
|
+
autoReconnect: true
|
|
40
|
+
},
|
|
41
|
+
usage: "<command> [options]",
|
|
42
|
+
help: {
|
|
43
|
+
intro: "Expose your local development server to the internet in seconds.",
|
|
44
|
+
examples: [
|
|
45
|
+
"quvur http 3000",
|
|
46
|
+
"quvur tcp 22",
|
|
47
|
+
"quvur http 3000 -s myapp",
|
|
48
|
+
"quvur auth",
|
|
49
|
+
"quvur config --reset"
|
|
50
|
+
],
|
|
51
|
+
commands: {
|
|
52
|
+
http: {
|
|
53
|
+
description: "Start an HTTP tunnel to expose a local web server.",
|
|
54
|
+
usage: "http <port> [options]",
|
|
55
|
+
examples: ["quvur http 3000", "quvur http 5173 -s myapp"]
|
|
56
|
+
},
|
|
57
|
+
tcp: {
|
|
58
|
+
description: "Start a raw TCP tunnel to expose any TCP service.",
|
|
59
|
+
usage: "tcp <port> [options]",
|
|
60
|
+
examples: ["quvur tcp 22", "quvur tcp 5432"]
|
|
61
|
+
},
|
|
62
|
+
auth: {
|
|
63
|
+
description: "Authenticate with Quvur server and store access token locally.",
|
|
64
|
+
usage: "auth",
|
|
65
|
+
examples: ["quvur auth"]
|
|
66
|
+
},
|
|
67
|
+
logout: {
|
|
68
|
+
description: "Remove stored authentication token.",
|
|
69
|
+
usage: "logout",
|
|
70
|
+
examples: ["quvur logout"]
|
|
71
|
+
},
|
|
72
|
+
config: {
|
|
73
|
+
description: "Load config file.",
|
|
74
|
+
usage: "config",
|
|
75
|
+
examples: ["quvur config", "quvur config --reset"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
telemetry: {
|
|
80
|
+
enabled: false
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
49
84
|
// src/utils/config.ts
|
|
50
|
-
var localConfigPath = path.join(process.cwd(), "config.json");
|
|
51
85
|
var configDir = path.join(os.homedir(), ".quvur");
|
|
52
86
|
var configPath = path.join(os.homedir(), ".quvur", "config.json");
|
|
53
87
|
var loadConfig = () => {
|
|
54
88
|
if (!fs.existsSync(configPath)) {
|
|
55
|
-
|
|
56
|
-
return loadConfigFromLocal();
|
|
57
|
-
}
|
|
58
|
-
throw new Error("Config file not found. Run `quvur auth` first.");
|
|
89
|
+
return loadConfigFromLocal();
|
|
59
90
|
}
|
|
60
91
|
const raw = fs.readFileSync(configPath, "utf-8");
|
|
61
92
|
try {
|
|
@@ -66,15 +97,14 @@ var loadConfig = () => {
|
|
|
66
97
|
}
|
|
67
98
|
};
|
|
68
99
|
var loadConfigFromLocal = () => {
|
|
69
|
-
const raw = fs.readFileSync(localConfigPath, "utf-8");
|
|
70
100
|
try {
|
|
71
|
-
const
|
|
101
|
+
const raw = JSON.stringify(defaultConfig, null, 2);
|
|
72
102
|
fs.mkdirSync(configDir, { recursive: true });
|
|
73
103
|
fs.writeFileSync(configPath, raw);
|
|
74
|
-
return
|
|
104
|
+
return defaultConfig;
|
|
75
105
|
} catch (error) {
|
|
76
106
|
logger.error(error);
|
|
77
|
-
throw new Error("
|
|
107
|
+
throw new Error("Failed to load default config file");
|
|
78
108
|
}
|
|
79
109
|
};
|
|
80
110
|
var saveConfig = (config2) => {
|
|
@@ -83,7 +113,7 @@ var saveConfig = (config2) => {
|
|
|
83
113
|
var config = loadConfig();
|
|
84
114
|
|
|
85
115
|
// src/auth/token-manager.ts
|
|
86
|
-
|
|
116
|
+
import axios, { AxiosError } from "axios";
|
|
87
117
|
var TokenManager = class {
|
|
88
118
|
async getValidAccessToken() {
|
|
89
119
|
const { accessToken, refreshToken } = config.auth;
|
|
@@ -129,7 +159,7 @@ var TokenManager = class {
|
|
|
129
159
|
}
|
|
130
160
|
async refreshTokens(refreshToken) {
|
|
131
161
|
try {
|
|
132
|
-
const response = await
|
|
162
|
+
const response = await axios.post(
|
|
133
163
|
`${config.apiBaseUrl}/auth/refresh-token`,
|
|
134
164
|
{ refresh_token: refreshToken }
|
|
135
165
|
);
|
|
@@ -141,7 +171,7 @@ var TokenManager = class {
|
|
|
141
171
|
saveConfig(config);
|
|
142
172
|
return tokens.access_token;
|
|
143
173
|
} catch (error) {
|
|
144
|
-
if (error instanceof
|
|
174
|
+
if (error instanceof AxiosError) {
|
|
145
175
|
const errorData = error.response?.data;
|
|
146
176
|
if (!errorData) throw error;
|
|
147
177
|
throw new Error(errorData.error);
|
|
@@ -151,7 +181,7 @@ var TokenManager = class {
|
|
|
151
181
|
}
|
|
152
182
|
async tokenExchange(accessToken) {
|
|
153
183
|
try {
|
|
154
|
-
const response = await
|
|
184
|
+
const response = await axios.post(
|
|
155
185
|
`${config.apiBaseUrl}/auth/token-exchange`,
|
|
156
186
|
{
|
|
157
187
|
access_token: accessToken
|
|
@@ -160,7 +190,7 @@ var TokenManager = class {
|
|
|
160
190
|
const { data } = response;
|
|
161
191
|
return data.access_token;
|
|
162
192
|
} catch (error) {
|
|
163
|
-
if (error instanceof
|
|
193
|
+
if (error instanceof AxiosError) {
|
|
164
194
|
const errorData = error.response?.data;
|
|
165
195
|
if (!errorData) throw error;
|
|
166
196
|
throw new Error(errorData.error);
|
|
@@ -179,7 +209,7 @@ var connectWebSocket = async (data) => {
|
|
|
179
209
|
});
|
|
180
210
|
const accessToken = await tokenManager.getValidAccessToken();
|
|
181
211
|
if (!accessToken) return null;
|
|
182
|
-
const ws = new
|
|
212
|
+
const ws = new WebSocket(url, {
|
|
183
213
|
headers: {
|
|
184
214
|
Authorization: `Bearer ${accessToken}`
|
|
185
215
|
}
|
|
@@ -188,8 +218,8 @@ var connectWebSocket = async (data) => {
|
|
|
188
218
|
};
|
|
189
219
|
|
|
190
220
|
// src/transport/http-tunnel.ts
|
|
191
|
-
|
|
192
|
-
|
|
221
|
+
import http from "http";
|
|
222
|
+
import "ws";
|
|
193
223
|
|
|
194
224
|
// src/@protocol/binary-frame.ts
|
|
195
225
|
var encodeBinaryFrame = (frame) => {
|
|
@@ -209,13 +239,13 @@ var decodeBinaryFrame = (buffer) => {
|
|
|
209
239
|
};
|
|
210
240
|
|
|
211
241
|
// src/@protocol/schemas/index.ts
|
|
212
|
-
|
|
242
|
+
import z6 from "zod";
|
|
213
243
|
|
|
214
244
|
// src/@protocol/schemas/request.schema.ts
|
|
215
|
-
|
|
245
|
+
import z2 from "zod";
|
|
216
246
|
|
|
217
247
|
// src/@protocol/schemas/base.schema.ts
|
|
218
|
-
|
|
248
|
+
import z from "zod";
|
|
219
249
|
|
|
220
250
|
// src/@protocol/constants.ts
|
|
221
251
|
var PROTOCOL_VERSION = "1.0.0";
|
|
@@ -233,55 +263,55 @@ var JsonMessageType = /* @__PURE__ */ ((JsonMessageType2) => {
|
|
|
233
263
|
})(JsonMessageType || {});
|
|
234
264
|
|
|
235
265
|
// src/@protocol/schemas/base.schema.ts
|
|
236
|
-
var baseSchema =
|
|
237
|
-
version:
|
|
238
|
-
type:
|
|
266
|
+
var baseSchema = z.object({
|
|
267
|
+
version: z.string().default(PROTOCOL_VERSION),
|
|
268
|
+
type: z.enum(JsonMessageType)
|
|
239
269
|
});
|
|
240
270
|
|
|
241
271
|
// src/@protocol/schemas/request.schema.ts
|
|
242
272
|
var requestStartSchema = baseSchema.extend({
|
|
243
|
-
type:
|
|
244
|
-
requestId:
|
|
245
|
-
method:
|
|
246
|
-
url:
|
|
247
|
-
headers:
|
|
273
|
+
type: z2.literal("request-start" /* RequestStart */),
|
|
274
|
+
requestId: z2.string(),
|
|
275
|
+
method: z2.string(),
|
|
276
|
+
url: z2.string(),
|
|
277
|
+
headers: z2.record(z2.string(), z2.string())
|
|
248
278
|
});
|
|
249
279
|
var requestEndSchema = baseSchema.extend({
|
|
250
|
-
type:
|
|
251
|
-
requestId:
|
|
280
|
+
type: z2.literal("request-end" /* RequestEnd */),
|
|
281
|
+
requestId: z2.string()
|
|
252
282
|
});
|
|
253
283
|
|
|
254
284
|
// src/@protocol/schemas/response.schema.ts
|
|
255
|
-
|
|
285
|
+
import z3 from "zod";
|
|
256
286
|
var responseStartSchema = baseSchema.extend({
|
|
257
|
-
type:
|
|
258
|
-
requestId:
|
|
259
|
-
statusCode:
|
|
260
|
-
headers:
|
|
287
|
+
type: z3.literal("response-start" /* ResponseStart */),
|
|
288
|
+
requestId: z3.string(),
|
|
289
|
+
statusCode: z3.number().int().min(100).max(599),
|
|
290
|
+
headers: z3.record(z3.string(), z3.string())
|
|
261
291
|
});
|
|
262
292
|
var responseEndSchema = baseSchema.extend({
|
|
263
|
-
type:
|
|
264
|
-
requestId:
|
|
293
|
+
type: z3.literal("response-end" /* ResponseEnd */),
|
|
294
|
+
requestId: z3.string()
|
|
265
295
|
});
|
|
266
296
|
|
|
267
297
|
// src/@protocol/schemas/tunnel.schema.ts
|
|
268
|
-
|
|
298
|
+
import z4 from "zod";
|
|
269
299
|
var tunnelCreatedSchema = baseSchema.extend({
|
|
270
|
-
type:
|
|
271
|
-
tunnelId:
|
|
272
|
-
subdomain:
|
|
273
|
-
host:
|
|
300
|
+
type: z4.literal("tunnel-created" /* TunnelCreated */),
|
|
301
|
+
tunnelId: z4.string(),
|
|
302
|
+
subdomain: z4.string(),
|
|
303
|
+
host: z4.string()
|
|
274
304
|
});
|
|
275
305
|
|
|
276
306
|
// src/@protocol/schemas/error-schema.ts
|
|
277
|
-
|
|
307
|
+
import z5 from "zod";
|
|
278
308
|
var errorSchema = baseSchema.extend({
|
|
279
|
-
type:
|
|
280
|
-
message:
|
|
309
|
+
type: z5.literal("error" /* Error */),
|
|
310
|
+
message: z5.string()
|
|
281
311
|
});
|
|
282
312
|
|
|
283
313
|
// src/@protocol/schemas/index.ts
|
|
284
|
-
var jsonMessageSchema =
|
|
314
|
+
var jsonMessageSchema = z6.discriminatedUnion("type", [
|
|
285
315
|
requestStartSchema,
|
|
286
316
|
requestEndSchema,
|
|
287
317
|
responseStartSchema,
|
|
@@ -291,40 +321,40 @@ var jsonMessageSchema = import_zod6.default.discriminatedUnion("type", [
|
|
|
291
321
|
]);
|
|
292
322
|
|
|
293
323
|
// src/@protocol/logger/index.ts
|
|
294
|
-
|
|
324
|
+
import chalk2 from "chalk";
|
|
295
325
|
var protoLogger = {
|
|
296
326
|
info: (...msg) => console.log(
|
|
297
|
-
|
|
327
|
+
chalk2.blue("[protocol:info]"),
|
|
298
328
|
...msg,
|
|
299
329
|
(/* @__PURE__ */ new Date()).toLocaleString(),
|
|
300
330
|
"\n"
|
|
301
331
|
),
|
|
302
332
|
next: (...msg) => console.log(
|
|
303
|
-
|
|
333
|
+
chalk2.green("[protocol:next]"),
|
|
304
334
|
...msg,
|
|
305
335
|
(/* @__PURE__ */ new Date()).toLocaleString(),
|
|
306
336
|
"\n"
|
|
307
337
|
),
|
|
308
338
|
success: (...msg) => console.log(
|
|
309
|
-
|
|
339
|
+
chalk2.green("[protocol:success]"),
|
|
310
340
|
...msg,
|
|
311
341
|
(/* @__PURE__ */ new Date()).toLocaleString(),
|
|
312
342
|
"\n"
|
|
313
343
|
),
|
|
314
344
|
error: (...msg) => console.error(
|
|
315
|
-
|
|
345
|
+
chalk2.red("[protocol:error]"),
|
|
316
346
|
...msg,
|
|
317
347
|
(/* @__PURE__ */ new Date()).toLocaleString(),
|
|
318
348
|
"\n"
|
|
319
349
|
),
|
|
320
350
|
debug: (...msg) => console.debug(
|
|
321
|
-
|
|
351
|
+
chalk2.bgRed("[protocol:debug]"),
|
|
322
352
|
...msg,
|
|
323
353
|
(/* @__PURE__ */ new Date()).toLocaleString(),
|
|
324
354
|
"\n"
|
|
325
355
|
),
|
|
326
356
|
warn: (...msg) => console.warn(
|
|
327
|
-
|
|
357
|
+
chalk2.bgYellowBright("[protocol:warn]"),
|
|
328
358
|
...msg,
|
|
329
359
|
(/* @__PURE__ */ new Date()).toLocaleString(),
|
|
330
360
|
"\n"
|
|
@@ -353,7 +383,7 @@ var parseFrame = (data, isBinary) => {
|
|
|
353
383
|
};
|
|
354
384
|
|
|
355
385
|
// src/@protocol/contract.ts
|
|
356
|
-
|
|
386
|
+
import "ws";
|
|
357
387
|
function createProtocolSide(incomingSchema, outgoingSchema) {
|
|
358
388
|
return {
|
|
359
389
|
validateIncoming: (data) => {
|
|
@@ -380,16 +410,16 @@ function createProtocolSide(incomingSchema, outgoingSchema) {
|
|
|
380
410
|
}
|
|
381
411
|
|
|
382
412
|
// src/@protocol/directions/client-to-server.ts
|
|
383
|
-
|
|
384
|
-
var clientToServerSchema =
|
|
413
|
+
import z7 from "zod";
|
|
414
|
+
var clientToServerSchema = z7.discriminatedUnion("type", [
|
|
385
415
|
responseStartSchema,
|
|
386
416
|
responseEndSchema,
|
|
387
417
|
errorSchema
|
|
388
418
|
]);
|
|
389
419
|
|
|
390
420
|
// src/@protocol/directions/server-to-client.ts
|
|
391
|
-
|
|
392
|
-
var serverToClientSchema =
|
|
421
|
+
import z8 from "zod";
|
|
422
|
+
var serverToClientSchema = z8.discriminatedUnion("type", [
|
|
393
423
|
tunnelCreatedSchema,
|
|
394
424
|
requestStartSchema,
|
|
395
425
|
requestEndSchema,
|
|
@@ -443,7 +473,7 @@ var startHttpTransport = (ws, localPort) => {
|
|
|
443
473
|
return;
|
|
444
474
|
}
|
|
445
475
|
if (message.type === "request-start" /* RequestStart */) {
|
|
446
|
-
const localRequest =
|
|
476
|
+
const localRequest = http.request({
|
|
447
477
|
hostname: "127.0.0.1",
|
|
448
478
|
port: localPort,
|
|
449
479
|
method: message.method,
|
|
@@ -511,29 +541,29 @@ async function startHttpTunnel(data) {
|
|
|
511
541
|
}
|
|
512
542
|
|
|
513
543
|
// src/commands/validators/http.validator.ts
|
|
514
|
-
|
|
544
|
+
import { InvalidArgumentError } from "commander";
|
|
515
545
|
var validatePort = (value) => {
|
|
516
546
|
const parsed = Number(value);
|
|
517
547
|
if (!Number.isInteger(parsed)) {
|
|
518
|
-
throw new
|
|
548
|
+
throw new InvalidArgumentError("port must be an integer");
|
|
519
549
|
}
|
|
520
550
|
if (parsed <= 0 || parsed > 65535) {
|
|
521
|
-
throw new
|
|
551
|
+
throw new InvalidArgumentError("port must be between 1 and 65535");
|
|
522
552
|
}
|
|
523
553
|
return parsed;
|
|
524
554
|
};
|
|
525
555
|
var validateSubdomain = (value) => {
|
|
526
556
|
if (value.length < 3) {
|
|
527
|
-
throw new
|
|
557
|
+
throw new InvalidArgumentError(
|
|
528
558
|
"subdomain must be at least 3 characters long"
|
|
529
559
|
);
|
|
530
560
|
}
|
|
531
561
|
if (value.length > 63) {
|
|
532
|
-
throw new
|
|
562
|
+
throw new InvalidArgumentError("subdomain must be less than 63 characters");
|
|
533
563
|
}
|
|
534
564
|
const regex = /^[a-z0-9][a-z0-9-]*$/;
|
|
535
565
|
if (!regex.test(value)) {
|
|
536
|
-
throw new
|
|
566
|
+
throw new InvalidArgumentError(
|
|
537
567
|
"subdomain must contain only lowercase letters, numbers, and hyphens"
|
|
538
568
|
);
|
|
539
569
|
}
|
|
@@ -557,7 +587,7 @@ var registerHttpCommand = (program2, config2) => {
|
|
|
557
587
|
};
|
|
558
588
|
|
|
559
589
|
// src/commands/help.ts
|
|
560
|
-
|
|
590
|
+
import "commander";
|
|
561
591
|
var registerHelpSubcommand = (program2) => {
|
|
562
592
|
program2.addHelpText(
|
|
563
593
|
"after",
|
|
@@ -570,25 +600,17 @@ Examples:
|
|
|
570
600
|
};
|
|
571
601
|
|
|
572
602
|
// src/commands/tcp.ts
|
|
573
|
-
|
|
574
|
-
var registerTcpCommand = (program2, config2) => {
|
|
575
|
-
program2.command("tcp").description(config2.description).usage(config2.usage).argument("<port>", "Local TCP port to expose").option("-t <token>", "Override auth token").addHelpText("after", `
|
|
576
|
-
Examples:
|
|
577
|
-
${config2.examples.join("\n ")}`).action((port, options) => {
|
|
578
|
-
logger.success("TCP tunnel starting on port:", port);
|
|
579
|
-
logger.info("Options:", options);
|
|
580
|
-
});
|
|
581
|
-
};
|
|
603
|
+
import "commander";
|
|
582
604
|
|
|
583
605
|
// src/commands/auth.ts
|
|
584
|
-
|
|
606
|
+
import "commander";
|
|
585
607
|
|
|
586
608
|
// src/auth/auth-service.ts
|
|
587
|
-
|
|
609
|
+
import axios2, { AxiosError as AxiosError2 } from "axios";
|
|
588
610
|
|
|
589
611
|
// src/events/auth-emitter.ts
|
|
590
|
-
|
|
591
|
-
var AuthEventEmitter = class extends
|
|
612
|
+
import { EventEmitter } from "events";
|
|
613
|
+
var AuthEventEmitter = class extends EventEmitter {
|
|
592
614
|
emit(event, payload) {
|
|
593
615
|
return super.emit(event, payload);
|
|
594
616
|
}
|
|
@@ -603,7 +625,7 @@ var AuthService = class {
|
|
|
603
625
|
async startLogin() {
|
|
604
626
|
try {
|
|
605
627
|
authEmitter.emit("auth:start");
|
|
606
|
-
const response = await
|
|
628
|
+
const response = await axios2.post(
|
|
607
629
|
`${config.apiBaseUrl}/auth/github/device-start`
|
|
608
630
|
);
|
|
609
631
|
const { data } = response;
|
|
@@ -621,7 +643,7 @@ var AuthService = class {
|
|
|
621
643
|
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
|
|
622
644
|
while (Date.now() < expiresAt.getTime()) {
|
|
623
645
|
try {
|
|
624
|
-
const response = await
|
|
646
|
+
const response = await axios2.post(
|
|
625
647
|
`${config.apiBaseUrl}/auth/github/device-poll`,
|
|
626
648
|
{ device_code: deviceCode }
|
|
627
649
|
);
|
|
@@ -633,7 +655,7 @@ var AuthService = class {
|
|
|
633
655
|
});
|
|
634
656
|
return authEmitter.emit("auth:completed");
|
|
635
657
|
} catch (error) {
|
|
636
|
-
if (error instanceof
|
|
658
|
+
if (error instanceof AxiosError2) {
|
|
637
659
|
const errorData = error.response?.data;
|
|
638
660
|
if (!errorData) {
|
|
639
661
|
authEmitter.emit("auth:error", error);
|
|
@@ -667,7 +689,7 @@ var AuthService = class {
|
|
|
667
689
|
}
|
|
668
690
|
async logout(refreshToken) {
|
|
669
691
|
try {
|
|
670
|
-
const response = await
|
|
692
|
+
const response = await axios2.post(
|
|
671
693
|
`${config.apiBaseUrl}/auth/logout`,
|
|
672
694
|
{
|
|
673
695
|
refresh_token: refreshToken
|
|
@@ -680,7 +702,7 @@ var AuthService = class {
|
|
|
680
702
|
);
|
|
681
703
|
return true;
|
|
682
704
|
} catch (error) {
|
|
683
|
-
if (error instanceof
|
|
705
|
+
if (error instanceof AxiosError2) {
|
|
684
706
|
const errorData = error.response?.data;
|
|
685
707
|
if (!errorData) throw error;
|
|
686
708
|
throw new Error(`Logout failed: ${errorData.error}`);
|
|
@@ -692,7 +714,7 @@ var AuthService = class {
|
|
|
692
714
|
var authService = new AuthService();
|
|
693
715
|
|
|
694
716
|
// src/commands/auth.ts
|
|
695
|
-
|
|
717
|
+
import chalk3 from "chalk";
|
|
696
718
|
var registerAuthCommand = (program2, commandConfig) => {
|
|
697
719
|
program2.command("auth").description(commandConfig.description).usage(commandConfig.usage).addHelpText(
|
|
698
720
|
"after",
|
|
@@ -705,13 +727,13 @@ Examples:
|
|
|
705
727
|
});
|
|
706
728
|
authEmitter.on("auth:code", ({ user_code, verification_uri }) => {
|
|
707
729
|
logger.info("Please visit the following URL to authorize the CLI:");
|
|
708
|
-
logger.log(
|
|
709
|
-
logger.info(`Enter the code: ${
|
|
730
|
+
logger.log(chalk3.bold.cyan(verification_uri));
|
|
731
|
+
logger.info(`Enter the code: ${chalk3.bold.yellow(user_code)}`);
|
|
710
732
|
});
|
|
711
733
|
authEmitter.on("auth:success", ({ accessToken, refreshToken, user }) => {
|
|
712
734
|
tokenManager.saveTokens(accessToken, refreshToken);
|
|
713
735
|
logger.success(
|
|
714
|
-
`Successfully authenticated as ${
|
|
736
|
+
`Successfully authenticated as ${chalk3.bold.green(`${user.name} (${user.username})`)}!`
|
|
715
737
|
);
|
|
716
738
|
});
|
|
717
739
|
authEmitter.on("auth:error", (error) => {
|
|
@@ -730,7 +752,7 @@ Examples:
|
|
|
730
752
|
};
|
|
731
753
|
|
|
732
754
|
// src/commands/logout.ts
|
|
733
|
-
|
|
755
|
+
import "commander";
|
|
734
756
|
var registerLogoutCommand = (program2, commandConfig) => {
|
|
735
757
|
program2.command("logout").description(commandConfig.description).usage(commandConfig.usage).addHelpText("after", `Examples:
|
|
736
758
|
${commandConfig.examples.join("\n ")}`).action(async () => {
|
|
@@ -753,7 +775,7 @@ var registerLogoutCommand = (program2, commandConfig) => {
|
|
|
753
775
|
};
|
|
754
776
|
|
|
755
777
|
// src/commands/config.ts
|
|
756
|
-
|
|
778
|
+
import "commander";
|
|
757
779
|
var registerConfigCommand = (program2, config2) => {
|
|
758
780
|
program2.command("config").description(config2.description).usage(config2.usage).addHelpText("after", `Examples:
|
|
759
781
|
${config2.examples.join("\n ")}`).option("-r, --reset", "Reset config file options to default.").action((options) => {
|
|
@@ -768,13 +790,12 @@ var registerConfigCommand = (program2, config2) => {
|
|
|
768
790
|
};
|
|
769
791
|
|
|
770
792
|
// src/commands/index.ts
|
|
771
|
-
var program = new
|
|
793
|
+
var program = new Command6();
|
|
772
794
|
program.name(config.name).version(config.version).description(config.description).usage(config.usage).configureOutput({
|
|
773
795
|
writeOut: (message) => logger.info(message),
|
|
774
796
|
writeErr: (message) => logger.error(message)
|
|
775
797
|
});
|
|
776
798
|
registerHttpCommand(program, config.help.commands.http);
|
|
777
|
-
registerTcpCommand(program, config.help.commands.tcp);
|
|
778
799
|
registerAuthCommand(program, config.help.commands.auth);
|
|
779
800
|
registerLogoutCommand(program, config.help.commands.logout);
|
|
780
801
|
registerConfigCommand(program, config.help.commands.config);
|
package/package.json
CHANGED
|
@@ -1,19 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quvur-dev",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "A lightweight developer tunneling CLI that securely exposes local HTTP and TCP services to the internet via a remote gateway.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "Muhammadali Yuldoshev <mukhammadaliweb@gmail.com>",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"cli",
|
|
12
|
+
"tunnel",
|
|
13
|
+
"tcp-tunnel",
|
|
14
|
+
"http-tunnel",
|
|
15
|
+
"reverse-proxy",
|
|
16
|
+
"port-forwarding",
|
|
17
|
+
"local-development",
|
|
18
|
+
"developer-tools",
|
|
19
|
+
"devops",
|
|
20
|
+
"networking",
|
|
21
|
+
"websocket-tunnel"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20"
|
|
25
|
+
},
|
|
9
26
|
"bin": {
|
|
10
|
-
"quvur": "dist/index.
|
|
27
|
+
"quvur": "dist/index.js"
|
|
11
28
|
},
|
|
12
29
|
"files": [
|
|
13
30
|
"dist"
|
|
14
31
|
],
|
|
15
32
|
"scripts": {
|
|
16
|
-
"build": "npx tsup src/index.ts --dts",
|
|
33
|
+
"build": "npx tsup src/index.ts --format esm --dts",
|
|
17
34
|
"start:dev": "tsx --watch src/index.ts",
|
|
18
35
|
"prepublishOnly": "npm run build"
|
|
19
36
|
},
|
package/dist/index.d.cts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|