@dutodev/cli 1.1.0 → 1.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.
@@ -0,0 +1,462 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ../shared/src/names.ts
4
+ var EMAIL_SENDING_SUBDOMAINS = ["send"];
5
+ var RESERVED_NAMES = [
6
+ "www",
7
+ "api",
8
+ "app",
9
+ "dash",
10
+ "admin",
11
+ "docs",
12
+ "status",
13
+ "mail",
14
+ "custom",
15
+ "cname",
16
+ "duto",
17
+ "auth",
18
+ "login",
19
+ "signup",
20
+ "invite",
21
+ "static",
22
+ "assets",
23
+ "cdn",
24
+ "help",
25
+ "support",
26
+ "blog",
27
+ ...EMAIL_SENDING_SUBDOMAINS
28
+ ];
29
+ var MAX_NAME = 40;
30
+ var FORMAT = /^[a-z0-9]+$/;
31
+ function normalizeName(input) {
32
+ return input.trim().toLowerCase();
33
+ }
34
+ function validateName(name, max = MAX_NAME) {
35
+ if (name.length === 0 || name.length > max) return { ok: false, reason: "length" };
36
+ if (!FORMAT.test(name)) return { ok: false, reason: "format" };
37
+ if (RESERVED_NAMES.includes(name)) return { ok: false, reason: "reserved" };
38
+ return { ok: true };
39
+ }
40
+
41
+ // ../shared/src/places.ts
42
+ var PLACES = {
43
+ AAE: ["Annaba", "Algeria"],
44
+ ABJ: ["Abidjan", "C\xF4te d\u2019Ivoire"],
45
+ ABQ: ["Albuquerque", "United States"],
46
+ ACC: ["Accra", "Ghana"],
47
+ ACX: ["Xingyi", "China"],
48
+ ADB: ["Izmir", "Turkey"],
49
+ ADD: ["Addis Ababa", "Ethiopia"],
50
+ ADL: ["Adelaide", "Australia"],
51
+ AGR: ["Agra", "India"],
52
+ AIP: ["Jalandhar", "India"],
53
+ AKL: ["Auckland", "New Zealand"],
54
+ AKX: ["Aktobe", "Kazakhstan"],
55
+ ALA: ["Almaty", "Kazakhstan"],
56
+ ALG: ["Algiers", "Algeria"],
57
+ AMD: ["Ahmedabad", "India"],
58
+ AMM: ["Amman", "Jordan"],
59
+ AMS: ["Amsterdam", "Netherlands"],
60
+ ANC: ["Anchorage", "United States"],
61
+ ARI: ["Arica", "Chile"],
62
+ ARN: ["Stockholm", "Sweden"],
63
+ ARU: ["Aracatuba", "Brazil"],
64
+ ASK: ["Yamoussoukro", "C\xF4te d\u2019Ivoire"],
65
+ ASU: ["Asunci\xF3n", "Paraguay"],
66
+ ATH: ["Athens", "Greece"],
67
+ ATL: ["Atlanta", "United States"],
68
+ AUS: ["Austin", "United States"],
69
+ AVA: ["Anshun", "China"],
70
+ BAH: ["Manama", "Bahrain"],
71
+ BAQ: ["Barranquilla", "Colombia"],
72
+ BBI: ["Bhubaneswar", "India"],
73
+ BCN: ["Barcelona", "Spain"],
74
+ BDQ: ["Jamnagar", "India"],
75
+ BEG: ["Belgrade", "Serbia"],
76
+ BEL: ["Bel\xE9m", "Brazil"],
77
+ BEY: ["Beirut", "Lebanon"],
78
+ BGI: ["Bridgetown", "Barbados"],
79
+ BGR: ["Bangor", "United States"],
80
+ BGW: ["Baghdad", "Iraq"],
81
+ BKK: ["Bangkok", "Thailand"],
82
+ BLR: ["Bangalore", "India"],
83
+ BNA: ["Nashville", "United States"],
84
+ BNE: ["Brisbane", "Australia"],
85
+ BOD: ["Bordeaux", "France"],
86
+ BOG: ["Bogot\xE1", "Colombia"],
87
+ BOM: ["Mumbai", "India"],
88
+ BOS: ["Boston", "United States"],
89
+ BRU: ["Brussels", "Belgium"],
90
+ BSB: ["Brasilia", "Brazil"],
91
+ BSR: ["Basra", "Iraq"],
92
+ BTS: ["Bratislava", "Slovakia"],
93
+ BUD: ["Budapest", "Hungary"],
94
+ BWN: ["Bandar Seri Begawan", "Brunei"],
95
+ CAI: ["Cairo", "Egypt"],
96
+ CAN: ["Guangzhou", "China"],
97
+ CAW: ["Campos dos Goytacazes", "Brazil"],
98
+ CBR: ["Canberra", "Australia"],
99
+ CCU: ["Kolkata", "India"],
100
+ CDG: ["Paris", "France"],
101
+ CEB: ["Cebu", "Philippines"],
102
+ CFC: ["Cacador", "Brazil"],
103
+ CGB: ["Cuiaba", "Brazil"],
104
+ CGD: ["Changde", "China"],
105
+ CGK: ["Jakarta", "Indonesia"],
106
+ CGO: ["Zhengzhou", "China"],
107
+ CGP: ["Chittagong", "Bangladesh"],
108
+ CGY: ["Cagayan de Oro", "Philippines"],
109
+ CHC: ["Christchurch", "New Zealand"],
110
+ CJB: ["Coimbatore", "India"],
111
+ CKG: ["Chongqing", "China"],
112
+ CLE: ["Cleveland", "United States"],
113
+ CLO: ["Cali", "Colombia"],
114
+ CLT: ["Charlotte", "United States"],
115
+ CMB: ["Colombo", "Sri Lanka"],
116
+ CMH: ["Columbus", "United States"],
117
+ CNF: ["Belo Horizonte", "Brazil"],
118
+ CNN: ["Kannur", "India"],
119
+ CNX: ["Chiang Mai", "Thailand"],
120
+ COK: ["Kochi", "India"],
121
+ COR: ["C\xF3rdoba", "Argentina"],
122
+ CPH: ["Copenhagen", "Denmark"],
123
+ CPT: ["Cape Town", "South Africa"],
124
+ CRK: ["Tarlac City", "Philippines"],
125
+ CSX: ["Changsha", "China"],
126
+ CTU: ["Chengdu", "China"],
127
+ CVG: ["Cincinnati", "United States"],
128
+ CWB: ["Curitiba", "Brazil"],
129
+ CZL: ["Constantine", "Algeria"],
130
+ CZX: ["Changzhou", "China"],
131
+ DAC: ["Dhaka", "Bangladesh"],
132
+ DAD: ["Da Nang", "Vietnam"],
133
+ DAR: ["Dar es Salaam", "Tanzania"],
134
+ DEL: ["New Delhi", "India"],
135
+ DEN: ["Denver", "United States"],
136
+ DFW: ["Dallas", "United States"],
137
+ DKR: ["Dakar", "Senegal"],
138
+ DLA: ["Douala", "Cameroon"],
139
+ DLC: ["Dalian", "China"],
140
+ DME: ["Moscow", "Russia"],
141
+ DMM: ["Dammam", "Saudi Arabia"],
142
+ DOH: ["Doha", "Qatar"],
143
+ DPS: ["Denpasar", "Indonesia"],
144
+ DTW: ["Detroit", "United States"],
145
+ DUB: ["Dublin", "Ireland"],
146
+ DUR: ["Durban", "South Africa"],
147
+ DUS: ["D\xFCsseldorf", "Germany"],
148
+ DXB: ["Dubai", "United Arab Emirates"],
149
+ DYU: ["Dushanbe", "Tajikistan"],
150
+ EBB: ["Kampala", "Uganda"],
151
+ EBL: ["Erbil", "Iraq"],
152
+ EVN: ["Yerevan", "Armenia"],
153
+ EWR: ["Newark", "United States"],
154
+ EZE: ["Buenos Aires", "Argentina"],
155
+ FCO: ["Rome", "Italy"],
156
+ FLN: ["Florianopolis", "Brazil"],
157
+ FOC: ["Fuzhou", "China"],
158
+ FOR: ["Fortaleza", "Brazil"],
159
+ FRA: ["Frankfurt", "Germany"],
160
+ FRU: ["Bishkek", "Kyrgyzstan"],
161
+ FSD: ["Sioux Falls", "United States"],
162
+ FUK: ["Fukuoka", "Japan"],
163
+ FUO: ["Foshan", "China"],
164
+ GBE: ["Gaborone", "Botswana"],
165
+ GDL: ["Guadalajara", "Mexico"],
166
+ GEO: ["Georgetown", "Guyana"],
167
+ GIG: ["Rio de Janeiro", "Brazil"],
168
+ GND: ["St. George's", "Grenada"],
169
+ GOT: ["Gothenburg", "Sweden"],
170
+ GRU: ["S\xE3o Paulo", "Brazil"],
171
+ GUA: ["Guatemala City", "Guatemala"],
172
+ GUM: ["Hagatna", "Guam"],
173
+ GVA: ["Geneva", "Switzerland"],
174
+ GYD: ["Baku", "Azerbaijan"],
175
+ GYE: ["Guayaquil", "Ecuador"],
176
+ GYN: ["Goiania", "Brazil"],
177
+ HAK: ["Chengmai", "China"],
178
+ HAM: ["Hamburg", "Germany"],
179
+ HAN: ["Hanoi", "Vietnam"],
180
+ HBA: ["Hobart", "Australia"],
181
+ HEL: ["Helsinki", "Finland"],
182
+ HFA: ["Haifa", "Israel"],
183
+ HGH: ["Shaoxing", "China"],
184
+ HKG: ["Hong Kong", null],
185
+ HNL: ["Honolulu", "United States"],
186
+ HRE: ["Harare", "Zimbabwe"],
187
+ HYD: ["Hyderabad", "India"],
188
+ HYN: ["Taizhou", "China"],
189
+ IAD: ["Ashburn", "United States"],
190
+ IAH: ["Houston", "United States"],
191
+ ICN: ["Seoul", "South Korea"],
192
+ IND: ["Indianapolis", "United States"],
193
+ ISB: ["Islamabad", "Pakistan"],
194
+ IST: ["Istanbul", "Turkey"],
195
+ ISU: ["Sulaymaniyah", "Iraq"],
196
+ IXC: ["Chandigarh", "India"],
197
+ JAI: ["\u201CJaipur\u201D", "India"],
198
+ JAX: ["Jacksonville", "United States"],
199
+ JDO: ["Juazeiro do Norte", "Brazil"],
200
+ JED: ["Jeddah", "Saudi Arabia"],
201
+ JHB: ["Johor Bahru", "Malaysia"],
202
+ JIB: ["Djibouti", "Djibouti"],
203
+ JNB: ["Johannesburg", "South Africa"],
204
+ JOG: ["Yogyakarta", "Indonesia"],
205
+ JOI: ["Joinville", "Brazil"],
206
+ JRG: ["Sambalpur", "India"],
207
+ JXG: ["Jiaxing", "China"],
208
+ KBP: ["Kyiv", "Ukraine"],
209
+ KCH: ["Kuching", "Malaysia"],
210
+ KEF: ["Reykjav\xEDk", "Iceland"],
211
+ KGL: ["Kigali", "Rwanda"],
212
+ KHH: ["Kaohsiung City", null],
213
+ KHI: ["Karachi", "Pakistan"],
214
+ KHN: ["Nanchang", "China"],
215
+ KIN: ["Kingston", "Jamaica"],
216
+ KIV: ["Chi\u0219in\u0103u", "Moldova"],
217
+ KIX: ["Osaka", "Japan"],
218
+ KMG: ["Kunming", "China"],
219
+ KNU: ["Kanpur", "India"],
220
+ KTM: ["Kathmandu", "Nepal"],
221
+ KUL: ["Kuala Lumpur", "Malaysia"],
222
+ KWE: ["Guiyang", "China"],
223
+ KWI: ["Kuwait City", "Kuwait"],
224
+ LAD: ["Luanda", "Angola"],
225
+ LAS: ["Las Vegas", "United States"],
226
+ LAX: ["Los Angeles", "United States"],
227
+ LCA: ["Nicosia", "Cyprus"],
228
+ LED: ["Saint Petersburg", "Russia"],
229
+ LHE: ["Lahore", "Pakistan"],
230
+ LHR: ["London", "United Kingdom"],
231
+ LHW: ["Lanzhou", "China"],
232
+ LIM: ["Lima", "Peru"],
233
+ LIS: ["Lisbon", "Portugal"],
234
+ LJU: ["Ljubljana", "Slovenia"],
235
+ LLK: ["Astara", "Azerbaijan"],
236
+ LLW: ["Lilongwe", "Malawi"],
237
+ LOS: ["Lagos", "Nigeria"],
238
+ LPB: ["La Paz", "Bolivia"],
239
+ LUH: ["Ludhiana", "India"],
240
+ LUN: ["Lusaka", "Zambia"],
241
+ LUX: ["Luxembourg City", "Luxembourg"],
242
+ LYA: ["Luoyang", "China"],
243
+ LYS: ["Lyon", "France"],
244
+ MAA: ["Chennai", "India"],
245
+ MAD: ["Madrid", "Spain"],
246
+ MAN: ["Manchester", "United Kingdom"],
247
+ MAO: ["Manaus", "Brazil"],
248
+ MBA: ["Mombasa", "Kenya"],
249
+ MCI: ["Kansas City", "United States"],
250
+ MCT: ["Muscat", "Oman"],
251
+ MDE: ["Medell\xEDn", "Colombia"],
252
+ MEL: ["Melbourne", "Australia"],
253
+ MEM: ["Memphis", "United States"],
254
+ MEX: ["Mexico City", "Mexico"],
255
+ MFM: ["Macau", null],
256
+ MIA: ["Miami", "United States"],
257
+ MLA: ["Valletta", "Malta"],
258
+ MLE: ["Male", "Maldives"],
259
+ MLG: ["Malang", "Indonesia"],
260
+ MNL: ["Manila", "Philippines"],
261
+ MPM: ["Maputo", "Mozambique"],
262
+ MRS: ["Marseille", "France"],
263
+ MRU: ["Port Louis", "Mauritius"],
264
+ MSP: ["Minneapolis", "United States"],
265
+ MSQ: ["Minsk", "Belarus"],
266
+ MUC: ["Munich", "Germany"],
267
+ MXP: ["Milan", "Italy"],
268
+ NAG: ["Nagpur", "India"],
269
+ NBO: ["Nairobi", "Kenya"],
270
+ NJF: ["Najaf", "Iraq"],
271
+ NOU: ["Noumea", "New Caledonia"],
272
+ NQN: ["Neuquen", "Argentina"],
273
+ NQZ: ["Astana", "Kazakhstan"],
274
+ NRT: ["Tokyo", "Japan"],
275
+ NVT: ["Timbo", "Brazil"],
276
+ OKA: ["Naha", "Japan"],
277
+ OKC: ["Oklahoma City", "United States"],
278
+ OMA: ["Omaha", "United States"],
279
+ ORD: ["Chicago", "United States"],
280
+ ORF: ["Norfolk", "United States"],
281
+ ORN: ["Oran", "Algeria"],
282
+ OSL: ["Oslo", "Norway"],
283
+ OTP: ["Bucharest", "Romania"],
284
+ OUA: ["Ouagadougou", "Burkina Faso"],
285
+ PAT: ["Patna", "India"],
286
+ PBH: ["Thimphu", "Bhutan"],
287
+ PBM: ["Paramaribo", "Suriname"],
288
+ PDX: ["Portland", "United States"],
289
+ PER: ["Perth", "Australia"],
290
+ PHL: ["Philadelphia", "United States"],
291
+ PHX: ["Phoenix", "United States"],
292
+ PIT: ["Pittsburgh", "United States"],
293
+ PKX: ["Beijing", "China"],
294
+ PMO: ["Palermo", "Italy"],
295
+ PMW: ["Palmas", "Brazil"],
296
+ PNH: ["Phnom Penh", "Cambodia"],
297
+ PNQ: ["Pune", "India"],
298
+ POA: ["Porto Alegre", "Brazil"],
299
+ POS: ["Port of Spain", "Trinidad & Tobago"],
300
+ PPT: ["Tahiti", "French Polynesia"],
301
+ PRG: ["Prague", "Czechia"],
302
+ PRN: ["Prishtine", "Kosovo"],
303
+ PTY: ["Panama City", "Panama"],
304
+ QRO: ["Queretaro", "Mexico"],
305
+ QWJ: ["Americana", "Brazil"],
306
+ RAO: ["Ribeirao Preto", "Brazil"],
307
+ RDU: ["Durham", "United States"],
308
+ REC: ["Recife", "Brazil"],
309
+ RIC: ["Richmond", "United States"],
310
+ RIX: ["Riga", "Latvia"],
311
+ RUH: ["Riyadh", "Saudi Arabia"],
312
+ RUN: ["Saint-Denis", "R\xE9union"],
313
+ SAN: ["San Diego", "United States"],
314
+ SAP: ["San Pedro Sula", "Honduras"],
315
+ SAT: ["San Antonio", "United States"],
316
+ SCL: ["Santiago", "Chile"],
317
+ SDQ: ["Santo Domingo", "Dominican Republic"],
318
+ SEA: ["Seattle", "United States"],
319
+ SFO: ["San Francisco", "United States"],
320
+ SGN: ["Ho Chi Minh City", "Vietnam"],
321
+ SHA: ["Shanghai", "China"],
322
+ SIN: ["Singapore", "Singapore"],
323
+ SJC: ["San Jose", "United States"],
324
+ SJK: ["S\xE3o Jos\xE9 dos Campos", "Brazil"],
325
+ SJO: ["San Jos\xE9", "Costa Rica"],
326
+ SJP: ["S\xE3o Jos\xE9 do Rio Preto", "Brazil"],
327
+ SJU: ["San Juan", "Puerto Rico"],
328
+ SJW: ["Hengshui", "China"],
329
+ SKG: ["Thessaloniki", "Greece"],
330
+ SKP: ["Skopje", "Macedonia"],
331
+ SLC: ["Salt Lake City", "United States"],
332
+ SMF: ["Sacramento", "United States"],
333
+ SOD: ["Sorocaba", "Brazil"],
334
+ SOF: ["Sofia", "Bulgaria"],
335
+ SSA: ["Salvador", "Brazil"],
336
+ STI: ["Santiago de los Caballeros", "Dominican Republic"],
337
+ STL: ["St. Louis", "United States"],
338
+ STR: ["Stuttgart", "Germany"],
339
+ SUV: ["Suva", "Fiji"],
340
+ SYD: ["Sydney", "Australia"],
341
+ SZX: ["Shenzhen", "China"],
342
+ TAO: ["Qingdao", "China"],
343
+ TBS: ["Tbilisi", "Georgia"],
344
+ TEN: ["Tongren", "China"],
345
+ TGU: ["Tegucigalpa", "Honduras"],
346
+ TIA: ["Tirana", "Albania"],
347
+ TLH: ["Tallahassee", "United States"],
348
+ TLL: ["Tallinn", "Estonia"],
349
+ TLV: ["Tel Aviv", "Israel"],
350
+ TNA: ["Jinan", "China"],
351
+ TNR: ["Antananarivo", "Madagascar"],
352
+ TPA: ["Tampa", "United States"],
353
+ TPE: ["Taipei", null],
354
+ TUN: ["Tunis", "Tunisia"],
355
+ TXL: ["Berlin", "Germany"],
356
+ TYN: ["Yangquan", "China"],
357
+ UDI: ["Uberlandia", "Brazil"],
358
+ UDR: ["Udaipur", "India"],
359
+ UIO: ["Quito", "Ecuador"],
360
+ ULN: ["Ulaanbaatar", "Mongolia"],
361
+ URT: ["Surat Thani", "Thailand"],
362
+ VCP: ["Campinas", "Brazil"],
363
+ VIE: ["Vienna", "Austria"],
364
+ VIX: ["Vitoria", "Brazil"],
365
+ VNO: ["Vilnius", "Lithuania"],
366
+ VTE: ["Vientiane", "Laos"],
367
+ WAW: ["Warsaw", "Poland"],
368
+ WDH: ["Windhoek", "Namibia"],
369
+ WLG: ["Wellington", "New Zealand"],
370
+ WRO: ["Wroclaw", "Poland"],
371
+ XAP: ["Chapeco", "Brazil"],
372
+ XFN: ["Xiangyang", "China"],
373
+ XIY: ["Baoji", "China"],
374
+ XNH: ["Nasiriyah", "Iraq"],
375
+ YHZ: ["Halifax", "Canada"],
376
+ YUL: ["Montr\xE9al", "Canada"],
377
+ YVR: ["Vancouver", "Canada"],
378
+ YWG: ["Winnipeg", "Canada"],
379
+ YXE: ["Saskatoon", "Canada"],
380
+ YYC: ["Calgary", "Canada"],
381
+ YYZ: ["Toronto", "Canada"],
382
+ ZAG: ["Zagreb", "Croatia"],
383
+ ZDM: ["Ramallah", null],
384
+ ZRH: ["Zurich", "Switzerland"]
385
+ };
386
+ function placeOf(colo) {
387
+ const entry = colo ? PLACES[colo] : void 0;
388
+ return entry ? { city: entry[0], country: entry[1] } : null;
389
+ }
390
+
391
+ // src/ui/theme.ts
392
+ var C = {
393
+ signal: "#2dd4bf",
394
+ muted: "#8a8f8b",
395
+ strong: "#f3f4f1",
396
+ ok: "#4ade80",
397
+ warn: "#facc15",
398
+ err: "#f87171"
399
+ };
400
+ var TUNNEL_COLORS = ["#93c5fd", "#c4b5fd", "#facc15", "#4ade80", "#f9a8d4", "#fdba74", "#67e8f9"];
401
+ function tunnelColor(index) {
402
+ return TUNNEL_COLORS[index % TUNNEL_COLORS.length];
403
+ }
404
+ function fit(text, width) {
405
+ if (width <= 0) return "";
406
+ return text.length > width ? `${text.slice(0, Math.max(0, width - 1))}\u2026` : text.padEnd(width);
407
+ }
408
+
409
+ // src/session/bodyNote.ts
410
+ var TRUNCATED_NOTE = "Body cut at 64 KB.";
411
+ function bodyNote(r, side) {
412
+ if (side === "req") {
413
+ if (r.reqBodyBytes === 0) return "No body.";
414
+ if (r.reqBody === null && !r.reqTruncated) return "Binary body; not stored.";
415
+ return null;
416
+ }
417
+ if (r.bytes === 0) return "No body.";
418
+ if (r.resBody === null) return "Binary body; not stored.";
419
+ return null;
420
+ }
421
+
422
+ // src/ui/format.ts
423
+ function statusColor(status) {
424
+ if (status === null) return "muted";
425
+ if (status === 101) return "signal";
426
+ if (status >= 500) return "err";
427
+ if (status >= 400) return "warn";
428
+ if (status >= 300) return "muted";
429
+ return "ok";
430
+ }
431
+ function formatDuration(ms) {
432
+ return ms < 1e3 ? `${Math.round(ms)}ms` : `${(ms / 1e3).toFixed(1)}s`;
433
+ }
434
+ function formatBytes(n) {
435
+ if (n < 1024) return `${n} B`;
436
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
437
+ return `${(n / 1024 / 1024).toFixed(1)} MB`;
438
+ }
439
+ function formatTime(ms) {
440
+ const d = new Date(ms);
441
+ return [d.getHours(), d.getMinutes(), d.getSeconds()].map((n) => String(n).padStart(2, "0")).join(":");
442
+ }
443
+ function localLabel(t) {
444
+ return t.host ? `localhost:${t.port} (Host: ${t.host})` : `localhost:${t.port}`;
445
+ }
446
+
447
+ export {
448
+ MAX_NAME,
449
+ normalizeName,
450
+ validateName,
451
+ placeOf,
452
+ C,
453
+ tunnelColor,
454
+ fit,
455
+ TRUNCATED_NOTE,
456
+ bodyNote,
457
+ statusColor,
458
+ formatDuration,
459
+ formatBytes,
460
+ formatTime,
461
+ localLabel
462
+ };
@@ -13,7 +13,7 @@ import {
13
13
  statusColor,
14
14
  tunnelColor,
15
15
  validateName
16
- } from "./chunk-76YCOMXH.js";
16
+ } from "./chunk-KBH2C2UC.js";
17
17
 
