@heybox/hb-sdk 0.8.0-alpha.3 → 0.8.0-alpha.9
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/CHANGELOG.md +85 -438
- package/README.md +6 -2
- package/dist/cli-chunks/{build-qWzAbpS7.cjs → build-DkokKVNy.cjs} +2 -2
- package/dist/cli-chunks/{context-CtS2Thp0.cjs → context-CKzZxKbF.cjs} +1 -1
- package/dist/cli-chunks/{create-PV5ua977.cjs → create-BQy5Jdmu.cjs} +2 -2
- package/dist/cli-chunks/{dev-CwKbAm_H.cjs → dev-Dik2zr5R.cjs} +58 -57
- package/dist/cli-chunks/{doctor-tJUGOYrm.cjs → doctor-Byr4uwKG.cjs} +1 -1
- package/dist/cli-chunks/{index-De687C6-.cjs → index-BwGBr1ZA.cjs} +32 -21
- package/dist/cli-chunks/{index-DVuD75Hr.cjs → index-Cl0XaX8e.cjs} +1 -1
- package/dist/cli-chunks/{index.esm-B-4yrLNm.cjs → index.esm-BYifBABc.cjs} +6 -6
- package/dist/cli-chunks/{login-DolpqD8K.cjs → login-Dr9lclu3.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-1rvkK-M8.cjs → project-vite-BIPrOtRO.cjs} +1 -1
- package/dist/cli-chunks/{remote-rIAQE_G2.cjs → remote-DXxyA14a.cjs} +4 -4
- package/dist/cli-chunks/{session-CzaM2Cq3.cjs → session-B6Mo9eYW.cjs} +1 -1
- package/dist/cli-chunks/{skill-CM40_9WH.cjs → skill-f90sxv28.cjs} +2 -2
- package/dist/cli-chunks/{version-Bz-AfXQU.cjs → version-DDB_btOG.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/browser-dev-host/assets/{browser-dev-host-uq-Wac6k.js → browser-dev-host-CbhA4h8z.js} +15 -15
- package/dist/devtools/browser-dev-host/assets/{index-KD2f3Jdz.css → index-DJFB5ySU.css} +1 -1
- package/dist/devtools/browser-dev-host/assets/{index-CeP6SLB3.js → index-DaqmTjSF.js} +4 -4
- package/dist/devtools/browser-dev-host/assets/workbench-state-wHgWRb7I.js +5 -0
- package/dist/devtools/browser-dev-host/index.html +3 -3
- package/dist/index.cjs.js +2 -2
- package/dist/index.esm.js +2 -2
- package/dist/templates/{vue3-vite-ts → vanilla-vite-js}/.gitignore.ejs +0 -1
- package/dist/templates/vanilla-vite-js/README.md.ejs +14 -0
- package/dist/templates/vanilla-vite-js/index.html.ejs +20 -0
- package/dist/templates/vanilla-vite-js/package.json.ejs +21 -0
- package/dist/templates/vanilla-vite-js/src/assets/heybox-logo.svg +8 -0
- package/dist/templates/vanilla-vite-js/src/main.js +39 -0
- package/dist/templates/vanilla-vite-js/src/styles.css +155 -0
- package/dist/templates/{vue3-vite-ts/vite.config.ts → vanilla-vite-js/vite.config.js} +1 -2
- package/dist/vite.cjs.js +1 -1
- package/dist/vite.esm.js +1 -1
- package/package.json +12 -8
- package/skill/SKILL.md +1 -1
- package/skill/references/api-protocol.md +1 -3
- package/skill/references/api-root.md +3 -1
- package/skill/references/cli.md +14 -2
- package/skill/references/recipes.md +5 -3
- package/skill/skill.json +5 -5
- package/types/modules/share/index.d.ts +1 -1
- package/types/modules/share/show-share-menu.d.ts +1 -1
- package/types/modules/share/types.d.ts +2 -4
- package/dist/devtools/browser-dev-host/assets/workbench-state-D-1U0JRq.js +0 -5
- package/dist/templates/vue3-vite-ts/README.md.ejs +0 -47
- package/dist/templates/vue3-vite-ts/index.html.ejs +0 -12
- package/dist/templates/vue3-vite-ts/package.json.ejs +0 -33
- package/dist/templates/vue3-vite-ts/src/App.vue +0 -78
- package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +0 -148
- package/dist/templates/vue3-vite-ts/src/auth-handoff.ts +0 -46
- package/dist/templates/vue3-vite-ts/src/main.ts +0 -5
- package/dist/templates/vue3-vite-ts/src/styles.css +0 -60
- package/dist/templates/vue3-vite-ts/src/vite-env.d.ts +0 -1
- package/dist/templates/vue3-vite-ts/tsconfig.app.json +0 -17
- package/dist/templates/vue3-vite-ts/tsconfig.json +0 -11
- package/dist/templates/vue3-vite-ts/tsconfig.node.json +0 -11
- package/dist/templates/vue3-vite-ts/vitest.config.ts +0 -10
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { flushPromises, mount } from '@vue/test-utils';
|
|
2
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import App from '../App.vue';
|
|
4
|
-
|
|
5
|
-
const sdkMock = vi.hoisted(() => ({
|
|
6
|
-
...(() => {
|
|
7
|
-
type HandshakeState = { status: 'connecting' } | { status: 'ready' } | { status: 'failed'; error: Error & { code: string } };
|
|
8
|
-
|
|
9
|
-
let state: HandshakeState = { status: 'connecting' };
|
|
10
|
-
const handlers = new Set<(nextState: HandshakeState) => void>();
|
|
11
|
-
const unsubscribe = vi.fn();
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
getHandshakeState: vi.fn(() => state),
|
|
15
|
-
onHandshakeStateChange: vi.fn((handler: (nextState: HandshakeState) => void) => {
|
|
16
|
-
handlers.add(handler);
|
|
17
|
-
handler(state);
|
|
18
|
-
return () => {
|
|
19
|
-
unsubscribe();
|
|
20
|
-
handlers.delete(handler);
|
|
21
|
-
};
|
|
22
|
-
}),
|
|
23
|
-
reset(nextState: HandshakeState = { status: 'connecting' }) {
|
|
24
|
-
state = nextState;
|
|
25
|
-
handlers.clear();
|
|
26
|
-
unsubscribe.mockReset();
|
|
27
|
-
},
|
|
28
|
-
setHandshakeState(nextState: HandshakeState) {
|
|
29
|
-
state = nextState;
|
|
30
|
-
handlers.forEach((handler) => handler(state));
|
|
31
|
-
},
|
|
32
|
-
unsubscribe,
|
|
33
|
-
};
|
|
34
|
-
})(),
|
|
35
|
-
login: vi.fn(),
|
|
36
|
-
networkRequest: vi.fn(),
|
|
37
|
-
}));
|
|
38
|
-
|
|
39
|
-
vi.mock('@heybox/hb-sdk', () => ({
|
|
40
|
-
default: {
|
|
41
|
-
auth: {
|
|
42
|
-
login: sdkMock.login,
|
|
43
|
-
},
|
|
44
|
-
network: {
|
|
45
|
-
request: sdkMock.networkRequest,
|
|
46
|
-
},
|
|
47
|
-
getHandshakeState: sdkMock.getHandshakeState,
|
|
48
|
-
onHandshakeStateChange: sdkMock.onHandshakeStateChange,
|
|
49
|
-
},
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
describe('App', () => {
|
|
53
|
-
beforeEach(() => {
|
|
54
|
-
vi.clearAllMocks();
|
|
55
|
-
vi.unstubAllEnvs();
|
|
56
|
-
|
|
57
|
-
sdkMock.reset();
|
|
58
|
-
sdkMock.login.mockResolvedValue({ code: 'authorization_code', expiresIn: 300, scopes: ['identity'] });
|
|
59
|
-
sdkMock.networkRequest.mockResolvedValue({ status: 200 });
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('keeps actions disabled while the SDK is connecting', () => {
|
|
63
|
-
const wrapper = mount(App);
|
|
64
|
-
|
|
65
|
-
expect(sdkMock.getHandshakeState).not.toHaveBeenCalled();
|
|
66
|
-
expect(wrapper.get('[data-testid="status"]').text()).toBe('正在连接 SDK...');
|
|
67
|
-
expect(wrapper.get<HTMLButtonElement>('[data-testid="login"]').element.disabled).toBe(true);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('enables actions when the handshake becomes ready', async () => {
|
|
71
|
-
const wrapper = mount(App);
|
|
72
|
-
|
|
73
|
-
sdkMock.setHandshakeState({ status: 'ready' });
|
|
74
|
-
await flushPromises();
|
|
75
|
-
|
|
76
|
-
expect(wrapper.get('[data-testid="status"]').text()).toBe('SDK 已连接');
|
|
77
|
-
expect(wrapper.get('[data-testid="output"]').text()).toContain('请选择操作');
|
|
78
|
-
expect(wrapper.get<HTMLButtonElement>('[data-testid="login"]').element.disabled).toBe(false);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
describe('late mount', () => {
|
|
82
|
-
it('renders an already-ready handshake immediately', () => {
|
|
83
|
-
sdkMock.reset({ status: 'ready' });
|
|
84
|
-
|
|
85
|
-
const wrapper = mount(App);
|
|
86
|
-
|
|
87
|
-
expect(wrapper.get('[data-testid="status"]').text()).toBe('SDK 已连接');
|
|
88
|
-
expect(wrapper.get<HTMLButtonElement>('[data-testid="login"]').element.disabled).toBe(false);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('renders the original failed handshake details immediately', () => {
|
|
92
|
-
const error = Object.assign(new Error('Host 未响应'), {
|
|
93
|
-
code: 'HANDSHAKE_TIMEOUT',
|
|
94
|
-
name: 'HbMiniProgramSDKError',
|
|
95
|
-
});
|
|
96
|
-
sdkMock.reset({ status: 'failed', error });
|
|
97
|
-
|
|
98
|
-
const wrapper = mount(App);
|
|
99
|
-
|
|
100
|
-
expect(wrapper.get('[data-testid="status"]').text()).toBe('SDK 连接失败');
|
|
101
|
-
expect(wrapper.get<HTMLButtonElement>('[data-testid="login"]').element.disabled).toBe(true);
|
|
102
|
-
expect(wrapper.get('[data-testid="output"]').text()).toContain('HbMiniProgramSDKError');
|
|
103
|
-
expect(wrapper.get('[data-testid="output"]').text()).toContain('Host 未响应');
|
|
104
|
-
expect(wrapper.get('[data-testid="output"]').text()).toContain('HANDSHAKE_TIMEOUT');
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('stops observing handshake state after unmount', () => {
|
|
109
|
-
const wrapper = mount(App);
|
|
110
|
-
|
|
111
|
-
wrapper.unmount();
|
|
112
|
-
|
|
113
|
-
expect(sdkMock.unsubscribe).toHaveBeenCalledTimes(1);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('hands the authorization code to the developer server without rendering it', async () => {
|
|
117
|
-
vi.stubEnv('VITE_HEYBOX_AUTH_EXCHANGE_URL', 'https://developer.example.com/api/heybox/exchange');
|
|
118
|
-
sdkMock.reset({ status: 'ready' });
|
|
119
|
-
const wrapper = mount(App);
|
|
120
|
-
|
|
121
|
-
await wrapper.get('[data-testid="login"]').trigger('click');
|
|
122
|
-
await flushPromises();
|
|
123
|
-
|
|
124
|
-
expect(sdkMock.login).toHaveBeenCalledTimes(1);
|
|
125
|
-
expect(sdkMock.networkRequest).toHaveBeenCalledWith({
|
|
126
|
-
method: 'POST',
|
|
127
|
-
url: 'https://developer.example.com/api/heybox/exchange',
|
|
128
|
-
data: { code: 'authorization_code' },
|
|
129
|
-
});
|
|
130
|
-
expect(wrapper.get('[data-testid="status"]').text()).toBe('auth.login 调用成功');
|
|
131
|
-
expect(wrapper.get('[data-testid="output"]').text()).toContain('300');
|
|
132
|
-
expect(wrapper.get('[data-testid="output"]').text()).toContain('identity');
|
|
133
|
-
expect(wrapper.text()).not.toContain('authorization_code');
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('does not request a code when the developer server is not configured', async () => {
|
|
137
|
-
sdkMock.reset({ status: 'ready' });
|
|
138
|
-
const wrapper = mount(App);
|
|
139
|
-
|
|
140
|
-
await wrapper.get('[data-testid="login"]').trigger('click');
|
|
141
|
-
await flushPromises();
|
|
142
|
-
|
|
143
|
-
expect(sdkMock.login).not.toHaveBeenCalled();
|
|
144
|
-
expect(sdkMock.networkRequest).not.toHaveBeenCalled();
|
|
145
|
-
expect(wrapper.get('[data-testid="status"]').text()).toBe('auth.login 调用失败');
|
|
146
|
-
expect(wrapper.get('[data-testid="output"]').text()).toContain('VITE_HEYBOX_AUTH_EXCHANGE_URL');
|
|
147
|
-
});
|
|
148
|
-
});
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export interface AuthorizationCodeLoginResult {
|
|
2
|
-
code: string;
|
|
3
|
-
expiresIn: number;
|
|
4
|
-
scopes: string[];
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface LoginAndExchangeAuthorizationCodeOptions {
|
|
8
|
-
exchangeUrl?: string;
|
|
9
|
-
login: () => Promise<AuthorizationCodeLoginResult>;
|
|
10
|
-
request: (config: {
|
|
11
|
-
method: 'POST';
|
|
12
|
-
url: string;
|
|
13
|
-
data: { code: string };
|
|
14
|
-
}) => Promise<unknown>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function loginAndExchangeAuthorizationCode(options: LoginAndExchangeAuthorizationCodeOptions) {
|
|
18
|
-
const exchangeUrl = options.exchangeUrl?.trim();
|
|
19
|
-
if (!exchangeUrl) {
|
|
20
|
-
throw new Error('请先配置 VITE_HEYBOX_AUTH_EXCHANGE_URL');
|
|
21
|
-
}
|
|
22
|
-
if (!isAllowedExchangeUrl(exchangeUrl)) {
|
|
23
|
-
throw new Error('VITE_HEYBOX_AUTH_EXCHANGE_URL 必须使用 HTTPS,本地调试仅允许 localhost');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const { code, expiresIn, scopes } = await options.login();
|
|
27
|
-
await options.request({
|
|
28
|
-
method: 'POST',
|
|
29
|
-
url: exchangeUrl,
|
|
30
|
-
data: { code },
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
return { expiresIn, scopes };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function isAllowedExchangeUrl(value: string) {
|
|
37
|
-
try {
|
|
38
|
-
const url = new URL(value);
|
|
39
|
-
if (url.protocol === 'https:') {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
return url.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);
|
|
43
|
-
} catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
color: #1f2933;
|
|
3
|
-
background: #f4f6f8;
|
|
4
|
-
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
5
|
-
line-height: 1.5;
|
|
6
|
-
}
|
|
7
|
-
* {
|
|
8
|
-
box-sizing: border-box;
|
|
9
|
-
}
|
|
10
|
-
body {
|
|
11
|
-
margin: 0; min-width: 320px;
|
|
12
|
-
}
|
|
13
|
-
.page {
|
|
14
|
-
width: min(100%, 720px);
|
|
15
|
-
margin: 0 auto;
|
|
16
|
-
padding: 40px 20px;
|
|
17
|
-
}
|
|
18
|
-
.card {
|
|
19
|
-
border: 1px solid #d8dee6;
|
|
20
|
-
border-radius: 8px;
|
|
21
|
-
background: #fff;
|
|
22
|
-
padding: 24px;
|
|
23
|
-
}
|
|
24
|
-
.eyebrow {
|
|
25
|
-
margin: 0 0 8px;
|
|
26
|
-
color: #287a4b;
|
|
27
|
-
font-size: 13px;
|
|
28
|
-
font-weight: 800;
|
|
29
|
-
}
|
|
30
|
-
h1 {
|
|
31
|
-
margin: 0; font-size: 36px; line-height: 1.1;
|
|
32
|
-
}
|
|
33
|
-
.intro,
|
|
34
|
-
.status {
|
|
35
|
-
color: #52616f;
|
|
36
|
-
}
|
|
37
|
-
button {
|
|
38
|
-
width: 100%;
|
|
39
|
-
min-height: 42px;
|
|
40
|
-
border: 0;
|
|
41
|
-
border-radius: 6px;
|
|
42
|
-
background: #1f2933;
|
|
43
|
-
color: #fff;
|
|
44
|
-
cursor: pointer;
|
|
45
|
-
font: inherit;
|
|
46
|
-
font-weight: 700;
|
|
47
|
-
}
|
|
48
|
-
button:disabled {
|
|
49
|
-
cursor: not-allowed; opacity: 0.6;
|
|
50
|
-
}
|
|
51
|
-
pre {
|
|
52
|
-
margin: 16px 0 0;
|
|
53
|
-
overflow: auto;
|
|
54
|
-
border-radius: 6px;
|
|
55
|
-
background: #101820;
|
|
56
|
-
color: #f7fbff;
|
|
57
|
-
padding: 14px;
|
|
58
|
-
white-space: pre-wrap;
|
|
59
|
-
word-break: break-word;
|
|
60
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="vite/client" />
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"moduleResolution": "Bundler",
|
|
7
|
-
"strict": true,
|
|
8
|
-
"jsx": "preserve",
|
|
9
|
-
"sourceMap": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
"isolatedModules": true,
|
|
12
|
-
"noEmit": true,
|
|
13
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
14
|
-
"types": ["vite/client"]
|
|
15
|
-
},
|
|
16
|
-
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
|
17
|
-
}
|