@jackwener/opencli 1.7.17 → 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.
Files changed (118) hide show
  1. package/README.md +10 -8
  2. package/README.zh-CN.md +9 -8
  3. package/cli-manifest.json +585 -9
  4. package/clis/ctrip/ctrip.test.js +486 -1
  5. package/clis/ctrip/flight.js +136 -0
  6. package/clis/ctrip/hotel-search.js +132 -0
  7. package/clis/ctrip/utils.js +298 -0
  8. package/clis/doubao/utils.js +17 -0
  9. package/clis/doubao/utils.test.js +61 -0
  10. package/clis/google/search.js +16 -6
  11. package/clis/google-scholar/search.js +20 -5
  12. package/clis/google-scholar/search.test.js +35 -2
  13. package/clis/reddit/home.js +117 -0
  14. package/clis/reddit/home.test.js +127 -0
  15. package/clis/reddit/read.js +400 -54
  16. package/clis/reddit/read.test.js +315 -12
  17. package/clis/reddit/reply.js +182 -0
  18. package/clis/reddit/reply.test.js +89 -0
  19. package/clis/reddit/subreddit-info.js +117 -0
  20. package/clis/reddit/subreddit-info.test.js +163 -0
  21. package/clis/reddit/whoami.js +84 -0
  22. package/clis/reddit/whoami.test.js +105 -0
  23. package/clis/rednote/comments.js +76 -0
  24. package/clis/rednote/download.js +59 -0
  25. package/clis/rednote/feed.js +95 -0
  26. package/clis/rednote/navigation.test.js +26 -0
  27. package/clis/rednote/note.js +68 -0
  28. package/clis/rednote/notifications.js +139 -0
  29. package/clis/rednote/rednote.test.js +157 -0
  30. package/clis/rednote/search.js +101 -0
  31. package/clis/rednote/user.js +55 -0
  32. package/clis/twitter/bookmark-folder.js +3 -1
  33. package/clis/twitter/bookmarks.js +3 -1
  34. package/clis/twitter/followers.js +20 -5
  35. package/clis/twitter/followers.test.js +44 -0
  36. package/clis/twitter/following.js +36 -20
  37. package/clis/twitter/following.test.js +60 -8
  38. package/clis/twitter/likes.js +28 -13
  39. package/clis/twitter/likes.test.js +111 -1
  40. package/clis/twitter/list-add.js +128 -204
  41. package/clis/twitter/list-add.test.js +97 -1
  42. package/clis/twitter/list-tweets.js +13 -4
  43. package/clis/twitter/list-tweets.test.js +48 -0
  44. package/clis/twitter/lists.js +5 -2
  45. package/clis/twitter/post.js +23 -4
  46. package/clis/twitter/post.test.js +30 -0
  47. package/clis/twitter/profile.js +16 -8
  48. package/clis/twitter/profile.test.js +39 -0
  49. package/clis/twitter/reply.js +133 -10
  50. package/clis/twitter/reply.test.js +55 -0
  51. package/clis/twitter/search.js +188 -170
  52. package/clis/twitter/search.test.js +96 -258
  53. package/clis/twitter/shared.js +167 -16
  54. package/clis/twitter/shared.test.js +102 -1
  55. package/clis/twitter/timeline.js +3 -1
  56. package/clis/twitter/tweets.js +147 -51
  57. package/clis/twitter/tweets.test.js +238 -1
  58. package/clis/xiaohongshu/comments.js +57 -26
  59. package/clis/xiaohongshu/comments.test.js +63 -1
  60. package/clis/xiaohongshu/download.js +32 -23
  61. package/clis/xiaohongshu/feed.js +23 -15
  62. package/clis/xiaohongshu/note-helpers.js +16 -6
  63. package/clis/xiaohongshu/note.js +26 -20
  64. package/clis/xiaohongshu/notifications.js +26 -19
  65. package/clis/xiaohongshu/search.js +201 -37
  66. package/clis/xiaohongshu/search.test.js +82 -8
  67. package/clis/xiaohongshu/user-helpers.js +13 -4
  68. package/clis/xiaohongshu/user-helpers.test.js +20 -0
  69. package/clis/xiaohongshu/user.js +9 -4
  70. package/clis/xueqiu/earnings-date.js +2 -2
  71. package/clis/xueqiu/kline.js +2 -2
  72. package/clis/xueqiu/utils.js +19 -0
  73. package/clis/xueqiu/utils.test.js +26 -0
  74. package/clis/youtube/transcript.js +28 -3
  75. package/clis/youtube/transcript.test.js +90 -1
  76. package/clis/zhihu/answer-detail.js +233 -0
  77. package/clis/zhihu/answer-detail.test.js +330 -0
  78. package/clis/zhihu/question.js +44 -10
  79. package/clis/zhihu/question.test.js +78 -1
  80. package/clis/zhihu/recommend.js +103 -0
  81. package/clis/zhihu/recommend.test.js +143 -0
  82. package/dist/src/browser/base-page.d.ts +3 -2
  83. package/dist/src/browser/base-page.test.js +2 -2
  84. package/dist/src/browser/cdp.js +3 -3
  85. package/dist/src/browser/page.d.ts +3 -2
  86. package/dist/src/browser/page.js +4 -4
  87. package/dist/src/browser/page.test.js +31 -0
  88. package/dist/src/browser/utils.d.ts +10 -0
  89. package/dist/src/browser/utils.js +37 -0
  90. package/dist/src/browser/utils.test.d.ts +1 -0
  91. package/dist/src/browser/utils.test.js +29 -0
  92. package/dist/src/cli-argv-preprocess.d.ts +37 -0
  93. package/dist/src/cli-argv-preprocess.js +131 -0
  94. package/dist/src/cli-argv-preprocess.test.d.ts +1 -0
  95. package/dist/src/cli-argv-preprocess.test.js +130 -0
  96. package/dist/src/cli.js +123 -86
  97. package/dist/src/cli.test.js +32 -22
  98. package/dist/src/commands/daemon.js +6 -7
  99. package/dist/src/doctor.js +21 -17
  100. package/dist/src/doctor.test.js +2 -0
  101. package/dist/src/download/progress.js +15 -11
  102. package/dist/src/download/progress.test.d.ts +1 -0
  103. package/dist/src/download/progress.test.js +25 -0
  104. package/dist/src/execution.js +1 -3
  105. package/dist/src/execution.test.js +4 -16
  106. package/dist/src/help.d.ts +11 -0
  107. package/dist/src/help.js +46 -5
  108. package/dist/src/logger.js +8 -9
  109. package/dist/src/main.js +16 -0
  110. package/dist/src/output.js +4 -5
  111. package/dist/src/runtime-detect.d.ts +1 -1
  112. package/dist/src/runtime-detect.js +1 -1
  113. package/dist/src/runtime-detect.test.js +3 -2
  114. package/dist/src/tui.d.ts +0 -1
  115. package/dist/src/tui.js +9 -22
  116. package/dist/src/types.d.ts +3 -1
  117. package/dist/src/update-check.js +4 -5
  118. package/package.json +5 -4
