cloak22 2.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/cli.js ADDED
@@ -0,0 +1,627 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseCli = parseCli;
7
+ exports.isHeadlessEnabled = isHeadlessEnabled;
8
+ const yargs_1 = __importDefault(require("yargs"));
9
+ const output_js_1 = require("./output.js");
10
+ function parseUrl(value) {
11
+ try {
12
+ const parsed = new URL(value);
13
+ if (!["http:", "https:"].includes(parsed.protocol)) {
14
+ throw new Error(`invalid site URL: ${value}`);
15
+ }
16
+ return parsed.toString();
17
+ }
18
+ catch {
19
+ throw new Error(`invalid URL: ${value}`);
20
+ }
21
+ }
22
+ function normalizeUrls(values) {
23
+ if (!values) {
24
+ return [];
25
+ }
26
+ const urls = Array.isArray(values) ? values : [values];
27
+ const normalized = urls.map(parseUrl);
28
+ return [...new Set(normalized)];
29
+ }
30
+ function normalizeFilePath(value) {
31
+ const normalized = value?.trim();
32
+ if (!normalized) {
33
+ return undefined;
34
+ }
35
+ return normalized;
36
+ }
37
+ function parseLimit(value) {
38
+ if (!Number.isInteger(value) || value <= 0) {
39
+ throw new Error("--limit must be a positive integer");
40
+ }
41
+ return value;
42
+ }
43
+ function createParser(args, scriptName) {
44
+ return (0, yargs_1.default)(args)
45
+ .scriptName(scriptName)
46
+ .exitProcess(false)
47
+ .help(false)
48
+ .version(false)
49
+ .showHelpOnFail(false)
50
+ .strict()
51
+ .strictCommands()
52
+ .strictOptions()
53
+ .wrap(100)
54
+ .fail((message, error) => {
55
+ if (error) {
56
+ throw error;
57
+ }
58
+ throw new Error(message);
59
+ });
60
+ }
61
+ function isHelpFlag(value) {
62
+ return value === "-h" || value === "--help";
63
+ }
64
+ function rootEpilog() {
65
+ return `${(0, output_js_1.formatHeading)("Examples:")}
66
+ cloak profile list
67
+ cloak profile use "Profile 7"
68
+ cloak profile show
69
+ cloak sites list
70
+ cloak run
71
+ cloak daemon start --profile "Profile 7" --persist-cookies --consent --cookie-url https://x.com
72
+ cloak daemon status
73
+ cloak daemon logs
74
+ cloak storage show
75
+ cloak storage destroy
76
+ cloak version
77
+
78
+ ${(0, output_js_1.formatHeading)("Storage:")}
79
+ cloak stores state in ~/.config/cloak/state.sqlite
80
+ cloak stores daemon logs and the pinned OpenCLI extension under ~/.cache/cloak/
81
+ `;
82
+ }
83
+ function buildRootProgram(args = []) {
84
+ return createParser(args, "cloak")
85
+ .usage("$0 <command>")
86
+ .command("run", "launch Patchright headless by default")
87
+ .command("daemon", "start, inspect, stop, restart, or print the managed daemon log")
88
+ .command("profile", "list, show, or select a Chrome profile")
89
+ .command("sites", "list cookie-bearing site URLs for the active profile")
90
+ .command("storage", "inspect or destroy cloak storage")
91
+ .command("version", "print the installed cloak version")
92
+ .epilog(rootEpilog());
93
+ }
94
+ function rootHelpText() {
95
+ return `Usage: cloak <command>
96
+
97
+ Commands:
98
+ cloak run launch Patchright headless by default
99
+ cloak daemon start start the managed daemon
100
+ cloak daemon status inspect the managed daemon
101
+ cloak daemon stop stop the managed daemon
102
+ cloak daemon restart restart the managed daemon
103
+ cloak daemon logs print the managed daemon log
104
+ cloak profile list list available Chrome profiles
105
+ cloak profile show show the saved default Chrome profile
106
+ cloak profile use <name> save the default Chrome profile
107
+ cloak sites list list Chrome cookie URLs for the active profile
108
+ cloak storage show show the cloak storage paths
109
+ cloak storage destroy destroy cloak storage after confirmation
110
+ cloak version print the installed cloak version
111
+
112
+ Options:
113
+ -h, --help Show help
114
+ -v, --version Show version
115
+
116
+ ${rootEpilog()}`;
117
+ }
118
+ function runEpilog() {
119
+ return `${(0, output_js_1.formatHeading)("Examples:")}
120
+ cloak run
121
+ cloak run --window
122
+ cloak run --cookie-file ./cookies.json
123
+ cloak run --cookie-url https://x.com --profile "Profile 7"
124
+ cloak run --persist-cookies --consent --cookie-url https://x.com
125
+
126
+ ${(0, output_js_1.formatHeading)("Related:")}
127
+ cloak daemon start [same options as run]
128
+
129
+ ${(0, output_js_1.formatHeading)("Storage:")}
130
+ --persist-cookies remembers cookie URLs for the chosen profile
131
+ `;
132
+ }
133
+ function buildRunProgram(args = []) {
134
+ return createParser(args, "cloak run")
135
+ .usage("$0 [options]")
136
+ .option("window", {
137
+ alias: "w",
138
+ type: "boolean",
139
+ description: "open a visible browser window",
140
+ })
141
+ .option("profile", {
142
+ type: "string",
143
+ description: "Chrome profile directory name",
144
+ })
145
+ .option("cookie-url", {
146
+ type: "string",
147
+ array: true,
148
+ description: "HTTP(S) site URL to import cookies from",
149
+ coerce: normalizeUrls,
150
+ })
151
+ .option("cookie-file", {
152
+ type: "string",
153
+ description: "JSON cookie export or Playwright storage-state file",
154
+ coerce: normalizeFilePath,
155
+ })
156
+ .option("persist-cookies", {
157
+ type: "boolean",
158
+ description: "remember the provided --cookie-url values for this profile",
159
+ })
160
+ .option("consent", {
161
+ type: "boolean",
162
+ description: "create ~/.config/cloak without prompting",
163
+ })
164
+ .check((options) => {
165
+ const cookieUrls = Array.isArray(options.cookieUrl)
166
+ ? options.cookieUrl
167
+ : [];
168
+ if (options.persistCookies && cookieUrls.length === 0) {
169
+ throw new Error("--persist-cookies requires at least one --cookie-url");
170
+ }
171
+ return true;
172
+ })
173
+ .epilog(runEpilog());
174
+ }
175
+ function runHelpText() {
176
+ return `Usage: cloak run [options]
177
+
178
+ Options:
179
+ -h, --help Show help
180
+ -w, --window open a visible browser window
181
+ --profile <profile> Chrome profile directory name
182
+ --cookie-url <url> HTTP(S) site URL to import cookies from
183
+ --cookie-file <path> JSON cookie export or Playwright storage-state file
184
+ --persist-cookies remember the provided --cookie-url values
185
+ --consent create ~/.config/cloak without prompting
186
+
187
+ ${runEpilog()}`;
188
+ }
189
+ function buildDaemonProgram(args = []) {
190
+ return createParser(args, "cloak daemon")
191
+ .usage("$0 <command>")
192
+ .command("start", "start the managed daemon")
193
+ .command("status", "inspect the managed daemon")
194
+ .command("stop", "stop the managed daemon")
195
+ .command("restart", "restart the managed daemon")
196
+ .command("logs", "print the managed daemon log");
197
+ }
198
+ function daemonHelpText() {
199
+ return `Usage: cloak daemon <command>
200
+
201
+ Commands:
202
+ cloak daemon start start the managed daemon
203
+ cloak daemon status inspect the managed daemon
204
+ cloak daemon stop stop the managed daemon
205
+ cloak daemon restart restart the managed daemon
206
+ cloak daemon logs print the managed daemon log
207
+
208
+ Options:
209
+ -h, --help Show help
210
+ `;
211
+ }
212
+ function buildDaemonStartProgram(args = []) {
213
+ return createParser(args, "cloak daemon start")
214
+ .usage("$0 [options]")
215
+ .option("window", {
216
+ alias: "w",
217
+ type: "boolean",
218
+ description: "open a visible browser window",
219
+ })
220
+ .option("profile", {
221
+ type: "string",
222
+ description: "Chrome profile directory name",
223
+ })
224
+ .option("cookie-url", {
225
+ type: "string",
226
+ array: true,
227
+ description: "HTTP(S) site URL to import cookies from",
228
+ coerce: normalizeUrls,
229
+ })
230
+ .option("cookie-file", {
231
+ type: "string",
232
+ description: "JSON cookie export or Playwright storage-state file",
233
+ coerce: normalizeFilePath,
234
+ })
235
+ .option("persist-cookies", {
236
+ type: "boolean",
237
+ description: "remember the provided --cookie-url values for this profile",
238
+ })
239
+ .option("consent", {
240
+ type: "boolean",
241
+ description: "create ~/.config/cloak without prompting",
242
+ })
243
+ .check((options) => {
244
+ const cookieUrls = Array.isArray(options.cookieUrl)
245
+ ? options.cookieUrl
246
+ : [];
247
+ if (options.persistCookies && cookieUrls.length === 0) {
248
+ throw new Error("--persist-cookies requires at least one --cookie-url");
249
+ }
250
+ return true;
251
+ });
252
+ }
253
+ function daemonStartHelpText() {
254
+ return `Usage: cloak daemon start [options]
255
+
256
+ Options:
257
+ -h, --help Show help
258
+ -w, --window open a visible browser window
259
+ --profile <profile> Chrome profile directory name
260
+ --cookie-url <url> HTTP(S) site URL to import cookies from
261
+ --cookie-file <path> JSON cookie export or Playwright storage-state file
262
+ --persist-cookies remember the provided --cookie-url values
263
+ --consent create ~/.config/cloak without prompting
264
+ `;
265
+ }
266
+ function buildZeroArgProgram(args = [], scriptName) {
267
+ return createParser(args, scriptName).usage("$0");
268
+ }
269
+ function zeroArgHelpText(usage) {
270
+ return `Usage: ${usage}
271
+
272
+ Options:
273
+ -h, --help Show help
274
+ `;
275
+ }
276
+ function buildProfileProgram(args = []) {
277
+ return createParser(args, "cloak profile")
278
+ .usage("$0 <command>")
279
+ .command("list", "list available Chrome profiles")
280
+ .command("show", "show the saved default Chrome profile")
281
+ .command("use <profile>", "save the default Chrome profile");
282
+ }
283
+ function profileHelpText() {
284
+ return `Usage: cloak profile <command>
285
+
286
+ Commands:
287
+ cloak profile list list available Chrome profiles
288
+ cloak profile show show the saved default Chrome profile
289
+ cloak profile use <name> save the default Chrome profile
290
+
291
+ Options:
292
+ -h, --help Show help
293
+ `;
294
+ }
295
+ function buildProfileUseProgram(args = []) {
296
+ return createParser(args, "cloak profile use")
297
+ .usage("$0 <profile> [options]")
298
+ .option("consent", {
299
+ type: "boolean",
300
+ description: "create ~/.config/cloak without prompting",
301
+ });
302
+ }
303
+ function profileUseHelpText() {
304
+ return `Usage: cloak profile use <profile> [options]
305
+
306
+ Options:
307
+ -h, --help Show help
308
+ --consent create ~/.config/cloak without prompting
309
+ `;
310
+ }
311
+ function buildSitesProgram(args = []) {
312
+ return createParser(args, "cloak sites")
313
+ .usage("$0 <command>")
314
+ .command("list", "list Chrome cookie URLs for the active profile");
315
+ }
316
+ function sitesHelpText() {
317
+ return `Usage: cloak sites <command>
318
+
319
+ Commands:
320
+ cloak sites list list Chrome cookie URLs for the active profile
321
+
322
+ Options:
323
+ -h, --help Show help
324
+ `;
325
+ }
326
+ function buildSitesListProgram(args = []) {
327
+ return createParser(args, "cloak sites list")
328
+ .usage("$0 [options]")
329
+ .option("pager", {
330
+ type: "boolean",
331
+ default: true,
332
+ description: "prompt for interactive selection after printing the list",
333
+ })
334
+ .option("limit", {
335
+ alias: "l",
336
+ type: "number",
337
+ default: 100,
338
+ description: "maximum number of URLs to print",
339
+ coerce: parseLimit,
340
+ })
341
+ .option("consent", {
342
+ type: "boolean",
343
+ description: "create ~/.config/cloak without prompting",
344
+ });
345
+ }
346
+ function sitesListHelpText() {
347
+ return `Usage: cloak sites list [options]
348
+
349
+ Options:
350
+ -h, --help Show help
351
+ -n, --no-pager print without prompting for selection
352
+ -l, --limit <count> maximum number of URLs to print (default 100)
353
+ --consent create ~/.config/cloak without prompting
354
+ `;
355
+ }
356
+ function buildStorageProgram(args = []) {
357
+ return createParser(args, "cloak storage")
358
+ .usage("$0 <command>")
359
+ .command("show", "show the cloak storage paths")
360
+ .command("destroy", "destroy cloak storage after confirmation");
361
+ }
362
+ function storageHelpText() {
363
+ return `Usage: cloak storage <command>
364
+
365
+ Commands:
366
+ cloak storage show show the cloak storage paths
367
+ cloak storage destroy destroy cloak storage after confirmation
368
+
369
+ Options:
370
+ -h, --help Show help
371
+ `;
372
+ }
373
+ function parseRunMode(args) {
374
+ const parser = buildRunProgram(args);
375
+ const options = parser.parseSync();
376
+ if (options.help) {
377
+ return {
378
+ mode: "help",
379
+ text: runHelpText(),
380
+ };
381
+ }
382
+ return {
383
+ mode: "run",
384
+ headless: !Boolean(options.window),
385
+ daemon: false,
386
+ persistCookies: Boolean(options.persistCookies),
387
+ consent: Boolean(options.consent),
388
+ profile: options.profile,
389
+ cookieUrls: options.cookieUrl ?? [],
390
+ cookieFile: options.cookieFile,
391
+ };
392
+ }
393
+ function parseDaemonStartMode(args) {
394
+ const parser = buildDaemonStartProgram(args);
395
+ const options = parser.parseSync();
396
+ if (options.help) {
397
+ return {
398
+ mode: "help",
399
+ text: daemonStartHelpText(),
400
+ };
401
+ }
402
+ return {
403
+ mode: "run",
404
+ headless: !Boolean(options.window),
405
+ daemon: true,
406
+ persistCookies: Boolean(options.persistCookies),
407
+ consent: Boolean(options.consent),
408
+ profile: options.profile,
409
+ cookieUrls: options.cookieUrl ?? [],
410
+ cookieFile: options.cookieFile,
411
+ };
412
+ }
413
+ function parseProfileUseMode(args) {
414
+ const profile = String(args[0] ?? "").trim();
415
+ if (!profile) {
416
+ throw new Error("profile is required");
417
+ }
418
+ const parser = buildProfileUseProgram(args.slice(1));
419
+ const options = parser.parseSync();
420
+ if (options.help) {
421
+ return {
422
+ mode: "help",
423
+ text: profileUseHelpText(),
424
+ };
425
+ }
426
+ return {
427
+ mode: "profile-use",
428
+ profile,
429
+ consent: Boolean(options.consent),
430
+ };
431
+ }
432
+ function parseSitesListMode(args) {
433
+ const normalizedArgs = args.map((arg) => (arg === "-n" ? "--no-pager" : arg));
434
+ const parser = buildSitesListProgram(normalizedArgs);
435
+ const options = parser.parseSync();
436
+ if (options.help) {
437
+ return {
438
+ mode: "help",
439
+ text: sitesListHelpText(),
440
+ };
441
+ }
442
+ return {
443
+ mode: "sites-list",
444
+ limit: options.limit ?? 100,
445
+ noPager: options.pager === false,
446
+ consent: Boolean(options.consent),
447
+ };
448
+ }
449
+ function parseRootMode(args) {
450
+ buildRootProgram(args).parseSync();
451
+ throw new Error("root mode parsing should not return");
452
+ }
453
+ function parseCli(argv) {
454
+ const args = argv.slice(2);
455
+ if (args.length === 0 || isHelpFlag(args[0])) {
456
+ return {
457
+ mode: "help",
458
+ text: rootHelpText(),
459
+ };
460
+ }
461
+ if (args[0] === "-v" || args[0] === "--version" || args[0] === "version") {
462
+ return {
463
+ mode: "version",
464
+ };
465
+ }
466
+ if (args[0] === "run") {
467
+ if (args.length === 2 && isHelpFlag(args[1])) {
468
+ return {
469
+ mode: "help",
470
+ text: runHelpText(),
471
+ };
472
+ }
473
+ return parseRunMode(args.slice(1));
474
+ }
475
+ if (args[0] === "daemon") {
476
+ if (args.length === 1 || isHelpFlag(args[1])) {
477
+ return {
478
+ mode: "help",
479
+ text: daemonHelpText(),
480
+ };
481
+ }
482
+ if (args[1] === "start") {
483
+ if (args.length === 3 && isHelpFlag(args[2])) {
484
+ return {
485
+ mode: "help",
486
+ text: daemonStartHelpText(),
487
+ };
488
+ }
489
+ return parseDaemonStartMode(args.slice(2));
490
+ }
491
+ if (args[1] === "status") {
492
+ if (args.length === 3 && isHelpFlag(args[2])) {
493
+ return {
494
+ mode: "help",
495
+ text: zeroArgHelpText("cloak daemon status"),
496
+ };
497
+ }
498
+ buildZeroArgProgram(args.slice(2), "cloak daemon status").parseSync();
499
+ return { mode: "daemon-status" };
500
+ }
501
+ if (args[1] === "stop") {
502
+ if (args.length === 3 && isHelpFlag(args[2])) {
503
+ return {
504
+ mode: "help",
505
+ text: zeroArgHelpText("cloak daemon stop"),
506
+ };
507
+ }
508
+ buildZeroArgProgram(args.slice(2), "cloak daemon stop").parseSync();
509
+ return { mode: "daemon-stop" };
510
+ }
511
+ if (args[1] === "restart") {
512
+ if (args.length === 3 && isHelpFlag(args[2])) {
513
+ return {
514
+ mode: "help",
515
+ text: zeroArgHelpText("cloak daemon restart"),
516
+ };
517
+ }
518
+ buildZeroArgProgram(args.slice(2), "cloak daemon restart").parseSync();
519
+ return { mode: "daemon-restart" };
520
+ }
521
+ if (args[1] === "logs") {
522
+ if (args.length === 3 && isHelpFlag(args[2])) {
523
+ return {
524
+ mode: "help",
525
+ text: zeroArgHelpText("cloak daemon logs"),
526
+ };
527
+ }
528
+ buildZeroArgProgram(args.slice(2), "cloak daemon logs").parseSync();
529
+ return { mode: "daemon-logs" };
530
+ }
531
+ buildDaemonProgram(args.slice(1)).parseSync();
532
+ throw new Error("daemon parsing should not return");
533
+ }
534
+ if (args[0] === "profile") {
535
+ if (args.length === 1 || isHelpFlag(args[1])) {
536
+ return {
537
+ mode: "help",
538
+ text: profileHelpText(),
539
+ };
540
+ }
541
+ if (args[1] === "list") {
542
+ if (args.length === 3 && isHelpFlag(args[2])) {
543
+ return {
544
+ mode: "help",
545
+ text: zeroArgHelpText("cloak profile list"),
546
+ };
547
+ }
548
+ buildZeroArgProgram(args.slice(2), "cloak profile list").parseSync();
549
+ return { mode: "profile-list" };
550
+ }
551
+ if (args[1] === "show") {
552
+ if (args.length === 3 && isHelpFlag(args[2])) {
553
+ return {
554
+ mode: "help",
555
+ text: zeroArgHelpText("cloak profile show"),
556
+ };
557
+ }
558
+ buildZeroArgProgram(args.slice(2), "cloak profile show").parseSync();
559
+ return { mode: "profile-show" };
560
+ }
561
+ if (args[1] === "use") {
562
+ if (args.length === 3 && isHelpFlag(args[2])) {
563
+ return {
564
+ mode: "help",
565
+ text: profileUseHelpText(),
566
+ };
567
+ }
568
+ return parseProfileUseMode(args.slice(2));
569
+ }
570
+ buildProfileProgram(args.slice(1)).parseSync();
571
+ throw new Error("profile parsing should not return");
572
+ }
573
+ if (args[0] === "sites") {
574
+ if (args.length === 1 || isHelpFlag(args[1])) {
575
+ return {
576
+ mode: "help",
577
+ text: sitesHelpText(),
578
+ };
579
+ }
580
+ if (args[1] === "list") {
581
+ if (args.length === 3 && isHelpFlag(args[2])) {
582
+ return {
583
+ mode: "help",
584
+ text: sitesListHelpText(),
585
+ };
586
+ }
587
+ return parseSitesListMode(args.slice(2));
588
+ }
589
+ buildSitesProgram(args.slice(1)).parseSync();
590
+ throw new Error("sites parsing should not return");
591
+ }
592
+ if (args[0] === "storage") {
593
+ if (args.length === 1 || isHelpFlag(args[1])) {
594
+ return {
595
+ mode: "help",
596
+ text: storageHelpText(),
597
+ };
598
+ }
599
+ if (args[1] === "show") {
600
+ if (args.length === 3 && isHelpFlag(args[2])) {
601
+ return {
602
+ mode: "help",
603
+ text: zeroArgHelpText("cloak storage show"),
604
+ };
605
+ }
606
+ buildZeroArgProgram(args.slice(2), "cloak storage show").parseSync();
607
+ return { mode: "storage-show" };
608
+ }
609
+ if (args[1] === "destroy") {
610
+ if (args.length === 3 && isHelpFlag(args[2])) {
611
+ return {
612
+ mode: "help",
613
+ text: zeroArgHelpText("cloak storage destroy"),
614
+ };
615
+ }
616
+ buildZeroArgProgram(args.slice(2), "cloak storage destroy").parseSync();
617
+ return { mode: "storage-destroy" };
618
+ }
619
+ buildStorageProgram(args.slice(1)).parseSync();
620
+ throw new Error("storage parsing should not return");
621
+ }
622
+ return parseRootMode(args);
623
+ }
624
+ function isHeadlessEnabled(argv) {
625
+ const parsed = parseCli(argv);
626
+ return parsed.mode === "run" ? parsed.headless : false;
627
+ }