@jackwener/opencli 1.0.1 → 1.0.4
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/.github/workflows/build-extension.yml +80 -0
- package/.github/workflows/ci.yml +6 -6
- package/.github/workflows/docs.yml +52 -0
- package/.github/workflows/e2e-headed.yml +2 -2
- package/.github/workflows/pkg-pr-new.yml +2 -2
- package/.github/workflows/release.yml +2 -5
- package/.github/workflows/security.yml +2 -2
- package/CDP.md +1 -1
- package/CDP.zh-CN.md +1 -1
- package/README.md +42 -34
- package/README.zh-CN.md +42 -34
- package/SKILL.md +3 -5
- package/dist/browser/cdp.d.ts +42 -0
- package/dist/browser/cdp.js +339 -0
- package/dist/browser/daemon-client.d.ts +3 -1
- package/dist/browser/daemon-client.js +4 -0
- package/dist/browser/dom-helpers.d.ts +20 -0
- package/dist/browser/dom-helpers.js +109 -0
- package/dist/browser/index.d.ts +3 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/mcp.d.ts +1 -0
- package/dist/browser/mcp.js +10 -5
- package/dist/browser/page.d.ts +7 -0
- package/dist/browser/page.js +39 -123
- package/dist/browser/utils.d.ts +10 -0
- package/dist/browser/utils.js +27 -0
- package/dist/browser.test.js +49 -1
- package/dist/build-manifest.js +3 -1
- package/dist/build-manifest.test.js +34 -0
- package/dist/capabilityRouting.d.ts +2 -0
- package/dist/capabilityRouting.js +30 -0
- package/dist/capabilityRouting.test.d.ts +1 -0
- package/dist/capabilityRouting.test.js +42 -0
- package/dist/chaoxing.d.ts +58 -0
- package/dist/chaoxing.js +225 -0
- package/dist/chaoxing.test.d.ts +1 -0
- package/dist/chaoxing.test.js +45 -0
- package/dist/cli-manifest.json +885 -48
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +234 -0
- package/dist/clis/antigravity/serve.d.ts +14 -0
- package/dist/clis/antigravity/serve.js +263 -0
- package/dist/clis/bilibili/download.js +4 -14
- package/dist/clis/boss/chatlist.d.ts +1 -0
- package/dist/clis/boss/chatlist.js +50 -0
- package/dist/clis/boss/chatmsg.d.ts +1 -0
- package/dist/clis/boss/chatmsg.js +73 -0
- package/dist/clis/boss/resume.d.ts +1 -0
- package/dist/clis/boss/resume.js +249 -0
- package/dist/clis/boss/send.d.ts +1 -0
- package/dist/clis/boss/send.js +176 -0
- package/dist/clis/chaoxing/assignments.d.ts +1 -0
- package/dist/clis/chaoxing/assignments.js +74 -0
- package/dist/clis/chaoxing/exams.d.ts +1 -0
- package/dist/clis/chaoxing/exams.js +74 -0
- package/dist/clis/chatgpt/ask.js +15 -14
- package/dist/clis/chatgpt/ax.d.ts +1 -0
- package/dist/clis/chatgpt/ax.js +78 -0
- package/dist/clis/chatgpt/read.js +5 -6
- package/dist/clis/hf/top.d.ts +1 -0
- package/dist/clis/hf/top.js +119 -0
- package/dist/clis/jike/comment.d.ts +1 -0
- package/dist/clis/jike/comment.js +107 -0
- package/dist/clis/jike/create.d.ts +1 -0
- package/dist/clis/jike/create.js +106 -0
- package/dist/clis/jike/feed.d.ts +1 -0
- package/dist/clis/jike/feed.js +67 -0
- package/dist/clis/jike/like.d.ts +1 -0
- package/dist/clis/jike/like.js +61 -0
- package/dist/clis/jike/notifications.d.ts +1 -0
- package/dist/clis/jike/notifications.js +169 -0
- package/dist/clis/jike/post.yaml +58 -0
- package/dist/clis/jike/repost.d.ts +1 -0
- package/dist/clis/jike/repost.js +103 -0
- package/dist/clis/jike/search.d.ts +1 -0
- package/dist/clis/jike/search.js +67 -0
- package/dist/clis/jike/shared.d.ts +19 -0
- package/dist/clis/jike/shared.js +25 -0
- package/dist/clis/jike/topic.yaml +52 -0
- package/dist/clis/jike/user.yaml +51 -0
- package/dist/clis/smzdm/search.js +28 -39
- package/dist/clis/stackoverflow/bounties.yaml +29 -0
- package/dist/clis/stackoverflow/hot.yaml +28 -0
- package/dist/clis/stackoverflow/search.yaml +32 -0
- package/dist/clis/stackoverflow/unanswered.yaml +28 -0
- package/dist/clis/twitter/download.js +6 -16
- package/dist/clis/twitter/post.js +9 -2
- package/dist/clis/twitter/search.js +14 -33
- package/dist/clis/xiaohongshu/download.d.ts +1 -1
- package/dist/clis/xiaohongshu/download.js +4 -4
- package/dist/clis/zhihu/download.js +3 -3
- package/dist/doctor.d.ts +7 -0
- package/dist/doctor.js +16 -0
- package/dist/download/index.d.ts +12 -8
- package/dist/download/index.js +11 -3
- package/dist/download/index.test.d.ts +1 -0
- package/dist/download/index.test.js +14 -0
- package/dist/engine.js +25 -14
- package/dist/explore.d.ts +1 -0
- package/dist/explore.js +48 -103
- package/dist/generate.js +1 -0
- package/dist/interceptor.js +3 -2
- package/dist/main.js +4 -193
- package/dist/output.d.ts +2 -1
- package/dist/output.js +3 -1
- package/dist/pipeline/executor.test.js +1 -0
- package/dist/pipeline/steps/download.js +14 -18
- package/dist/registry.d.ts +4 -3
- package/dist/registry.js +5 -2
- package/dist/runtime.d.ts +4 -1
- package/dist/runtime.js +2 -2
- package/dist/scripts/framework.d.ts +4 -0
- package/dist/scripts/framework.js +21 -0
- package/dist/scripts/interact.d.ts +4 -0
- package/dist/scripts/interact.js +20 -0
- package/dist/scripts/store.d.ts +9 -0
- package/dist/scripts/store.js +44 -0
- package/dist/synthesize.js +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/verify.d.ts +6 -1
- package/dist/verify.js +54 -2
- package/docs/.vitepress/config.mts +193 -0
- package/docs/adapters/browser/apple-podcasts.md +28 -0
- package/docs/adapters/browser/bbc.md +26 -0
- package/docs/adapters/browser/bilibili.md +38 -0
- package/docs/adapters/browser/boss.md +28 -0
- package/docs/adapters/browser/coupang.md +28 -0
- package/docs/adapters/browser/ctrip.md +27 -0
- package/docs/adapters/browser/github.md +26 -0
- package/docs/adapters/browser/hackernews.md +26 -0
- package/docs/adapters/browser/linkedin.md +27 -0
- package/docs/adapters/browser/reddit.md +41 -0
- package/docs/adapters/browser/reuters.md +27 -0
- package/docs/adapters/browser/smzdm.md +27 -0
- package/docs/adapters/browser/twitter.md +47 -0
- package/docs/adapters/browser/v2ex.md +32 -0
- package/docs/adapters/browser/weibo.md +27 -0
- package/docs/adapters/browser/xiaohongshu.md +32 -0
- package/docs/adapters/browser/xiaoyuzhou.md +28 -0
- package/docs/adapters/browser/xueqiu.md +32 -0
- package/docs/adapters/browser/yahoo-finance.md +26 -0
- package/docs/adapters/browser/youtube.md +29 -0
- package/docs/adapters/browser/zhihu.md +30 -0
- package/docs/adapters/desktop/antigravity.md +46 -0
- package/docs/adapters/desktop/chatgpt.md +43 -0
- package/docs/adapters/desktop/chatwise.md +38 -0
- package/docs/adapters/desktop/codex.md +32 -0
- package/docs/adapters/desktop/cursor.md +33 -0
- package/docs/adapters/desktop/discord.md +28 -0
- package/docs/adapters/desktop/feishu.md +20 -0
- package/docs/adapters/desktop/neteasemusic.md +31 -0
- package/docs/adapters/desktop/notion.md +29 -0
- package/docs/adapters/desktop/wechat.md +28 -0
- package/docs/adapters/index.md +49 -0
- package/docs/advanced/cdp.md +103 -0
- package/docs/advanced/download.md +63 -0
- package/docs/advanced/electron.md +125 -0
- package/docs/advanced/remote-chrome.md +72 -0
- package/docs/developer/ai-workflow.md +66 -0
- package/docs/developer/architecture.md +90 -0
- package/docs/developer/contributing.md +136 -0
- package/docs/developer/testing.md +237 -0
- package/docs/developer/ts-adapter.md +87 -0
- package/docs/developer/yaml-adapter.md +108 -0
- package/docs/guide/browser-bridge.md +38 -0
- package/docs/guide/getting-started.md +56 -0
- package/docs/guide/installation.md +37 -0
- package/docs/guide/troubleshooting.md +56 -0
- package/docs/index.md +35 -0
- package/docs/zh/adapters/index.md +5 -0
- package/docs/zh/advanced/cdp.md +3 -0
- package/docs/zh/developer/contributing.md +24 -0
- package/docs/zh/guide/browser-bridge.md +25 -0
- package/docs/zh/guide/getting-started.md +40 -0
- package/docs/zh/guide/installation.md +37 -0
- package/docs/zh/index.md +29 -0
- package/extension/dist/background.js +386 -438
- package/extension/manifest.json +2 -2
- package/extension/package-lock.json +1156 -0
- package/extension/src/background.test.ts +151 -0
- package/extension/src/background.ts +124 -53
- package/extension/src/protocol.ts +3 -1
- package/package.json +7 -3
- package/src/browser/cdp.ts +367 -0
- package/src/browser/daemon-client.ts +7 -1
- package/src/browser/dom-helpers.ts +116 -0
- package/src/browser/index.ts +4 -0
- package/src/browser/mcp.ts +14 -6
- package/src/browser/page.ts +47 -124
- package/src/browser/utils.ts +27 -0
- package/src/browser.test.ts +56 -0
- package/src/build-manifest.test.ts +36 -0
- package/src/build-manifest.ts +2 -1
- package/src/capabilityRouting.test.ts +47 -0
- package/src/capabilityRouting.ts +28 -0
- package/src/chaoxing.test.ts +53 -0
- package/src/chaoxing.ts +268 -0
- package/src/cli.ts +205 -0
- package/src/clis/antigravity/SKILL.md +5 -0
- package/src/clis/antigravity/serve.ts +329 -0
- package/src/clis/bilibili/download.ts +4 -15
- package/src/clis/boss/chatlist.ts +50 -0
- package/src/clis/boss/chatmsg.ts +70 -0
- package/src/clis/boss/resume.ts +262 -0
- package/src/clis/boss/send.ts +193 -0
- package/src/clis/chaoxing/README.md +36 -0
- package/src/clis/chaoxing/README.zh-CN.md +35 -0
- package/src/clis/chaoxing/assignments.ts +88 -0
- package/src/clis/chaoxing/exams.ts +88 -0
- package/src/clis/chatgpt/ask.ts +14 -15
- package/src/clis/chatgpt/ax.ts +81 -0
- package/src/clis/chatgpt/read.ts +5 -7
- package/src/clis/hf/top.ts +141 -0
- package/src/clis/jike/comment.ts +113 -0
- package/src/clis/jike/create.ts +113 -0
- package/src/clis/jike/feed.ts +74 -0
- package/src/clis/jike/like.ts +65 -0
- package/src/clis/jike/notifications.ts +185 -0
- package/src/clis/jike/post.yaml +58 -0
- package/src/clis/jike/repost.ts +114 -0
- package/src/clis/jike/search.ts +74 -0
- package/src/clis/jike/shared.ts +36 -0
- package/src/clis/jike/topic.yaml +52 -0
- package/src/clis/jike/user.yaml +51 -0
- package/src/clis/smzdm/search.ts +30 -39
- package/src/clis/stackoverflow/bounties.yaml +29 -0
- package/src/clis/stackoverflow/hot.yaml +28 -0
- package/src/clis/stackoverflow/search.yaml +32 -0
- package/src/clis/stackoverflow/unanswered.yaml +28 -0
- package/src/clis/twitter/download.ts +6 -17
- package/src/clis/twitter/post.ts +9 -2
- package/src/clis/twitter/search.ts +15 -33
- package/src/clis/xiaohongshu/download.ts +4 -4
- package/src/clis/zhihu/download.ts +3 -3
- package/src/doctor.ts +18 -2
- package/src/download/index.test.ts +16 -0
- package/src/download/index.ts +22 -4
- package/src/engine.ts +20 -13
- package/src/explore.ts +54 -103
- package/src/generate.ts +1 -0
- package/src/interceptor.ts +3 -2
- package/src/main.ts +4 -180
- package/src/output.ts +15 -13
- package/src/pipeline/executor.test.ts +1 -0
- package/src/pipeline/steps/download.ts +14 -17
- package/src/registry.ts +9 -5
- package/src/runtime.ts +3 -2
- package/src/scripts/framework.ts +20 -0
- package/src/scripts/interact.ts +22 -0
- package/src/scripts/store.ts +40 -0
- package/src/synthesize.ts +1 -1
- package/src/types.ts +9 -0
- package/src/verify.ts +64 -3
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
generateFilename,
|
|
24
24
|
exportCookiesToNetscape,
|
|
25
25
|
getTempDir,
|
|
26
|
+
formatCookieHeader,
|
|
26
27
|
} from '../../download/index.js';
|
|
27
28
|
import { DownloadProgressTracker, formatBytes } from '../../download/progress.js';
|
|
28
29
|
|
|
@@ -62,9 +63,8 @@ async function mapConcurrent<T, R>(
|
|
|
62
63
|
*/
|
|
63
64
|
async function extractBrowserCookies(page: IPage, domain?: string): Promise<string> {
|
|
64
65
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return typeof cookieString === 'string' ? cookieString : '';
|
|
66
|
+
const cookies = await page.getCookies(domain ? { domain } : {});
|
|
67
|
+
return formatCookieHeader(cookies);
|
|
68
68
|
} catch {
|
|
69
69
|
return '';
|
|
70
70
|
}
|
|
@@ -78,20 +78,17 @@ async function extractCookiesArray(
|
|
|
78
78
|
domain: string,
|
|
79
79
|
): Promise<Array<{ name: string; value: string; domain: string; path: string; secure: boolean; httpOnly: boolean }>> {
|
|
80
80
|
try {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
httpOnly: false,
|
|
93
|
-
};
|
|
94
|
-
}).filter((c) => c.name);
|
|
81
|
+
const cookies = await page.getCookies({ domain });
|
|
82
|
+
return cookies
|
|
83
|
+
.filter((cookie) => cookie.name)
|
|
84
|
+
.map((cookie) => ({
|
|
85
|
+
name: cookie.name,
|
|
86
|
+
value: cookie.value,
|
|
87
|
+
domain: cookie.domain,
|
|
88
|
+
path: cookie.path ?? '/',
|
|
89
|
+
secure: cookie.secure ?? false,
|
|
90
|
+
httpOnly: cookie.httpOnly ?? false,
|
|
91
|
+
}));
|
|
95
92
|
} catch {
|
|
96
93
|
return [];
|
|
97
94
|
}
|
package/src/registry.ts
CHANGED
|
@@ -15,7 +15,7 @@ export enum Strategy {
|
|
|
15
15
|
export interface Arg {
|
|
16
16
|
name: string;
|
|
17
17
|
type?: string;
|
|
18
|
-
default?:
|
|
18
|
+
default?: unknown;
|
|
19
19
|
required?: boolean;
|
|
20
20
|
positional?: boolean;
|
|
21
21
|
help?: string;
|
|
@@ -31,10 +31,11 @@ export interface CliCommand {
|
|
|
31
31
|
browser?: boolean;
|
|
32
32
|
args: Arg[];
|
|
33
33
|
columns?: string[];
|
|
34
|
-
func?: (page: IPage, kwargs: Record<string, any>, debug?: boolean) => Promise<
|
|
35
|
-
pipeline?:
|
|
34
|
+
func?: (page: IPage, kwargs: Record<string, any>, debug?: boolean) => Promise<unknown>;
|
|
35
|
+
pipeline?: Record<string, unknown>[];
|
|
36
36
|
timeoutSeconds?: number;
|
|
37
37
|
source?: string;
|
|
38
|
+
footerExtra?: (kwargs: Record<string, any>) => string | undefined;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/** Internal extension for lazy-loaded TS modules (not exposed in public API) */
|
|
@@ -51,18 +52,21 @@ export interface CliOptions extends Partial<Omit<CliCommand, 'args' | 'descripti
|
|
|
51
52
|
const _registry = new Map<string, CliCommand>();
|
|
52
53
|
|
|
53
54
|
export function cli(opts: CliOptions): CliCommand {
|
|
55
|
+
const strategy = opts.strategy ?? (opts.browser === false ? Strategy.PUBLIC : Strategy.COOKIE);
|
|
56
|
+
const browser = opts.browser ?? (strategy !== Strategy.PUBLIC);
|
|
54
57
|
const cmd: CliCommand = {
|
|
55
58
|
site: opts.site,
|
|
56
59
|
name: opts.name,
|
|
57
60
|
description: opts.description ?? '',
|
|
58
61
|
domain: opts.domain,
|
|
59
|
-
strategy
|
|
60
|
-
browser
|
|
62
|
+
strategy,
|
|
63
|
+
browser,
|
|
61
64
|
args: opts.args ?? [],
|
|
62
65
|
columns: opts.columns,
|
|
63
66
|
func: opts.func,
|
|
64
67
|
pipeline: opts.pipeline,
|
|
65
68
|
timeoutSeconds: opts.timeoutSeconds,
|
|
69
|
+
footerExtra: opts.footerExtra,
|
|
66
70
|
};
|
|
67
71
|
|
|
68
72
|
const key = fullName(cmd);
|
package/src/runtime.ts
CHANGED
|
@@ -30,17 +30,18 @@ export function withTimeoutMs<T>(promise: Promise<T>, timeoutMs: number, message
|
|
|
30
30
|
|
|
31
31
|
/** Interface for browser factory (BrowserBridge or test mocks) */
|
|
32
32
|
export interface IBrowserFactory {
|
|
33
|
-
connect(opts?: { timeout?: number }): Promise<IPage>;
|
|
33
|
+
connect(opts?: { timeout?: number; workspace?: string }): Promise<IPage>;
|
|
34
34
|
close(): Promise<void>;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export async function browserSession<T>(
|
|
38
38
|
BrowserFactory: new () => IBrowserFactory,
|
|
39
39
|
fn: (page: IPage) => Promise<T>,
|
|
40
|
+
opts: { workspace?: string } = {},
|
|
40
41
|
): Promise<T> {
|
|
41
42
|
const mcp = new BrowserFactory();
|
|
42
43
|
try {
|
|
43
|
-
const page = await mcp.connect({ timeout: DEFAULT_BROWSER_CONNECT_TIMEOUT });
|
|
44
|
+
const page = await mcp.connect({ timeout: DEFAULT_BROWSER_CONNECT_TIMEOUT, workspace: opts.workspace });
|
|
44
45
|
return await fn(page);
|
|
45
46
|
} finally {
|
|
46
47
|
await mcp.close().catch(() => {});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected script for detecting frontend frameworks (Vue, React, Next, Nuxt, etc.)
|
|
3
|
+
*/
|
|
4
|
+
export function detectFramework() {
|
|
5
|
+
const r: Record<string, boolean> = {};
|
|
6
|
+
try {
|
|
7
|
+
const app = document.querySelector('#app') as any;
|
|
8
|
+
r.vue3 = !!(app && app.__vue_app__);
|
|
9
|
+
r.vue2 = !!(app && app.__vue__);
|
|
10
|
+
r.react = !!(window as any).__REACT_DEVTOOLS_GLOBAL_HOOK__ || !!document.querySelector('[data-reactroot]');
|
|
11
|
+
r.nextjs = !!(window as any).__NEXT_DATA__;
|
|
12
|
+
r.nuxt = !!(window as any).__NUXT__;
|
|
13
|
+
if (r.vue3 && app.__vue_app__) {
|
|
14
|
+
const gp = app.__vue_app__.config?.globalProperties;
|
|
15
|
+
r.pinia = !!(gp && gp.$pinia);
|
|
16
|
+
r.vuex = !!(gp && gp.$store);
|
|
17
|
+
}
|
|
18
|
+
} catch {}
|
|
19
|
+
return r;
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected script for interactive fuzzing (clicking elements to trigger lazy loading)
|
|
3
|
+
*/
|
|
4
|
+
export async function interactFuzz() {
|
|
5
|
+
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
|
|
6
|
+
const clickables = Array.from(document.querySelectorAll(
|
|
7
|
+
'button, [role="button"], [role="tab"], .tab, .btn, a[href="javascript:void(0)"], a[href="#"]'
|
|
8
|
+
)).slice(0, 15); // limit to a small number to avoid endless loops
|
|
9
|
+
|
|
10
|
+
let clicked = 0;
|
|
11
|
+
for (const el of clickables) {
|
|
12
|
+
try {
|
|
13
|
+
const rect = el.getBoundingClientRect();
|
|
14
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
15
|
+
el.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
|
|
16
|
+
clicked++;
|
|
17
|
+
await sleep(300); // give it time to trigger network
|
|
18
|
+
}
|
|
19
|
+
} catch {}
|
|
20
|
+
}
|
|
21
|
+
return clicked;
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected script for discovering Pinia or Vuex stores and their actions/state representations
|
|
3
|
+
*/
|
|
4
|
+
export function discoverStores() {
|
|
5
|
+
const stores: Array<{ type: string; id: string; actions: string[]; stateKeys: string[] }> = [];
|
|
6
|
+
try {
|
|
7
|
+
const app = document.querySelector('#app') as any;
|
|
8
|
+
if (!app?.__vue_app__) return stores;
|
|
9
|
+
const gp = app.__vue_app__.config?.globalProperties;
|
|
10
|
+
|
|
11
|
+
// Pinia stores
|
|
12
|
+
const pinia = gp?.$pinia;
|
|
13
|
+
if (pinia?._s) {
|
|
14
|
+
pinia._s.forEach((store: any, id: string) => {
|
|
15
|
+
const actions: string[] = [];
|
|
16
|
+
const stateKeys: string[] = [];
|
|
17
|
+
for (const k in store) {
|
|
18
|
+
try {
|
|
19
|
+
if (k.startsWith('$') || k.startsWith('_')) continue;
|
|
20
|
+
if (typeof store[k] === 'function') actions.push(k);
|
|
21
|
+
else stateKeys.push(k);
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
stores.push({ type: 'pinia', id, actions: actions.slice(0, 20), stateKeys: stateKeys.slice(0, 15) });
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Vuex store modules
|
|
29
|
+
const vuex = gp?.$store;
|
|
30
|
+
if (vuex?._modules?.root?._children) {
|
|
31
|
+
const children = vuex._modules.root._children;
|
|
32
|
+
for (const [modName, mod] of Object.entries<any>(children)) {
|
|
33
|
+
const actions = Object.keys(mod._rawModule?.actions ?? {}).slice(0, 20);
|
|
34
|
+
const stateKeys = Object.keys(mod.state ?? {}).slice(0, 15);
|
|
35
|
+
stores.push({ type: 'vuex', id: modName, actions, stateKeys });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} catch {}
|
|
39
|
+
return stores;
|
|
40
|
+
}
|
package/src/synthesize.ts
CHANGED
|
@@ -116,7 +116,7 @@ function buildEvaluateScript(url: string, itemPath: string, endpoint: any): stri
|
|
|
116
116
|
|
|
117
117
|
return [
|
|
118
118
|
'(async () => {',
|
|
119
|
-
` const res = await fetch(
|
|
119
|
+
` const res = await fetch(${JSON.stringify(url)}, {`,
|
|
120
120
|
` credentials: 'include'`,
|
|
121
121
|
' });',
|
|
122
122
|
' const data = await res.json();',
|
package/src/types.ts
CHANGED
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
export interface IPage {
|
|
9
9
|
goto(url: string): Promise<void>;
|
|
10
10
|
evaluate(js: string): Promise<any>;
|
|
11
|
+
getCookies(opts?: { domain?: string; url?: string }): Promise<Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
value: string;
|
|
14
|
+
domain: string;
|
|
15
|
+
path?: string;
|
|
16
|
+
secure?: boolean;
|
|
17
|
+
httpOnly?: boolean;
|
|
18
|
+
expirationDate?: number;
|
|
19
|
+
}>>;
|
|
11
20
|
snapshot(opts?: { interactive?: boolean; compact?: boolean; maxDepth?: number; raw?: boolean }): Promise<any>;
|
|
12
21
|
click(ref: string): Promise<void>;
|
|
13
22
|
typeText(ref: string, text: string): Promise<void>;
|
package/src/verify.ts
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { validateClisWithTarget, renderValidationReport, type ValidationReport } from './validate.js';
|
|
10
|
+
import { spawn } from 'node:child_process';
|
|
11
|
+
import * as fs from 'node:fs';
|
|
12
|
+
import * as path from 'node:path';
|
|
10
13
|
|
|
11
14
|
export interface VerifyOptions {
|
|
12
15
|
builtinClis: string;
|
|
@@ -18,15 +21,73 @@ export interface VerifyOptions {
|
|
|
18
21
|
export interface VerifyReport {
|
|
19
22
|
ok: boolean;
|
|
20
23
|
validation: ValidationReport;
|
|
21
|
-
smoke: null
|
|
24
|
+
smoke: null | {
|
|
25
|
+
requested: boolean;
|
|
26
|
+
executed: boolean;
|
|
27
|
+
ok: boolean;
|
|
28
|
+
summary: string;
|
|
29
|
+
};
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
export async function verifyClis(opts: VerifyOptions): Promise<VerifyReport> {
|
|
25
33
|
const report = validateClisWithTarget([opts.builtinClis, opts.userClis], opts.target);
|
|
26
|
-
|
|
34
|
+
let smoke: VerifyReport['smoke'] = null;
|
|
35
|
+
if (opts.smoke) {
|
|
36
|
+
smoke = await runSmokeTests(opts.builtinClis);
|
|
37
|
+
}
|
|
38
|
+
return { ok: report.ok && (smoke?.ok ?? true), validation: report, smoke };
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
export function renderVerifyReport(report: VerifyReport): string {
|
|
30
|
-
|
|
42
|
+
const base = renderValidationReport(report.validation);
|
|
43
|
+
if (!report.smoke) return base;
|
|
44
|
+
const status = report.smoke.ok ? 'PASS' : 'FAIL';
|
|
45
|
+
const mode = report.smoke.executed ? 'executed' : 'skipped';
|
|
46
|
+
return `${base}\nSmoke: ${status} (${mode}) — ${report.smoke.summary}`;
|
|
31
47
|
}
|
|
32
48
|
|
|
49
|
+
async function runSmokeTests(builtinClis: string): Promise<NonNullable<VerifyReport['smoke']>> {
|
|
50
|
+
const projectRoot = path.resolve(builtinClis, '..', '..');
|
|
51
|
+
const smokeDir = path.join(projectRoot, 'tests', 'smoke');
|
|
52
|
+
|
|
53
|
+
if (!fs.existsSync(smokeDir)) {
|
|
54
|
+
return {
|
|
55
|
+
requested: true,
|
|
56
|
+
executed: false,
|
|
57
|
+
ok: false,
|
|
58
|
+
summary: 'Smoke tests are unavailable in this package/environment.',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
const child = spawn(npx, ['vitest', 'run', 'tests/smoke/', '--reporter=dot'], {
|
|
65
|
+
cwd: projectRoot,
|
|
66
|
+
env: { ...process.env },
|
|
67
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
let stderr = '';
|
|
71
|
+
child.stderr.on('data', (chunk) => {
|
|
72
|
+
stderr += chunk.toString();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
child.on('error', (error) => {
|
|
76
|
+
resolve({
|
|
77
|
+
requested: true,
|
|
78
|
+
executed: false,
|
|
79
|
+
ok: false,
|
|
80
|
+
summary: `Failed to start smoke tests: ${error.message}`,
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
child.on('close', (code) => {
|
|
85
|
+
resolve({
|
|
86
|
+
requested: true,
|
|
87
|
+
executed: true,
|
|
88
|
+
ok: code === 0,
|
|
89
|
+
summary: code === 0 ? 'tests/smoke passed' : (stderr.trim() || `vitest exited with code ${code}`),
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|