18
18
  // src/ui/fullscreen.tsx
19
19
  import { render } from "ink";
package/dist/index.js CHANGED
@@ -9,9 +9,10 @@ import {
9
9
  formatTime,
10
10
  localLabel,
11
11
  normalizeName,
12
+ placeOf,
12
13
  statusColor,
13
14
  validateName
14
- } from "./chunk-76YCOMXH.js";
15
+ } from "./chunk-KBH2C2UC.js";
15
16
 
16
17
  // src/ui/brand.ts
17
18
  function colorOn(stream = process.stdout) {
@@ -51,6 +52,7 @@ var DutoApiError = class extends Error {
51
52
  status;
52
53
  code;
53
54
  };
55
+ var BOOKMARK_HEADER = "x-d1-bookmark";
54
56
  var MESSAGES = {
55
57
  unauthorized: "This machine is not logged in. Run: duto login",
56
58
  suspended: "Your account is suspended.",
@@ -59,6 +61,7 @@ var MESSAGES = {
59
61
  };
60
62
  function createApiClient(o) {
61
63
  const doFetch = o.fetchImpl ?? fetch;
64
+ let bookmark = null;
62
65
  async function call(method, path, body) {
63
66
  let res;
64
67
  try {
@@ -67,6 +70,7 @@ function createApiClient(o) {
67
70
  headers: {
68
71
  ...o.token === void 0 ? {} : { authorization: `Bearer ${o.token}` },
69
72
  ...body === void 0 ? {} : { "content-type": "application/json" },
73
+ ...bookmark === null ? {} : { [BOOKMARK_HEADER]: bookmark },
70
74
  "user-agent": "duto-cli"
71
75
  },
72
76
  body: body === void 0 ? void 0 : JSON.stringify(body)
@@ -74,6 +78,7 @@ function createApiClient(o) {
74
78
  } catch {
75
79
  throw new DutoApiError(MESSAGES.network, 0, "network");
76
80
  }
81
+ bookmark = res.headers.get(BOOKMARK_HEADER) ?? bookmark;
77
82
  return res;
78
83
  }
79
84
  async function fail3(res) {
@@ -540,7 +545,7 @@ async function browserLogin(o) {
540
545
  const start = await api.startLogin({
541
546
  deviceId: o.deviceId,
542
547
  deviceName: hostname(),
543
- cliVersion: "1.1.0",
548
+ cliVersion: "1.2.0",
544
549
  nodeVersion: process.version,
545
550
  os: process.platform,
546
551
  arch: process.arch
@@ -616,6 +621,22 @@ function startSpinner(label, stream = process.stderr) {
616
621
  };
617
622
  }
618
623
 
624
+ // src/inspector/edge.ts
625
+ var RAY_COLO = /-([A-Za-z]{3})$/;
626
+ function edgeOf(headers) {
627
+ const name = Object.keys(headers).find((k) => k.toLowerCase() === "cf-ray");
628
+ const code = name ? RAY_COLO.exec(headers[name] ?? "")?.[1] : void 0;
629
+ if (!code) return null;
630
+ const colo = code.toUpperCase();
631
+ const place = placeOf(colo);
632
+ return { colo, city: place?.city ?? null, country: place?.country ?? null };
633
+ }
634
+ function edgeLabel(edge) {
635
+ if (!edge) return "";
636
+ const place = [edge.city, edge.country].filter(Boolean).join(", ");
637
+ return place ? "via " + edge.colo + " (" + place + ")" : "via " + edge.colo;
638
+ }
639
+
619
640
  // src/inspector/jsonView.ts
620
641
  function countLabel(n, one, many) {
621
642
  return n + " " + (n === 1 ? one : many);
@@ -796,6 +817,7 @@ th { color: ${JSON_KEY}; font-weight: 400; white-space: nowrap; }
796
817
  `;
797
818
  var SCRIPT = String.raw`"use strict";
798
819
  var countLabel = (${countLabel.toString()});
820
+ var edgeLabel = (${edgeLabel.toString()});
799
821
  var jsonSyntaxError = (${jsonSyntaxError.toString()});
800
822
  var jsonTokens = (${jsonTokens.toString()});
801
823
  var jsonIndent = (${jsonIndent.toString()});
@@ -969,6 +991,7 @@ function renderDetail() {
969
991
  if (duration(d)) parts.push(duration(d));
970
992
  parts.push(size(d.bytes));
971
993
  parts.push(d.tunnel);
994
+ if (d.edge) parts.push(edgeLabel(d.edge));
972
995
  if (d.replayOf !== undefined) parts.push("↻ replay of #" + d.replayOf);
973
996
  head.appendChild(el("span", "mut", " · " + parts.join(" · ")));
974
997
  if (d.error) head.appendChild(el("div", "msg err", d.error));
@@ -1362,6 +1385,7 @@ function detail(r, session) {
1362
1385
  }
1363
1386
  return {
1364
1387
  ...listItem(r),
1388
+ edge: edgeOf(r.reqHeaders),
1365
1389
  reqHeaders: r.reqHeaders,
1366
1390
  resHeaders: r.resHeaders,
1367
1391
  reqBody: r.reqBody,
@@ -2679,12 +2703,12 @@ async function runSession(specs, source, flags) {
2679
2703
  }
2680
2704
  }
2681
2705
  if (wantsUi(flags)) {
2682
- const { runFullscreen } = await import("./fullscreen-ECEH3R2V.js");
2683
- const code = await runFullscreen(session, specs, "1.1.0", inspector, inspectorError);
2706
+ const { runFullscreen } = await import("./fullscreen-2I3U6JL7.js");
2707
+ const code = await runFullscreen(session, specs, "1.2.0", inspector, inspectorError);
2684
2708
  await inspector?.close().catch(() => void 0);
2685
2709
  process.exit(code);
2686
2710
  }
2687
- console.log(`${mark()} ${paint("muted", `${"1.1.0"} \xB7 ${source} \xB7 Ctrl+C to stop`)}`);
2711
+ console.log(`${mark()} ${paint("muted", `${"1.2.0"} \xB7 ${source} \xB7 Ctrl+C to stop`)}`);
2688
2712
  if (inspector) console.log(paint("muted", `inspector: ${inspector.openUrl}`));
2689
2713
  if (inspectorError) console.log(warn(`inspector failed to start: ${inspectorError}`));
2690
2714
  const stopLog = runPlain(session, (l) => console.log(l));
@@ -2812,7 +2836,7 @@ cli.command("status", "Show your account and live tunnels").action(async () => {
2812
2836
  }
2813
2837
  });
2814
2838
  cli.help();
2815
- cli.version("1.1.0");
2839
+ cli.version("1.2.0");
2816
2840
  try {
2817
2841
  cli.parse(process.argv, { run: false });
2818
2842
  await cli.runMatchedCommand();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dutodev/cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Expose a local port at https://<name>-<user>.duto.dev with one command.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,111 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ../shared/src/names.ts
4
- var EMAIL_SENDING_SUBDOMAINS = ["send"];
5
- var RESERVED_NAMES = [
6
- "www",
7
- "api",
8
- "app",
9
- "dash",
10
- "admin",
11
- "docs",
12
- "status",
13
- "mail",
14
- "custom",
15
- "cname",
16
- "duto",
17
- "auth",
18
- "login",
19
- "signup",
20
- "invite",
21
- "static",
22
- "assets",
23
- "cdn",
24
- "help",
25
- "support",
26
- "blog",
27
- ...EMAIL_SENDING_SUBDOMAINS
28
- ];
29
- var MAX_NAME = 40;
30
- var FORMAT = /^[a-z0-9]+$/;
31
- function normalizeName(input) {
32
- return input.trim().toLowerCase();
33
- }
34
- function validateName(name, max = MAX_NAME) {
35
- if (name.length === 0 || name.length > max) return { ok: false, reason: "length" };
36
- if (!FORMAT.test(name)) return { ok: false, reason: "format" };
37
- if (RESERVED_NAMES.includes(name)) return { ok: false, reason: "reserved" };
38
- return { ok: true };
39
- }
40
-
41
- // src/ui/theme.ts
42
- var C = {
43
- signal: "#2dd4bf",
44
- muted: "#8a8f8b",
45
- strong: "#f3f4f1",
46
- ok: "#4ade80",
47
- warn: "#facc15",
48
- err: "#f87171"
49
- };
50
- var TUNNEL_COLORS = ["#93c5fd", "#c4b5fd", "#facc15", "#4ade80", "#f9a8d4", "#fdba74", "#67e8f9"];
51
- function tunnelColor(index) {
52
- return TUNNEL_COLORS[index % TUNNEL_COLORS.length];
53
- }
54
- function fit(text, width) {
55
- if (width <= 0) return "";
56
- return text.length > width ? `${text.slice(0, Math.max(0, width - 1))}\u2026` : text.padEnd(width);
57
- }
58
-
59
- // src/session/bodyNote.ts
60
- var TRUNCATED_NOTE = "Body cut at 64 KB.";
61
- function bodyNote(r, side) {
62
- if (side === "req") {
63
- if (r.reqBodyBytes === 0) return "No body.";
64
- if (r.reqBody === null && !r.reqTruncated) return "Binary body; not stored.";
65
- return null;
66
- }
67
- if (r.bytes === 0) return "No body.";
68
- if (r.resBody === null) return "Binary body; not stored.";
69
- return null;
70
- }
71
-
72
- // src/ui/format.ts
73
- function statusColor(status) {
74
- if (status === null) return "muted";
75
- if (status === 101) return "signal";
76
- if (status >= 500) return "err";
77
- if (status >= 400) return "warn";
78
- if (status >= 300) return "muted";
79
- return "ok";
80
- }
81
- function formatDuration(ms) {
82
- return ms < 1e3 ? `${Math.round(ms)}ms` : `${(ms / 1e3).toFixed(1)}s`;
83
- }
84
- function formatBytes(n) {
85
- if (n < 1024) return `${n} B`;
86
- if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
87
- return `${(n / 1024 / 1024).toFixed(1)} MB`;
88
- }
89
- function formatTime(ms) {
90
- const d = new Date(ms);
91
- return [d.getHours(), d.getMinutes(), d.getSeconds()].map((n) => String(n).padStart(2, "0")).join(":");
92
- }
93
- function localLabel(t) {
94
- return t.host ? `localhost:${t.port} (Host: ${t.host})` : `localhost:${t.port}`;
95
- }
96
-
97
- export {
98
- MAX_NAME,
99
- normalizeName,
100
- validateName,
101
- C,
102
- tunnelColor,
103
- fit,
104
- TRUNCATED_NOTE,
105
- bodyNote,
106
- statusColor,
107
- formatDuration,
108
- formatBytes,
109
- formatTime,
110
- localLabel
111
- };