@farview/example 0.1.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/index.html ADDED
@@ -0,0 +1,96 @@
1
+ <!doctype html>
2
+ <html lang="zh">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Farview E2E 测试页</title>
7
+ <style>
8
+ body {
9
+ font:
10
+ 15px/1.6 system-ui,
11
+ sans-serif;
12
+ max-width: 720px;
13
+ margin: 40px auto;
14
+ padding: 0 16px;
15
+ }
16
+ h1 {
17
+ font-size: 20px;
18
+ }
19
+ .row {
20
+ display: flex;
21
+ flex-wrap: wrap;
22
+ gap: 8px;
23
+ margin: 12px 0;
24
+ }
25
+ button {
26
+ padding: 8px 14px;
27
+ border: 1px solid #ccc;
28
+ border-radius: 8px;
29
+ background: #fff;
30
+ cursor: pointer;
31
+ }
32
+ button:hover {
33
+ background: #f2f2f2;
34
+ }
35
+ input {
36
+ padding: 8px;
37
+ border: 1px solid #ccc;
38
+ border-radius: 8px;
39
+ }
40
+ #state {
41
+ padding: 8px 12px;
42
+ border-radius: 8px;
43
+ background: #f6f6f6;
44
+ font-family: monospace;
45
+ }
46
+ section {
47
+ margin: 20px 0;
48
+ padding: 12px 16px;
49
+ border: 1px solid #eee;
50
+ border-radius: 12px;
51
+ }
52
+ h2 {
53
+ font-size: 14px;
54
+ color: #666;
55
+ margin: 0 0 8px;
56
+ text-transform: uppercase;
57
+ letter-spacing: 0.04em;
58
+ }
59
+ </style>
60
+ </head>
61
+ <body>
62
+ <h1>Farview E2E 测试页</h1>
63
+ <p id="state">
64
+ agent 状态:<b id="agentState">未加载</b>(仅当 URL 带 <code>?debug=</code> 时加载)
65
+ </p>
66
+
67
+ <section>
68
+ <h2>Console</h2>
69
+ <div class="row">
70
+ <button data-act="log">console.log</button>
71
+ <button data-act="warn">console.warn</button>
72
+ <button data-act="error">console.error</button>
73
+ <button data-act="throw">抛未捕获异常</button>
74
+ </div>
75
+ </section>
76
+
77
+ <section>
78
+ <h2>Network</h2>
79
+ <div class="row">
80
+ <button data-act="fetch-ok">fetch 200 (JSON)</button>
81
+ <button data-act="fetch-404">fetch 404</button>
82
+ <button data-act="fetch-fail">fetch 失败(跨域/断网)</button>
83
+ </div>
84
+ </section>
85
+
86
+ <section>
87
+ <h2>环境 / 镜像 / eval</h2>
88
+ <p>环境快照、镜像画面由 agent 自动上报;eval 从 viewer 端执行,无需页面按钮。</p>
89
+ <div class="row">
90
+ <button data-act="mutate">改一下 DOM(验证镜像实时性)</button>
91
+ </div>
92
+ </section>
93
+
94
+ <script type="module" src="/src/main.ts"></script>
95
+ </body>
96
+ </html>
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@farview/example",
3
+ "version": "0.1.0",
4
+ "description": "Farview 端到端联调示例(Vite + TS)——按需懒加载 agent 的最小接入范式。用 `npx @farview/cli example` 释放成可改脚手架。",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "files": [
8
+ "index.html",
9
+ "tsconfig.json",
10
+ "src"
11
+ ],
12
+ "dependencies": {
13
+ "@farview/agent": "0.1.0"
14
+ },
15
+ "devDependencies": {
16
+ "typescript": "~5.7.2",
17
+ "vite": "^6.0.5"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "scripts": {
23
+ "dev": "vite --host --port 5188",
24
+ "typecheck": "tsc --noEmit"
25
+ }
26
+ }
package/src/actions.ts ADDED
@@ -0,0 +1,43 @@
1
+ // 各类可观测行为触发器,按 index.html 里按钮的 data-act 键索引。
2
+ // 点一下就在 viewer 对应面板(Console / Network / 镜像)产生一条记录。
3
+
4
+ type Action = () => void;
5
+
6
+ export const actions: Record<string, Action> = {
7
+ // --- Console / 报错 ---
8
+ log: () => console.log('[e2e] 普通日志', { ts: Date.now(), items: [1, 2, 3] }),
9
+ warn: () => console.warn('[e2e] 警告一下'),
10
+ error: () => console.error('[e2e] 错误日志', new Error('demo error')),
11
+ throw: () => {
12
+ // 未捕获异常,验证 error hook
13
+ setTimeout(() => {
14
+ throw new Error('[e2e] 未捕获的运行时异常');
15
+ }, 0);
16
+ },
17
+
18
+ // --- Network ---
19
+ 'fetch-ok': () => {
20
+ void fetch('https://jsonplaceholder.typicode.com/todos/1')
21
+ .then((r) => r.json())
22
+ .then((d) => console.log('[e2e] fetch ok', d));
23
+ },
24
+ 'fetch-404': () => {
25
+ void fetch('https://jsonplaceholder.typicode.com/nope-404').then((r) =>
26
+ console.log('[e2e] fetch status', r.status),
27
+ );
28
+ },
29
+ 'fetch-fail': () => {
30
+ // 指向一个连不上的地址,验证网络失败上报
31
+ void fetch('https://127.0.0.1:1/nope').catch((err: unknown) =>
32
+ console.log('[e2e] fetch failed', err instanceof Error ? err.message : err),
33
+ );
34
+ },
35
+
36
+ // --- 镜像实时性 ---
37
+ mutate: () => {
38
+ const tag = document.createElement('div');
39
+ tag.textContent = `镜像测试块 @ ${new Date().toLocaleTimeString()}`;
40
+ tag.style.cssText = 'margin:8px 0;padding:8px;background:#e0f2fe;border-radius:8px;';
41
+ document.body.appendChild(tag);
42
+ },
43
+ };
package/src/farview.ts ADDED
@@ -0,0 +1,32 @@
1
+ // agent 引导:仅当 URL 带 ?debug= 时懒加载并启动。
2
+ //
3
+ // 关键:这里用 `import type`(编译期擦除,不进产物),运行时才 `await import()`
4
+ // 拉真正的 agent。这样保留 README 的真实语义——正常用户(无 ?debug=)永不下载
5
+ // agent chunk,同时又能拿到完整 TS 类型。
6
+ import type { FarviewOptions } from '@farview/agent';
7
+
8
+ /** 演示用业务码表:HTTP 200 但 code≠0 时,viewer 的 Network 面板据此标红。 */
9
+ const BUSINESS_CODES: Record<number, string> = {
10
+ 1001: '未登录',
11
+ 1002: '无权限',
12
+ };
13
+
14
+ const options: FarviewOptions = {
15
+ decodeBusinessCode: (code) => (code === 0 ? '成功' : (BUSINESS_CODES[code] ?? `业务码 ${code}`)),
16
+ // 环境快照的业务补充(真实项目里密钥须自行剥离后再返回)
17
+ buildSnapshot: () => ({ tenant: 'e2e-tenant', theme: 'light' }),
18
+ };
19
+
20
+ /**
21
+ * 若 URL 带 ?debug=<隧道子域名> 则懒加载启动 agent。
22
+ * @returns 供页面显示的状态文案。
23
+ */
24
+ export async function bootstrapFarview(): Promise<string> {
25
+ const token = new URLSearchParams(location.search).get('debug');
26
+ if (!token) {
27
+ return '未加载(安全:无 ?debug= 时 agent 完全不下载、不连接)';
28
+ }
29
+ const { startFarview } = await import('@farview/agent'); // 独立 chunk
30
+ startFarview(token, options);
31
+ return `已加载并连接:${token}`;
32
+ }
package/src/main.ts ADDED
@@ -0,0 +1,19 @@
1
+ // 入口:引导 agent + 把按钮点击派发到 actions。
2
+ import { actions } from './actions';
3
+ import { bootstrapFarview } from './farview';
4
+
5
+ function setState(text: string): void {
6
+ const el = document.getElementById('agentState');
7
+ if (el) el.textContent = text;
8
+ }
9
+
10
+ bootstrapFarview()
11
+ .then(setState)
12
+ .catch((err: unknown) => setState(`加载失败:${err instanceof Error ? err.message : err}`));
13
+
14
+ document.body.addEventListener('click', (e) => {
15
+ const target = e.target;
16
+ if (!(target instanceof HTMLElement)) return;
17
+ const act = target.dataset.act;
18
+ if (act && act in actions) actions[act]();
19
+ });
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "skipLibCheck": true,
10
+ "isolatedModules": true,
11
+ "verbatimModuleSyntax": true,
12
+ "types": ["vite/client"]
13
+ },
14
+ "include": ["src"]
15
+ }