@heybox/hb-sdk 0.2.0-alpha.1 → 0.2.0-alpha.2
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 +68 -1
- package/dist/cli.cjs +71174 -3895
- package/dist/miniapp-publish.cjs.js +77 -0
- package/dist/miniapp-publish.esm.js +66 -0
- package/dist/templates/vue3-vite-ts/vite.config.ts +2 -1
- package/dist/vite.cjs.js +62 -0
- package/dist/vite.esm.js +60 -0
- package/package.json +28 -1
- package/skill/SKILL.md +28 -17
- package/skill/references/api-root.md +129 -1
- package/skill/references/cli.md +17 -1
- package/skill/references/examples.md +12 -0
- package/skill/references/safety-boundaries.md +2 -0
- package/skill/scripts/sync-references.mjs +24 -0
- package/skill/scripts/validate-skill.mjs +4 -2
- package/skill/skill.json +4 -4
- package/types/miniapp-publish/index.d.ts +23 -0
- package/types/vite/index.d.ts +17 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MINIAPP_UPLOAD_SCOPE = 'activity';
|
|
4
|
+
const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
|
|
5
|
+
const PUBLISH_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/publish';
|
|
6
|
+
const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
7
|
+
const FNV_OFFSET = 0x811c9dc5;
|
|
8
|
+
const FNV_PRIME = 0x01000193;
|
|
9
|
+
function isValidVersion(version) {
|
|
10
|
+
return VERSION_PATTERN.test(String(version || '').trim());
|
|
11
|
+
}
|
|
12
|
+
function normalizeRelativePath(relativePath) {
|
|
13
|
+
return String(relativePath || '')
|
|
14
|
+
.replace(/\\/g, '/')
|
|
15
|
+
.replace(/^\/+/, '')
|
|
16
|
+
.replace(/\/+/g, '/');
|
|
17
|
+
}
|
|
18
|
+
function relativePathContainsNodeModulesSegment(relativePath) {
|
|
19
|
+
return normalizeRelativePath(relativePath)
|
|
20
|
+
.split('/')
|
|
21
|
+
.some((segment) => segment.length > 0 && segment.toLowerCase() === 'node_modules');
|
|
22
|
+
}
|
|
23
|
+
function getMiniProgramUploadAlias(miniProgramId) {
|
|
24
|
+
let hash = FNV_OFFSET;
|
|
25
|
+
const input = String(miniProgramId || '');
|
|
26
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
27
|
+
hash ^= input.charCodeAt(i);
|
|
28
|
+
hash = Math.imul(hash, FNV_PRIME) >>> 0;
|
|
29
|
+
}
|
|
30
|
+
return hash.toString(36);
|
|
31
|
+
}
|
|
32
|
+
function getMiniappUploadKey(input) {
|
|
33
|
+
const alias = getMiniProgramUploadAlias(input.miniProgramId);
|
|
34
|
+
const normalized = normalizeRelativePath(input.relativePath);
|
|
35
|
+
return `/u/${alias}/${input.version}/${normalized}`;
|
|
36
|
+
}
|
|
37
|
+
function validateUploadPaths(items, options) {
|
|
38
|
+
const limit = options.maxLength ?? ACTIVITY_UPLOAD_KEY_MAX_LENGTH;
|
|
39
|
+
for (const item of items) {
|
|
40
|
+
const key = getMiniappUploadKey({
|
|
41
|
+
miniProgramId: options.miniProgramId,
|
|
42
|
+
version: options.version,
|
|
43
|
+
relativePath: item.relativePath,
|
|
44
|
+
});
|
|
45
|
+
if (key.length > limit) {
|
|
46
|
+
return `文件路径过长,请缩短构建产物文件名或目录层级:${item.relativePath}`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
function shouldUploadDistFile(relativePath) {
|
|
52
|
+
const normalized = normalizeRelativePath(relativePath);
|
|
53
|
+
if (!normalized) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (normalized === 'manifest.json') {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (normalized === '.DS_Store' || normalized.endsWith('/.DS_Store')) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (normalized.toLowerCase().endsWith('.map')) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
exports.ACTIVITY_UPLOAD_KEY_MAX_LENGTH = ACTIVITY_UPLOAD_KEY_MAX_LENGTH;
|
|
69
|
+
exports.MINIAPP_UPLOAD_SCOPE = MINIAPP_UPLOAD_SCOPE;
|
|
70
|
+
exports.PUBLISH_USER_MINIPROGRAM_API_PATH = PUBLISH_USER_MINIPROGRAM_API_PATH;
|
|
71
|
+
exports.getMiniProgramUploadAlias = getMiniProgramUploadAlias;
|
|
72
|
+
exports.getMiniappUploadKey = getMiniappUploadKey;
|
|
73
|
+
exports.isValidVersion = isValidVersion;
|
|
74
|
+
exports.normalizeRelativePath = normalizeRelativePath;
|
|
75
|
+
exports.relativePathContainsNodeModulesSegment = relativePathContainsNodeModulesSegment;
|
|
76
|
+
exports.shouldUploadDistFile = shouldUploadDistFile;
|
|
77
|
+
exports.validateUploadPaths = validateUploadPaths;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const MINIAPP_UPLOAD_SCOPE = 'activity';
|
|
2
|
+
const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
|
|
3
|
+
const PUBLISH_USER_MINIPROGRAM_API_PATH = '/mall/developer/user_miniprogram/publish';
|
|
4
|
+
const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
5
|
+
const FNV_OFFSET = 0x811c9dc5;
|
|
6
|
+
const FNV_PRIME = 0x01000193;
|
|
7
|
+
function isValidVersion(version) {
|
|
8
|
+
return VERSION_PATTERN.test(String(version || '').trim());
|
|
9
|
+
}
|
|
10
|
+
function normalizeRelativePath(relativePath) {
|
|
11
|
+
return String(relativePath || '')
|
|
12
|
+
.replace(/\\/g, '/')
|
|
13
|
+
.replace(/^\/+/, '')
|
|
14
|
+
.replace(/\/+/g, '/');
|
|
15
|
+
}
|
|
16
|
+
function relativePathContainsNodeModulesSegment(relativePath) {
|
|
17
|
+
return normalizeRelativePath(relativePath)
|
|
18
|
+
.split('/')
|
|
19
|
+
.some((segment) => segment.length > 0 && segment.toLowerCase() === 'node_modules');
|
|
20
|
+
}
|
|
21
|
+
function getMiniProgramUploadAlias(miniProgramId) {
|
|
22
|
+
let hash = FNV_OFFSET;
|
|
23
|
+
const input = String(miniProgramId || '');
|
|
24
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
25
|
+
hash ^= input.charCodeAt(i);
|
|
26
|
+
hash = Math.imul(hash, FNV_PRIME) >>> 0;
|
|
27
|
+
}
|
|
28
|
+
return hash.toString(36);
|
|
29
|
+
}
|
|
30
|
+
function getMiniappUploadKey(input) {
|
|
31
|
+
const alias = getMiniProgramUploadAlias(input.miniProgramId);
|
|
32
|
+
const normalized = normalizeRelativePath(input.relativePath);
|
|
33
|
+
return `/u/${alias}/${input.version}/${normalized}`;
|
|
34
|
+
}
|
|
35
|
+
function validateUploadPaths(items, options) {
|
|
36
|
+
const limit = options.maxLength ?? ACTIVITY_UPLOAD_KEY_MAX_LENGTH;
|
|
37
|
+
for (const item of items) {
|
|
38
|
+
const key = getMiniappUploadKey({
|
|
39
|
+
miniProgramId: options.miniProgramId,
|
|
40
|
+
version: options.version,
|
|
41
|
+
relativePath: item.relativePath,
|
|
42
|
+
});
|
|
43
|
+
if (key.length > limit) {
|
|
44
|
+
return `文件路径过长,请缩短构建产物文件名或目录层级:${item.relativePath}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
function shouldUploadDistFile(relativePath) {
|
|
50
|
+
const normalized = normalizeRelativePath(relativePath);
|
|
51
|
+
if (!normalized) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (normalized === 'manifest.json') {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (normalized === '.DS_Store' || normalized.endsWith('/.DS_Store')) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (normalized.toLowerCase().endsWith('.map')) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { ACTIVITY_UPLOAD_KEY_MAX_LENGTH, MINIAPP_UPLOAD_SCOPE, PUBLISH_USER_MINIPROGRAM_API_PATH, getMiniProgramUploadAlias, getMiniappUploadKey, isValidVersion, normalizeRelativePath, relativePathContainsNodeModulesSegment, shouldUploadDistFile, validateUploadPaths };
|
package/dist/vite.cjs.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_fs = require('node:fs');
|
|
4
|
+
var path = require('node:path');
|
|
5
|
+
|
|
6
|
+
const TEMPLATE_VERSION = '0.0.0';
|
|
7
|
+
const SEMVER_LIKE_RE = /^\d+\.\d+\.\d+(?:[-+].*)?$/;
|
|
8
|
+
const TEMPLATE_VERSION_ERROR = '@heybox/hb-sdk 提示:请把 package.json.version 从模板默认的 0.0.0 改成实际版本号再发布';
|
|
9
|
+
function miniappManifest() {
|
|
10
|
+
let root = process.cwd();
|
|
11
|
+
let outDir = 'dist';
|
|
12
|
+
return {
|
|
13
|
+
name: 'heybox-miniapp-manifest',
|
|
14
|
+
apply: 'build',
|
|
15
|
+
configResolved(resolved) {
|
|
16
|
+
root = resolved.root;
|
|
17
|
+
outDir = resolved.build.outDir;
|
|
18
|
+
},
|
|
19
|
+
writeBundle() {
|
|
20
|
+
const version = readMiniappVersion(root);
|
|
21
|
+
if (!SEMVER_LIKE_RE.test(version)) {
|
|
22
|
+
this.warn(`package.json.version "${version}" 不是标准 semver,仍会写入 manifest.json`);
|
|
23
|
+
}
|
|
24
|
+
const manifestPath = path.resolve(root, outDir, 'manifest.json');
|
|
25
|
+
node_fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
26
|
+
node_fs.writeFileSync(manifestPath, `${JSON.stringify({ version }, null, 2)}\n`);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function readMiniappVersion(root) {
|
|
31
|
+
const packageJsonPath = path.join(root, 'package.json');
|
|
32
|
+
let content;
|
|
33
|
+
try {
|
|
34
|
+
content = node_fs.readFileSync(packageJsonPath, 'utf8');
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw new Error(`@heybox/hb-sdk 读取 package.json 失败:${formatReason(error)}`);
|
|
38
|
+
}
|
|
39
|
+
let packageJson;
|
|
40
|
+
try {
|
|
41
|
+
packageJson = JSON.parse(content);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new Error(`@heybox/hb-sdk 解析 package.json 失败:${formatReason(error)}`);
|
|
45
|
+
}
|
|
46
|
+
if (typeof packageJson.version !== 'string' || packageJson.version.trim() === '') {
|
|
47
|
+
throw new Error('@heybox/hb-sdk 提示:package.json.version 必须是非空字符串');
|
|
48
|
+
}
|
|
49
|
+
const version = packageJson.version.trim();
|
|
50
|
+
if (version === TEMPLATE_VERSION) {
|
|
51
|
+
throw new Error(TEMPLATE_VERSION_ERROR);
|
|
52
|
+
}
|
|
53
|
+
return version;
|
|
54
|
+
}
|
|
55
|
+
function formatReason(error) {
|
|
56
|
+
if (error instanceof Error && error.message) {
|
|
57
|
+
return error.message;
|
|
58
|
+
}
|
|
59
|
+
return String(error);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
exports.miniappManifest = miniappManifest;
|
package/dist/vite.esm.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
const TEMPLATE_VERSION = '0.0.0';
|
|
5
|
+
const SEMVER_LIKE_RE = /^\d+\.\d+\.\d+(?:[-+].*)?$/;
|
|
6
|
+
const TEMPLATE_VERSION_ERROR = '@heybox/hb-sdk 提示:请把 package.json.version 从模板默认的 0.0.0 改成实际版本号再发布';
|
|
7
|
+
function miniappManifest() {
|
|
8
|
+
let root = process.cwd();
|
|
9
|
+
let outDir = 'dist';
|
|
10
|
+
return {
|
|
11
|
+
name: 'heybox-miniapp-manifest',
|
|
12
|
+
apply: 'build',
|
|
13
|
+
configResolved(resolved) {
|
|
14
|
+
root = resolved.root;
|
|
15
|
+
outDir = resolved.build.outDir;
|
|
16
|
+
},
|
|
17
|
+
writeBundle() {
|
|
18
|
+
const version = readMiniappVersion(root);
|
|
19
|
+
if (!SEMVER_LIKE_RE.test(version)) {
|
|
20
|
+
this.warn(`package.json.version "${version}" 不是标准 semver,仍会写入 manifest.json`);
|
|
21
|
+
}
|
|
22
|
+
const manifestPath = path.resolve(root, outDir, 'manifest.json');
|
|
23
|
+
mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
24
|
+
writeFileSync(manifestPath, `${JSON.stringify({ version }, null, 2)}\n`);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function readMiniappVersion(root) {
|
|
29
|
+
const packageJsonPath = path.join(root, 'package.json');
|
|
30
|
+
let content;
|
|
31
|
+
try {
|
|
32
|
+
content = readFileSync(packageJsonPath, 'utf8');
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
throw new Error(`@heybox/hb-sdk 读取 package.json 失败:${formatReason(error)}`);
|
|
36
|
+
}
|
|
37
|
+
let packageJson;
|
|
38
|
+
try {
|
|
39
|
+
packageJson = JSON.parse(content);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new Error(`@heybox/hb-sdk 解析 package.json 失败:${formatReason(error)}`);
|
|
43
|
+
}
|
|
44
|
+
if (typeof packageJson.version !== 'string' || packageJson.version.trim() === '') {
|
|
45
|
+
throw new Error('@heybox/hb-sdk 提示:package.json.version 必须是非空字符串');
|
|
46
|
+
}
|
|
47
|
+
const version = packageJson.version.trim();
|
|
48
|
+
if (version === TEMPLATE_VERSION) {
|
|
49
|
+
throw new Error(TEMPLATE_VERSION_ERROR);
|
|
50
|
+
}
|
|
51
|
+
return version;
|
|
52
|
+
}
|
|
53
|
+
function formatReason(error) {
|
|
54
|
+
if (error instanceof Error && error.message) {
|
|
55
|
+
return error.message;
|
|
56
|
+
}
|
|
57
|
+
return String(error);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { miniappManifest };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heybox/hb-sdk",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -16,6 +16,19 @@
|
|
|
16
16
|
"node": "./dist/protocol.cjs.js",
|
|
17
17
|
"browser": "./dist/protocol.esm.js",
|
|
18
18
|
"default": "./dist/protocol.esm.js"
|
|
19
|
+
},
|
|
20
|
+
"./miniapp-publish": {
|
|
21
|
+
"types": "./types/miniapp-publish/index.d.ts",
|
|
22
|
+
"heybox": "./src/miniapp-publish/index.ts",
|
|
23
|
+
"node": "./dist/miniapp-publish.cjs.js",
|
|
24
|
+
"browser": "./dist/miniapp-publish.esm.js",
|
|
25
|
+
"default": "./dist/miniapp-publish.esm.js"
|
|
26
|
+
},
|
|
27
|
+
"./vite": {
|
|
28
|
+
"types": "./types/vite/index.d.ts",
|
|
29
|
+
"import": "./dist/vite.esm.js",
|
|
30
|
+
"require": "./dist/vite.cjs.js",
|
|
31
|
+
"default": "./dist/vite.esm.js"
|
|
19
32
|
}
|
|
20
33
|
},
|
|
21
34
|
"bin": {
|
|
@@ -30,6 +43,17 @@
|
|
|
30
43
|
"keywords": [],
|
|
31
44
|
"author": "",
|
|
32
45
|
"license": "ISC",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"cos-nodejs-sdk-v5": "2.15.4"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"vite": ">=5"
|
|
51
|
+
},
|
|
52
|
+
"peerDependenciesMeta": {
|
|
53
|
+
"vite": {
|
|
54
|
+
"optional": true
|
|
55
|
+
}
|
|
56
|
+
},
|
|
33
57
|
"devDependencies": {
|
|
34
58
|
"@rollup/plugin-commonjs": "^28.0.6",
|
|
35
59
|
"@rollup/plugin-json": "^6.1.0",
|
|
@@ -53,6 +77,7 @@
|
|
|
53
77
|
"rollup": "^4.52.4",
|
|
54
78
|
"typescript": "^5.9.3",
|
|
55
79
|
"vue": "2.7.16",
|
|
80
|
+
"vite": "^8.0.12",
|
|
56
81
|
"vitest": "^3.2.4"
|
|
57
82
|
},
|
|
58
83
|
"publishConfig": {
|
|
@@ -86,9 +111,11 @@
|
|
|
86
111
|
"build:templates": "node scripts/copy-cli-templates.cjs",
|
|
87
112
|
"build:types": "tsc -p tsconfig.dts.json",
|
|
88
113
|
"check:boundary": "node scripts/check-boundary.cjs",
|
|
114
|
+
"check:docs-sync": "node scripts/check-docs-sync.cjs",
|
|
89
115
|
"clean": "rimraf ./dist && rimraf ./types",
|
|
90
116
|
"test:unit": "NODE_OPTIONS='--conditions=heybox' vitest run",
|
|
91
117
|
"test:unit:coverage": "NODE_OPTIONS='--conditions=heybox' vitest run --coverage",
|
|
118
|
+
"test:vite": "vitest run --config vitest.vite.config.ts",
|
|
92
119
|
"test:watch": "NODE_OPTIONS='--conditions=heybox' vitest"
|
|
93
120
|
}
|
|
94
121
|
}
|
package/skill/SKILL.md
CHANGED
|
@@ -22,9 +22,10 @@ Apply these instructions when writing, reviewing, or debugging code that consume
|
|
|
22
22
|
3. For common business flows, read `references/recipes.md`.
|
|
23
23
|
4. For CLI commands, local mock runtime, generated templates, CLI login cache, Agent Skill doctor, and update reminders, read `references/cli.md`.
|
|
24
24
|
5. For allowed/forbidden capabilities and security boundaries, read `references/safety-boundaries.md`.
|
|
25
|
-
6. For
|
|
26
|
-
7. For
|
|
27
|
-
8. For
|
|
25
|
+
6. For Vite build manifest behavior, read `references/api-root.md` and `references/safety-boundaries.md`.
|
|
26
|
+
7. For generated documentation provenance and deeper API lookup paths, read `references/llms-index.md`.
|
|
27
|
+
8. For smoke-test expectations, positive examples, and anti-examples, read `references/examples.md`.
|
|
28
|
+
9. For evaluating whether another agent followed this skill, read `references/smoke-evaluation.md`.
|
|
28
29
|
|
|
29
30
|
## Step 3: Follow import rules
|
|
30
31
|
|
|
@@ -47,14 +48,18 @@ Apply these instructions when writing, reviewing, or debugging code that consume
|
|
|
47
48
|
|
|
48
49
|
1. Use `hb-sdk create <project-name>` to scaffold a standalone external mini-program template.
|
|
49
50
|
2. Use `hb-sdk dev` for local browser debugging through the built-in mock runtime host.
|
|
50
|
-
3. Use the
|
|
51
|
-
4. Use
|
|
52
|
-
5. Use
|
|
53
|
-
6. Use
|
|
54
|
-
7.
|
|
55
|
-
8.
|
|
56
|
-
9. Do not
|
|
57
|
-
10.
|
|
51
|
+
3. Use `hb-sdk deploy` to build and publish the current project. It reads `package.json.heybox.miniProgramId`, runs the project's `build` script via the package manager auto-detected by lockfile, then uploads `dist/` to CDN (skipping `manifest.json`, `.DS_Store`, `.map`) and calls the publish API.
|
|
52
|
+
4. Use `hb-sdk deploy --skip-build` only when the `dist/` directory is already prepared by an upstream CI stage. Missing `dist/manifest.json` or `dist/index.html` aborts the run.
|
|
53
|
+
5. Use the Mock runtime host's "在 Mac 版 APP 中启动" button when the page needs to be loaded by the real Heybox mini-program container.
|
|
54
|
+
6. Use `--port`, `--mock-port`, `--host`, and `--no-open` when the default Vite/mock ports, host, or browser opening behavior need to be controlled.
|
|
55
|
+
7. Use `hb-sdk login`, `hb-sdk login status`, and `hb-sdk login clear` only for the CLI's own Heybox auth cache.
|
|
56
|
+
8. Use `hb-sdk doctor` to diagnose whether the local `hb-sdk` skill matches the installed SDK and remote latest skill metadata.
|
|
57
|
+
9. Do not use `hb-sdk doctor` to auto-install skills; when installation or refresh is needed, tell the user to run `npx skills add https://open.xiaoheihe.cn/agent-skills/hb-sdk`.
|
|
58
|
+
10. If doctor reports `SDK_MISMATCH`, upgrade `@heybox/hb-sdk@latest` before reinstalling the skill.
|
|
59
|
+
11. Do not treat CLI login cache as iframe SDK login state; it does not change `auth.login()`, `user.getInfo()`, `network.request()`, or mock-user behavior.
|
|
60
|
+
12. Keep the CLI and mock runtime under `@heybox/hb-sdk`; do not create or revive a separate mock runtime package.
|
|
61
|
+
13. Do not pass `mini_program_id` as a CLI flag or environment variable; it must come from `package.json.heybox.miniProgramId`.
|
|
62
|
+
14. Do not import deploy / upload internals from outside the CLI; the only externally consumable subpath for publishing is `@heybox/hb-sdk/miniapp-publish`.
|
|
58
63
|
|
|
59
64
|
## Step 6: Preserve capability boundaries
|
|
60
65
|
|
|
@@ -65,6 +70,7 @@ For iframe mini-program business code:
|
|
|
65
70
|
3. Do not use unsupported storage operations such as delete, clear, info listing, or global client storage access.
|
|
66
71
|
4. Do not pass raw host protocol fields through `network.request`; use only the public axios-like request config.
|
|
67
72
|
5. Do not construct bridge envelopes, nonce logic, or raw `postMessage` calls.
|
|
73
|
+
6. Build artifacts may include `dist/manifest.json`; business code should not fetch a deployed manifest directly because it is not a CDN asset.
|
|
68
74
|
|
|
69
75
|
For CLI and local development:
|
|
70
76
|
|
|
@@ -81,15 +87,20 @@ For host/runtime/protocol-maintenance code:
|
|
|
81
87
|
## Step 7: Validate changes
|
|
82
88
|
|
|
83
89
|
1. Run the nearest package tests and builds with repo-native commands when editing this repository.
|
|
84
|
-
2. When modifying
|
|
85
|
-
- `
|
|
86
|
-
- `
|
|
90
|
+
2. When modifying docs, skill instructions, CLI guidance, or public agent-skill sync points, start with:
|
|
91
|
+
- `pnpm --filter @heybox/hb-sdk run check:docs-sync`
|
|
92
|
+
- `cat packages/hb-sdk/DOC_SYNC_CHECKLIST.md`
|
|
93
|
+
3. When modifying this repo's source skill at `packages/hb-sdk/skill` and preparing distributable artifacts, also run:
|
|
87
94
|
- `node packages/hb-sdk/skill/scripts/package-skill.mjs`
|
|
88
|
-
|
|
95
|
+
4. When modifying CLI, mock runtime, package exports, or package dependency direction, also run:
|
|
89
96
|
- `pnpm --filter @heybox/hb-sdk run check:boundary`
|
|
90
97
|
- `pnpm --filter @heybox/hb-sdk run test:unit`
|
|
91
|
-
|
|
98
|
+
5. Inspect the generated zip before distribution:
|
|
92
99
|
- `unzip -l packages/hb-sdk/hb-sdk.zip | sed -n '1,120p'`
|
|
93
|
-
|
|
100
|
+
6. When adding or modifying the deploy command or its upload pipeline, also run:
|
|
101
|
+
- `pnpm --filter @heybox/hb-sdk run check:boundary`
|
|
102
|
+
- `pnpm --filter @heybox/hb-sdk run test:unit`
|
|
103
|
+
- Verify `dist/cli.cjs` does not have any `require('cos-nodejs-sdk-v5')` left after `build:cli`; the boundary check enforces this automatically.
|
|
104
|
+
6. Verify public payload sync before publishing:
|
|
94
105
|
- `pnpm --filter @heybox-spa/open run sync:agent-skills`
|
|
95
106
|
- `pnpm --filter @heybox-spa/open run check:agent-skills`
|
|
@@ -6,20 +6,23 @@
|
|
|
6
6
|
|
|
7
7
|
- packages/hb-sdk/package.json
|
|
8
8
|
- packages/hb-sdk/src/index.ts
|
|
9
|
+
- packages/hb-sdk/src/vite/index.ts
|
|
9
10
|
- packages/hb-sdk/README.md
|
|
10
11
|
|
|
11
12
|
## Contents
|
|
12
13
|
|
|
13
14
|
- [Package metadata](#package-metadata)
|
|
14
15
|
- [Public root entrypoint](#public-root-entrypoint)
|
|
16
|
+
- [Vite plugin export](#vite-plugin-export)
|
|
15
17
|
- [App-facing concepts](#app-facing-concepts)
|
|
16
18
|
- [Public modules](#public-modules)
|
|
17
19
|
## Package metadata
|
|
18
20
|
|
|
19
21
|
- Package: `@heybox/hb-sdk`
|
|
20
|
-
- Version at generation time: `0.2.0-alpha.
|
|
22
|
+
- Version at generation time: `0.2.0-alpha.2`
|
|
21
23
|
- Public root export: `@heybox/hb-sdk`
|
|
22
24
|
- Protocol export: `@heybox/hb-sdk/protocol`
|
|
25
|
+
- Vite plugin export: `@heybox/hb-sdk/vite`
|
|
23
26
|
|
|
24
27
|
## Public root entrypoint
|
|
25
28
|
|
|
@@ -130,6 +133,131 @@ const hbSDK = {
|
|
|
130
133
|
export default hbSDK;
|
|
131
134
|
```
|
|
132
135
|
|
|
136
|
+
## Vite plugin export
|
|
137
|
+
|
|
138
|
+
Use `@heybox/hb-sdk/vite` only in `vite.config.ts`. Do not import it from iframe mini-program business code.
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
142
|
+
import path from 'node:path';
|
|
143
|
+
|
|
144
|
+
const TEMPLATE_VERSION = '0.0.0';
|
|
145
|
+
const SEMVER_LIKE_RE = /^\d+\.\d+\.\d+(?:[-+].*)?$/;
|
|
146
|
+
const TEMPLATE_VERSION_ERROR = '@heybox/hb-sdk 提示:请把 package.json.version 从模板默认的 0.0.0 改成实际版本号再发布';
|
|
147
|
+
|
|
148
|
+
type MiniappManifestPlugin = {
|
|
149
|
+
name: string;
|
|
150
|
+
apply: 'build';
|
|
151
|
+
configResolved: (resolved: MiniappManifestResolvedConfig) => void;
|
|
152
|
+
writeBundle: (this: MiniappManifestPluginContext) => void;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
interface MiniappManifestPluginContext {
|
|
156
|
+
warn: (message: string) => void;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface MiniappManifestResolvedConfig {
|
|
160
|
+
root: string;
|
|
161
|
+
build: {
|
|
162
|
+
outDir: string;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function miniappManifest(): MiniappManifestPlugin {
|
|
167
|
+
let root = process.cwd();
|
|
168
|
+
let outDir = 'dist';
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
name: 'heybox-miniapp-manifest',
|
|
172
|
+
apply: 'build',
|
|
173
|
+
configResolved(resolved) {
|
|
174
|
+
root = resolved.root;
|
|
175
|
+
outDir = resolved.build.outDir;
|
|
176
|
+
},
|
|
177
|
+
writeBundle() {
|
|
178
|
+
const version = readMiniappVersion(root);
|
|
179
|
+
|
|
180
|
+
if (!SEMVER_LIKE_RE.test(version)) {
|
|
181
|
+
this.warn(`package.json.version "${version}" 不是标准 semver,仍会写入 manifest.json`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const manifestPath = path.resolve(root, outDir, 'manifest.json');
|
|
185
|
+
mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
186
|
+
writeFileSync(manifestPath, `${JSON.stringify({ version }, null, 2)}\n`);
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function readMiniappVersion(root: string): string {
|
|
192
|
+
const packageJsonPath = path.join(root, 'package.json');
|
|
193
|
+
let content: string;
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
content = readFileSync(packageJsonPath, 'utf8');
|
|
197
|
+
} catch (error) {
|
|
198
|
+
throw new Error(`@heybox/hb-sdk 读取 package.json 失败:${formatReason(error)}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let packageJson: { version?: unknown };
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
packageJson = JSON.parse(content) as { version?: unknown };
|
|
205
|
+
} catch (error) {
|
|
206
|
+
throw new Error(`@heybox/hb-sdk 解析 package.json 失败:${formatReason(error)}`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (typeof packageJson.version !== 'string' || packageJson.version.trim() === '') {
|
|
210
|
+
throw new Error('@heybox/hb-sdk 提示:package.json.version 必须是非空字符串');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const version = packageJson.version.trim();
|
|
214
|
+
|
|
215
|
+
if (version === TEMPLATE_VERSION) {
|
|
216
|
+
throw new Error(TEMPLATE_VERSION_ERROR);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return version;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function formatReason(error: unknown): string {
|
|
223
|
+
if (error instanceof Error && error.message) {
|
|
224
|
+
return error.message;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return String(error);
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Manifest
|
|
232
|
+
|
|
233
|
+
`@heybox/hb-sdk/vite` 提供构建时插件 `miniappManifest()`。Vite 项目完成 `vite build` 后,会在输出目录写入 `manifest.json`:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"version": "1.2.3"
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`version` 来自小程序项目自身的 `package.json.version`。`hb-sdk create` 生成的模板默认已注册插件;现有 Vite 项目可以在 `vite.config.ts` 中手动接入:
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
import { miniappManifest } from '@heybox/hb-sdk/vite';
|
|
245
|
+
import { defineConfig } from 'vite';
|
|
246
|
+
|
|
247
|
+
export default defineConfig({
|
|
248
|
+
plugins: [miniappManifest()],
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
失败与警告语义:
|
|
253
|
+
|
|
254
|
+
- 读取 `package.json` 失败或 JSON 解析失败:`vite build` 直接失败,并输出具体原因。
|
|
255
|
+
- `package.json.version` 不是非空字符串:`vite build` 直接失败。
|
|
256
|
+
- `package.json.version` 仍是模板默认值 `0.0.0`:`vite build` 直接失败,并提示把模板默认版本改成实际版本号再发布。
|
|
257
|
+
- 版本号不满足极简 semver 形态 `x.y.z`:只输出 Rollup/Vite warning,仍会写入 manifest。
|
|
258
|
+
|
|
259
|
+
`manifest.json` 不部署到 CDN,只交给发布流水线读取后上送后台;Host 通过后台 API 间接读取版本信息。第一阶段只支持 Vite 项目,非 Vite 打包器未来通过其他子入口扩展。
|
|
260
|
+
|
|
133
261
|
## App-facing concepts
|
|
134
262
|
|
|
135
263
|
## 快速开始
|
package/skill/references/cli.md
CHANGED
|
@@ -37,6 +37,7 @@ The CLI, templates, and mock host are owned by `@heybox/hb-sdk`. Do not create a
|
|
|
37
37
|
```ts
|
|
38
38
|
import { Command, CommanderError, InvalidArgumentError } from 'commander';
|
|
39
39
|
import { runCreateCommand as defaultRunCreateCommand } from './commands/create';
|
|
40
|
+
import { runDeployCommand as defaultRunDeployCommand } from './commands/deploy';
|
|
40
41
|
import { runDevCommand as defaultRunDevCommand } from './commands/dev';
|
|
41
42
|
import { runDoctorCommand as defaultRunDoctorCommand } from './commands/doctor';
|
|
42
43
|
import {
|
|
@@ -54,6 +55,7 @@ export interface CliCommandHandlers {
|
|
|
54
55
|
printLoginStatus: typeof defaultPrintLoginStatus;
|
|
55
56
|
printUpdateReminder: typeof defaultPrintUpdateReminder;
|
|
56
57
|
runCreateCommand: typeof defaultRunCreateCommand;
|
|
58
|
+
runDeployCommand: typeof defaultRunDeployCommand;
|
|
57
59
|
runDevCommand: typeof defaultRunDevCommand;
|
|
58
60
|
runDoctorCommand: typeof defaultRunDoctorCommand;
|
|
59
61
|
}
|
|
@@ -90,6 +92,7 @@ export function createCliProgram(overrides: Partial<CliCommandHandlers> = {}) {
|
|
|
90
92
|
printLoginStatus: defaultPrintLoginStatus,
|
|
91
93
|
printUpdateReminder: defaultPrintUpdateReminder,
|
|
92
94
|
runCreateCommand: defaultRunCreateCommand,
|
|
95
|
+
runDeployCommand: defaultRunDeployCommand,
|
|
93
96
|
runDevCommand: defaultRunDevCommand,
|
|
94
97
|
runDoctorCommand: defaultRunDoctorCommand,
|
|
95
98
|
...overrides,
|
|
@@ -126,6 +129,16 @@ export function createCliProgram(overrides: Partial<CliCommandHandlers> = {}) {
|
|
|
126
129
|
}, handlers.printUpdateReminder),
|
|
127
130
|
);
|
|
128
131
|
|
|
132
|
+
program
|
|
133
|
+
.command('deploy')
|
|
134
|
+
.description('构建并发布当前小程序到 Heybox 后台')
|
|
135
|
+
.option('--skip-build', '跳过 build,直接读 dist 目录上传并发布')
|
|
136
|
+
.action(
|
|
137
|
+
withUpdateReminder(async (options) => {
|
|
138
|
+
await handlers.runDeployCommand({ skipBuild: Boolean(options.skipBuild) });
|
|
139
|
+
}, handlers.printUpdateReminder),
|
|
140
|
+
);
|
|
141
|
+
|
|
129
142
|
program
|
|
130
143
|
.command('doctor')
|
|
131
144
|
.description('诊断 hb-sdk 本地环境和 Agent Skill 版本')
|
|
@@ -298,7 +311,7 @@ Agent rules:
|
|
|
298
311
|
|
|
299
312
|
## 版本提醒
|
|
300
313
|
|
|
301
|
-
`hb-sdk`
|
|
314
|
+
`hb-sdk create`、`hb-sdk dev`、`hb-sdk login`、`hb-sdk login status`、`hb-sdk login clear` 会在命令成功执行后检查 npm registry 上 `@heybox/hb-sdk` 的 `latest` 版本。检查结果会缓存 24 小时;检查失败会静默跳过;`CI=true` 时会跳过检查,避免污染 CI 日志。`hb-sdk doctor` 不会附带版本提醒,避免把 skill 诊断输出和升级提示混在一起。本地可通过 `HB_SDK_NO_UPDATE_CHECK=1` 禁用检查。
|
|
302
315
|
|
|
303
316
|
## Repository validation commands
|
|
304
317
|
|
|
@@ -308,10 +321,13 @@ Agent rules:
|
|
|
308
321
|
pnpm --filter @heybox/hb-sdk run test:unit
|
|
309
322
|
pnpm --filter @heybox/hb-sdk run build:package
|
|
310
323
|
pnpm --filter @heybox/hb-sdk run check:boundary
|
|
324
|
+
pnpm --filter @heybox/hb-sdk run check:docs-sync
|
|
311
325
|
```
|
|
312
326
|
|
|
313
327
|
`check:boundary` 用于保护 SDK、CLI、mock host 与 runtime 之间的依赖边界。调整 CLI、mock 或协议导出时应一起运行。
|
|
314
328
|
|
|
329
|
+
`check:docs-sync` 用于校验 `README`、文档站 llms 镜像、skill references 与公开 `agent-skills` payload 没有漏同步。维护清单见 `packages/hb-sdk/DOC_SYNC_CHECKLIST.md`。
|
|
330
|
+
|
|
315
331
|
## Generated template README
|
|
316
332
|
|
|
317
333
|
````md
|
|
@@ -96,6 +96,17 @@ hb-sdk login status
|
|
|
96
96
|
hb-sdk login clear
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
### Vite manifest plugin
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import { miniappManifest } from '@heybox/hb-sdk/vite';
|
|
103
|
+
import { defineConfig } from 'vite';
|
|
104
|
+
|
|
105
|
+
export default defineConfig({
|
|
106
|
+
plugins: [miniappManifest()],
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
99
110
|
## Negative examples
|
|
100
111
|
|
|
101
112
|
- Do not import from internal hb-sdk implementation paths.
|
|
@@ -105,3 +116,4 @@ hb-sdk login clear
|
|
|
105
116
|
- Do not pass raw internal share/network protocol fields from mini-program code.
|
|
106
117
|
- Do not treat `hb-sdk login` as iframe SDK authentication state.
|
|
107
118
|
- Do not create a second mock runtime package when `hb-sdk dev` is the supported local mock workflow.
|
|
119
|
+
- Do not import `@heybox/hb-sdk/vite` from iframe business code or fetch a deployed `manifest.json` directly.
|