@@ -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(styleText('dim', '(no data)'));
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 => styleText('bold', 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(styleText('dim', ` ${opts.title}`));
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(styleText('dim', footer.join(' · ')));
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 = 21;
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 = 21;
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(21);
34
- expect(isSupportedNodeVersion('v20.18.0')).toBe(false);
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
@@ -4,7 +4,6 @@ export interface CheckboxItem {
4
4
  checked: boolean;
5
5
  /** Optional status to display after the label */
6
6
  status?: string;
7
- statusColor?: 'green' | 'yellow' | 'red' | 'dim';
8
7
  }
9
8
  /**
10
9
  * Interactive multi-select checkbox prompt.
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${styleText('bold', opts.title)}\n\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 ? styleText('cyan', '❯') : ' ';
48
- const checkbox = item.checked ? styleText('green', '◉') : styleText('dim', '○');
49
- const label = i === cursor ? styleText('bold', item.label) : item.label;
50
- const status = colorStatus(item.status, item.statusColor);
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 ${styleText('dim', '↑↓ navigate · Space toggle · a all · Enter confirm · q cancel')}\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(` ${styleText('green', '')} ${styleText('bold', `${selected.length} file(s) selected`)}\n\n`);
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(` ${styleText('yellow', '')} ${styleText('dim', 'Cancelled')}\n\n`);
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} ${styleText('dim', hint)} `);
139
+ stdout.write(` ${message} ${hint} `);
153
140
  return new Promise((resolve) => {
154
141
  const wasRaw = stdin.isRaw;
155
142
  stdin.setRawMode(true);
@@ -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<any>;
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
  /**
@@ -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
- styleText('yellow', `\n Update available: v${cliVersion} → v${cache.latestVersion}\n`) +
74
- styleText('dim', ` Run: npm install -g @jackwener/opencli\n`);
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
- styleText('yellow', `\n Extension update available: v${currentExtensionVersion} → v${latestExtensionVersion}\n`) +
84
- styleText('dim', ` Download: https://github.com/jackwener/opencli/releases\n`);
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.17",
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": ">=21.0.0"
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 && tsc && npm run copy-yaml && npm run build-manifest",
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": "^8.0.2",
87
+ "undici": "^6.25.0",
87
88
  "ws": "^8.18.0"
88
89
  },
89
90
  "devDependencies": {