@jackwener/opencli 1.7.18 → 1.7.19
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/README.md +7 -8
- package/README.zh-CN.md +7 -8
- package/cli-manifest.json +305 -9
- package/clis/ctrip/ctrip.test.js +486 -1
- package/clis/ctrip/flight.js +136 -0
- package/clis/ctrip/hotel-search.js +132 -0
- package/clis/ctrip/utils.js +298 -0
- package/clis/google/search.js +16 -6
- package/clis/google-scholar/search.js +20 -5
- package/clis/google-scholar/search.test.js +35 -2
- package/clis/reddit/home.js +117 -0
- package/clis/reddit/home.test.js +127 -0
- package/clis/reddit/read.js +400 -54
- package/clis/reddit/read.test.js +315 -12
- package/clis/reddit/subreddit-info.js +117 -0
- package/clis/reddit/subreddit-info.test.js +163 -0
- package/clis/reddit/whoami.js +84 -0
- package/clis/reddit/whoami.test.js +105 -0
- package/clis/rednote/search.js +6 -2
- package/clis/twitter/bookmark-folder.js +3 -1
- package/clis/twitter/bookmarks.js +3 -1
- package/clis/twitter/followers.js +20 -5
- package/clis/twitter/followers.test.js +44 -0
- package/clis/twitter/following.js +36 -20
- package/clis/twitter/following.test.js +60 -8
- package/clis/twitter/likes.js +28 -13
- package/clis/twitter/likes.test.js +111 -1
- package/clis/twitter/list-add.js +128 -204
- package/clis/twitter/list-add.test.js +97 -1
- package/clis/twitter/list-tweets.js +13 -4
- package/clis/twitter/list-tweets.test.js +48 -0
- package/clis/twitter/lists.js +5 -2
- package/clis/twitter/post.js +23 -4
- package/clis/twitter/post.test.js +30 -0
- package/clis/twitter/profile.js +16 -8
- package/clis/twitter/profile.test.js +39 -0
- package/clis/twitter/reply.js +133 -10
- package/clis/twitter/reply.test.js +55 -0
- package/clis/twitter/search.js +188 -170
- package/clis/twitter/search.test.js +96 -258
- package/clis/twitter/shared.js +167 -16
- package/clis/twitter/shared.test.js +102 -1
- package/clis/twitter/timeline.js +3 -1
- package/clis/twitter/tweets.js +147 -51
- package/clis/twitter/tweets.test.js +238 -1
- package/clis/xiaohongshu/comments.js +23 -2
- package/clis/xiaohongshu/comments.test.js +63 -1
- package/clis/xiaohongshu/search.js +168 -13
- package/clis/xiaohongshu/search.test.js +82 -8
- package/clis/xueqiu/earnings-date.js +2 -2
- package/clis/xueqiu/kline.js +2 -2
- package/clis/xueqiu/utils.js +19 -0
- package/clis/xueqiu/utils.test.js +26 -0
- package/clis/zhihu/answer-detail.js +233 -0
- package/clis/zhihu/answer-detail.test.js +330 -0
- package/clis/zhihu/question.js +44 -10
- package/clis/zhihu/question.test.js +78 -1
- package/clis/zhihu/recommend.js +103 -0
- package/clis/zhihu/recommend.test.js +143 -0
- package/dist/src/browser/base-page.d.ts +3 -2
- package/dist/src/browser/base-page.test.js +2 -2
- package/dist/src/browser/cdp.js +3 -3
- package/dist/src/browser/page.d.ts +3 -2
- package/dist/src/browser/page.js +4 -4
- package/dist/src/browser/page.test.js +31 -0
- package/dist/src/browser/utils.d.ts +10 -0
- package/dist/src/browser/utils.js +37 -0
- package/dist/src/browser/utils.test.d.ts +1 -0
- package/dist/src/browser/utils.test.js +29 -0
- package/dist/src/cli-argv-preprocess.d.ts +37 -0
- package/dist/src/cli-argv-preprocess.js +131 -0
- package/dist/src/cli-argv-preprocess.test.d.ts +1 -0
- package/dist/src/cli-argv-preprocess.test.js +130 -0
- package/dist/src/cli.js +123 -86
- package/dist/src/cli.test.js +33 -28
- package/dist/src/commands/daemon.js +6 -7
- package/dist/src/doctor.js +15 -16
- package/dist/src/download/progress.js +15 -11
- package/dist/src/download/progress.test.d.ts +1 -0
- package/dist/src/download/progress.test.js +25 -0
- package/dist/src/execution.js +1 -3
- package/dist/src/execution.test.js +4 -16
- package/dist/src/help.d.ts +11 -0
- package/dist/src/help.js +46 -5
- package/dist/src/logger.js +8 -9
- package/dist/src/main.js +16 -0
- package/dist/src/output.js +4 -5
- package/dist/src/runtime-detect.d.ts +1 -1
- package/dist/src/runtime-detect.js +1 -1
- package/dist/src/runtime-detect.test.js +3 -2
- package/dist/src/tui.d.ts +0 -1
- package/dist/src/tui.js +9 -22
- package/dist/src/types.d.ts +3 -1
- package/dist/src/update-check.js +4 -5
- package/package.json +5 -4
package/dist/src/output.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Output formatting: table, JSON, Markdown, CSV, YAML.
|
|
3
3
|
*/
|
|
4
|
-
import { styleText } from 'node:util';
|
|
5
4
|
import Table from 'cli-table3';
|
|
6
5
|
import yaml from 'js-yaml';
|
|
7
6
|
function normalizeRows(data) {
|
|
@@ -51,13 +50,13 @@ export function render(data, opts = {}) {
|
|
|
51
50
|
function renderTable(data, opts) {
|
|
52
51
|
const rows = normalizeRows(data);
|
|
53
52
|
if (!rows.length) {
|
|
54
|
-
console.log(
|
|
53
|
+
console.log('(no data)');
|
|
55
54
|
return;
|
|
56
55
|
}
|
|
57
56
|
const columns = resolveColumns(rows, opts);
|
|
58
57
|
const header = columns.map(c => capitalize(c));
|
|
59
58
|
const table = new Table({
|
|
60
|
-
head: header.map(h =>
|
|
59
|
+
head: header.map(h => h),
|
|
61
60
|
style: { head: [], border: [] },
|
|
62
61
|
wordWrap: true,
|
|
63
62
|
wrapOnWordBoundary: true,
|
|
@@ -70,7 +69,7 @@ function renderTable(data, opts) {
|
|
|
70
69
|
}
|
|
71
70
|
console.log();
|
|
72
71
|
if (opts.title)
|
|
73
|
-
console.log(
|
|
72
|
+
console.log(` ${opts.title}`);
|
|
74
73
|
console.log(table.toString());
|
|
75
74
|
const footer = [];
|
|
76
75
|
footer.push(`${rows.length} items`);
|
|
@@ -80,7 +79,7 @@ function renderTable(data, opts) {
|
|
|
80
79
|
footer.push(opts.source);
|
|
81
80
|
if (opts.footerExtra)
|
|
82
81
|
footer.push(opts.footerExtra);
|
|
83
|
-
console.log(
|
|
82
|
+
console.log(footer.join(' · '));
|
|
84
83
|
}
|
|
85
84
|
function renderJson(data) {
|
|
86
85
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* (e.g. logging, diagnostics) without littering runtime sniffing everywhere.
|
|
7
7
|
*/
|
|
8
8
|
export type Runtime = 'bun' | 'node';
|
|
9
|
-
export declare const MIN_SUPPORTED_NODE_MAJOR =
|
|
9
|
+
export declare const MIN_SUPPORTED_NODE_MAJOR = 20;
|
|
10
10
|
/**
|
|
11
11
|
* Detect the current JavaScript runtime.
|
|
12
12
|
*/
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* This module centralises the check so other code can adapt behaviour
|
|
6
6
|
* (e.g. logging, diagnostics) without littering runtime sniffing everywhere.
|
|
7
7
|
*/
|
|
8
|
-
export const MIN_SUPPORTED_NODE_MAJOR =
|
|
8
|
+
export const MIN_SUPPORTED_NODE_MAJOR = 20;
|
|
9
9
|
/**
|
|
10
10
|
* Detect the current JavaScript runtime.
|
|
11
11
|
*/
|
|
@@ -30,8 +30,9 @@ describe('runtime-detect', () => {
|
|
|
30
30
|
expect(parseNodeMajor('bun-1.2.0')).toBeNull();
|
|
31
31
|
});
|
|
32
32
|
it('checks the current minimum supported Node major version', () => {
|
|
33
|
-
expect(MIN_SUPPORTED_NODE_MAJOR).toBe(
|
|
34
|
-
expect(isSupportedNodeVersion('
|
|
33
|
+
expect(MIN_SUPPORTED_NODE_MAJOR).toBe(20);
|
|
34
|
+
expect(isSupportedNodeVersion('v19.9.0')).toBe(false);
|
|
35
|
+
expect(isSupportedNodeVersion('v20.0.0')).toBe(true);
|
|
35
36
|
expect(isSupportedNodeVersion('v21.0.0')).toBe(true);
|
|
36
37
|
expect(isSupportedNodeVersion('v25.0.0')).toBe(true);
|
|
37
38
|
});
|
package/dist/src/tui.d.ts
CHANGED
package/dist/src/tui.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Uses raw stdin mode + ANSI escape codes for interactive prompts.
|
|
5
5
|
*/
|
|
6
|
-
import { styleText } from 'node:util';
|
|
7
6
|
import { EXIT_CODES } from './errors.js';
|
|
8
7
|
/**
|
|
9
8
|
* Interactive multi-select checkbox prompt.
|
|
@@ -25,32 +24,20 @@ export async function checkboxPrompt(items, opts = {}) {
|
|
|
25
24
|
}
|
|
26
25
|
let cursor = 0;
|
|
27
26
|
const state = items.map(i => ({ ...i }));
|
|
28
|
-
function colorStatus(status, color) {
|
|
29
|
-
if (!status)
|
|
30
|
-
return '';
|
|
31
|
-
switch (color) {
|
|
32
|
-
case 'green': return styleText('green', status);
|
|
33
|
-
case 'yellow': return styleText('yellow', status);
|
|
34
|
-
case 'red': return styleText('red', status);
|
|
35
|
-
case 'dim': return styleText('dim', status);
|
|
36
|
-
default: return styleText('dim', status);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
27
|
function render() {
|
|
40
28
|
// Move cursor to start and clear
|
|
41
29
|
let out = '';
|
|
42
30
|
if (opts.title) {
|
|
43
|
-
out += `\n${
|
|
31
|
+
out += `\n${opts.title}\n\n`;
|
|
44
32
|
}
|
|
45
33
|
for (let i = 0; i < state.length; i++) {
|
|
46
34
|
const item = state[i];
|
|
47
|
-
const pointer = i === cursor ?
|
|
48
|
-
const checkbox = item.checked ?
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
out += ` ${pointer} ${checkbox} ${label}${status ? ` ${status}` : ''}\n`;
|
|
35
|
+
const pointer = i === cursor ? '❯' : ' ';
|
|
36
|
+
const checkbox = item.checked ? '◉' : '○';
|
|
37
|
+
const status = item.status ?? '';
|
|
38
|
+
out += ` ${pointer} ${checkbox} ${item.label}${status ? ` ${status}` : ''}\n`;
|
|
52
39
|
}
|
|
53
|
-
out += `\n
|
|
40
|
+
out += `\n ↑↓ navigate · Space toggle · a all · Enter confirm · q cancel\n`;
|
|
54
41
|
return out;
|
|
55
42
|
}
|
|
56
43
|
return new Promise((resolve) => {
|
|
@@ -117,14 +104,14 @@ export async function checkboxPrompt(items, opts = {}) {
|
|
|
117
104
|
cleanup();
|
|
118
105
|
const selected = state.filter(i => i.checked).map(i => i.value);
|
|
119
106
|
// Show summary
|
|
120
|
-
stdout.write(`
|
|
107
|
+
stdout.write(` ✓ ${selected.length} file(s) selected\n\n`);
|
|
121
108
|
resolve(selected);
|
|
122
109
|
return;
|
|
123
110
|
}
|
|
124
111
|
// q / Esc — cancel
|
|
125
112
|
if (key === 'q' || key === '\x1b') {
|
|
126
113
|
cleanup();
|
|
127
|
-
stdout.write(`
|
|
114
|
+
stdout.write(` ✗ Cancelled\n\n`);
|
|
128
115
|
resolve([]);
|
|
129
116
|
return;
|
|
130
117
|
}
|
|
@@ -149,7 +136,7 @@ export async function confirmPrompt(message, defaultYes = true) {
|
|
|
149
136
|
if (!stdin.isTTY)
|
|
150
137
|
return defaultYes;
|
|
151
138
|
const hint = defaultYes ? '[Y/n]' : '[y/N]';
|
|
152
|
-
stdout.write(` ${message} ${
|
|
139
|
+
stdout.write(` ${message} ${hint} `);
|
|
153
140
|
return new Promise((resolve) => {
|
|
154
141
|
const wasRaw = stdin.isRaw;
|
|
155
142
|
stdin.setRawMode(true);
|
package/dist/src/types.d.ts
CHANGED
|
@@ -60,12 +60,14 @@ export interface FetchJsonOptions {
|
|
|
60
60
|
body?: unknown;
|
|
61
61
|
timeoutMs?: number;
|
|
62
62
|
}
|
|
63
|
+
export type BrowserEvaluateFunction<Args extends unknown[] = unknown[], Result = unknown> = (...args: Args) => Result | Promise<Result>;
|
|
63
64
|
export interface IPage {
|
|
64
65
|
goto(url: string, options?: {
|
|
65
66
|
waitUntil?: 'load' | 'none';
|
|
66
67
|
settleMs?: number;
|
|
67
68
|
}): Promise<void>;
|
|
68
|
-
evaluate(js: string): Promise<
|
|
69
|
+
evaluate<T = any>(js: string): Promise<T>;
|
|
70
|
+
evaluate<Args extends unknown[], T>(fn: BrowserEvaluateFunction<Args, T>, ...args: Args): Promise<Awaited<T>>;
|
|
69
71
|
/** Safely evaluate JS with pre-serialized arguments — prevents injection. */
|
|
70
72
|
evaluateWithArgs?(js: string, args: Record<string, unknown>): Promise<any>;
|
|
71
73
|
/**
|
package/dist/src/update-check.js
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
import * as fs from 'node:fs';
|
|
17
17
|
import * as path from 'node:path';
|
|
18
18
|
import * as os from 'node:os';
|
|
19
|
-
import { styleText } from 'node:util';
|
|
20
19
|
import { PKG_VERSION } from './version.js';
|
|
21
20
|
const CACHE_DIR = path.join(os.homedir(), '.opencli');
|
|
22
21
|
const CACHE_FILE = path.join(CACHE_DIR, 'update-check.json');
|
|
@@ -70,8 +69,8 @@ function buildUpdateNotices({ cliVersion, cache, now }) {
|
|
|
70
69
|
const lines = {};
|
|
71
70
|
if (cache.latestVersion && isNewer(cache.latestVersion, cliVersion)) {
|
|
72
71
|
lines.cli =
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
`\n Update available: v${cliVersion} → v${cache.latestVersion}\n` +
|
|
73
|
+
` Run: npm install -g @jackwener/opencli\n`;
|
|
75
74
|
}
|
|
76
75
|
const { currentExtensionVersion, latestExtensionVersion, extensionLastSeenAt } = cache;
|
|
77
76
|
if (currentExtensionVersion &&
|
|
@@ -80,8 +79,8 @@ function buildUpdateNotices({ cliVersion, cache, now }) {
|
|
|
80
79
|
now - extensionLastSeenAt < EXTENSION_STALE_MS &&
|
|
81
80
|
isNewer(latestExtensionVersion, currentExtensionVersion)) {
|
|
82
81
|
lines.extension =
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
`\n Extension update available: v${currentExtensionVersion} → v${latestExtensionVersion}\n` +
|
|
83
|
+
` Download: https://github.com/jackwener/opencli/releases\n`;
|
|
85
84
|
}
|
|
86
85
|
return lines;
|
|
87
86
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jackwener/opencli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.19",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"description": "Make any website or Electron App your CLI. AI-powered.",
|
|
8
8
|
"engines": {
|
|
9
|
-
"node": ">=
|
|
9
|
+
"node": ">=20.0.0"
|
|
10
10
|
},
|
|
11
11
|
"type": "module",
|
|
12
12
|
"main": "dist/src/main.js",
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
"scripts": {
|
|
42
42
|
"dev": "tsx src/main.ts",
|
|
43
43
|
"dev:bun": "bun src/main.ts",
|
|
44
|
-
"build": "npm run clean-dist &&
|
|
44
|
+
"build": "npm run clean-dist && npm run copy-yaml && npm run build-manifest",
|
|
45
|
+
"prebuild-manifest": "tsc --build",
|
|
45
46
|
"build-manifest": "tsx src/build-manifest.ts",
|
|
46
47
|
"clean-dist": "node scripts/clean-dist.cjs",
|
|
47
48
|
"copy-yaml": "node scripts/copy-yaml.cjs",
|
|
@@ -83,7 +84,7 @@
|
|
|
83
84
|
"js-yaml": "^4.1.0",
|
|
84
85
|
"turndown": "^7.2.2",
|
|
85
86
|
"turndown-plugin-gfm": "^1.0.2",
|
|
86
|
-
"undici": "^
|
|
87
|
+
"undici": "^6.25.0",
|
|
87
88
|
"ws": "^8.18.0"
|
|
88
89
|
},
|
|
89
90
|
"devDependencies": {
|