@tbox.cn/app-template-h5 0.1.14 → 0.1.16

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/AGENTS.md CHANGED
@@ -13,23 +13,26 @@ template-h5 是面向 AI 生成 H5 应用的单 workspace 模板:`apps/client`
13
13
  ## 运行与验证(平台沙箱)
14
14
 
15
15
  应用构建与运行在平台沙箱中,启动/停止/重启由平台负责——不要运行 `pnpm dev` 等长驻进程
16
- 命令(沙箱规则 `config/rules/no-persistent-process.md`)。你只改代码与配置,用一次性命令
17
- 验证:
16
+ 命令。你只改代码与配置,用一次性命令验证:
18
17
 
19
18
  ```sh
20
19
  pnpm install # 会话开始时 node_modules 缺失先装
21
20
  pnpm typecheck
22
21
  pnpm test
23
- pnpm build
24
- pnpm verify # typecheck + test + lint + build + check:inspector
22
+ pnpm verify:fast # typecheck + test + check(不含 build/lint)
25
23
  pnpm check:inspector # inspector 接线守卫(随 @tbox.cn/app-sdk-server 分发)
24
+ ```
25
+
26
+ - **编译验证 = typecheck**;运行效果看平台托管的 8000 活体(`curl /api/health`,连接被拒 ≠ 应用损坏)。
27
+ - **不要运行 `pnpm build` / `pnpm verify`**:冷构建超过沙箱命令时限,且 dev 不消费 `dist`。
28
+ - 环境变量见 [README.md](README.md) 的「环境变量」节。
26
29
 
27
30
  ## SDK 复用点(优先复用,勿手写)
28
31
 
29
32
  - `@tbox.cn/app-sdk-client`:`configureRuntime`(API base 注入,勿硬编码 host)、`httpGet/httpPost/createService`(HTTP 客户端)、`ErrorBoundary`、`createLogger`、`installGlobalErrorReporting`
30
33
  - `@tbox.cn/app-sdk-server`:`createLogger`
31
34
  - `@tbox.cn/app-sdk-server/platform`:`installInspector`;vite `code-inspect` 插件入口为 `@tbox.cn/app-sdk-client/platform/code-inspect`(页面微调基线,受 `check:inspector` 守卫)
32
- - 不直接 import `@tbox-dev-js/sdk`——平台能力一律经 `@tbox.cn/app-sdk-client` / `@tbox.cn/app-sdk-server` 公开入口。开入口。
35
+ - 不直接 import `@tbox-dev-js/sdk`——平台能力一律经 `@tbox.cn/app-sdk-client` / `@tbox.cn/app-sdk-server` 公开入口。
33
36
 
34
37
  ## 关键入口
35
38
 
@@ -46,6 +49,7 @@ apps/server/src/dev.ts # vite dev 入口(仅 tsx 运行;
46
49
  - 单端口 8000(dev 与生产统一;端口经 `process.env.PORT || 8000`,lint 禁止硬编码)
47
50
  - `installInspector` 接线 + `apps/client/index.html` 的 `/__vs_inspector__.js` 标签(页面微调契约)
48
51
  - `GET /api/health` 恒返回 `{ "status": "ok" }`;未知 `/api/*` 恒 JSON 404
52
+ - `apps/server/tests` 契约测试随模板分发勿删(health/JSON 404 断言);client 业务面测试由应用自建——模板出厂零 client 测试文件(`passWithNoTests` 保绿,新增测试后本约定不变)
49
53
  - 服务端凭证/环境变量不进 client bundle(客户端环境值仅 `import.meta.env.VITE_*` 且经 `configureRuntime` 注入)
50
54
 
51
55
  ## web-view 样式约定(嵌入支付宝小程序 web-view 壳时遵守)
@@ -58,6 +62,6 @@ apps/server/src/dev.ts # vite dev 入口(仅 tsx 运行;
58
62
  ## 边界
59
63
 
60
64
  - 保持单 workspace 的 `apps/client` + `apps/server` 两成员;不新增 `apps/client/` 之外的 Vite 配置或嵌套 lockfile(`pnpm check:workspace` 校验)。
61
- - 无模块/Provider/主题装配面:缺双端 `apps/*/src/modules.ts`——`tbox-app module add`、`tbox-app new module`、`tbox-app new provider` 会被 CLI 直接拒绝;`tbox-app theme use` 因无主题接线点也不适用。
65
+ - 无模块/Provider/主题装配面:缺双端 `apps/*/src/modules.ts`——`npx --yes @tbox.cn/app-cli module add`、`npx --yes @tbox.cn/app-cli new module`、`npx --yes @tbox.cn/app-cli new provider` 会被 CLI 直接拒绝;`npx --yes @tbox.cn/app-cli theme use` 因无主题接线点也不适用。
62
66
  - 模板不预设端形态(移动/桌面/自适应)——适配策略由应用自定;全局样式挂点 = `apps/client/src/styles/base.css`(仅设备无关卫生规则)。
63
67
  - 结构、路由、命令、依赖或环境变量变化时同步 README 与本文件。
package/README.md CHANGED
@@ -14,7 +14,7 @@ pnpm dev
14
14
  ## 生成新应用
15
15
 
16
16
  ```sh
17
- tbox-app create . --name my-h5-app --source @tbox.cn/app-template-h5
17
+ npx --yes @tbox.cn/app-cli create . --name my-h5-app --source @tbox.cn/app-template-h5
18
18
  pnpm install
19
19
  ```
20
20
 
@@ -18,4 +18,8 @@ export default defineConfig(({ command }) => ({
18
18
  build: {
19
19
  rollupOptions: { input: { index: resolve(__dirname, 'index.html') } },
20
20
  },
21
+ // 模板出厂零 client 测试文件:随发测试禁钉用户实施面(business/App.tsx 是用户首个改写对象,
22
+ // 出厂断言其内容必随应用构建失败——testing/2026-10-20-template-shipped-test-boundary.md);
23
+ // 新增客户端测试时移除本旗标。
24
+ test: { passWithNoTests: true },
21
25
  }));
@@ -72,7 +72,7 @@ const vite = await createViteServer({
72
72
  });
73
73
 
74
74
  const runtime = createTboxDevRuntime({
75
- vite: { middlewares: vite.middlewares, transformIndexHtml: vite.transformIndexHtml },
75
+ vite: { middlewares: vite.middlewares, transformIndexHtml: vite.transformIndexHtml, ws: vite.ws },
76
76
  hmrHub,
77
77
  hmrPath: path.posix.join(vite.config.base, HMR_WS_PATH),
78
78
  tokenState,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tbox.cn/app-template-h5",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "tbox H5 全栈模板(单 workspace:apps/client + apps/server),运行时与页面微调经 @tbox.cn/app-sdk。",
5
5
  "type": "module",
6
6
  "engines": {
@@ -35,7 +35,7 @@
35
35
  "eslint-plugin-react-hooks": "5.2.0",
36
36
  "typescript-eslint": "8.67.0",
37
37
  "vite": "6.4.3",
38
- "@tbox.cn/app-sdk-server": "0.26.0"
38
+ "@tbox.cn/app-sdk-server": "0.26.2"
39
39
  },
40
40
  "scripts": {
41
41
  "dev": "pnpm --filter ./apps/server dev",
@@ -47,6 +47,7 @@
47
47
  "verify": "pnpm typecheck && pnpm test && pnpm lint && pnpm build && pnpm check:inspector",
48
48
  "check": "pnpm check:workspace && pnpm check:inspector",
49
49
  "check:workspace": "node scripts/check-workspace.mjs",
50
- "check:inspector": "tbox-inspector-check"
50
+ "check:inspector": "tbox-inspector-check",
51
+ "verify:fast": "pnpm typecheck && pnpm test && pnpm check"
51
52
  }
52
53
  }
@@ -10,8 +10,8 @@ catalogs:
10
10
  specifier: 0.21.3
11
11
  version: 0.21.3
12
12
  '@tbox.cn/app-sdk-server':
13
- specifier: 0.26.0
14
- version: 0.26.0
13
+ specifier: 0.26.2
14
+ version: 0.26.2
15
15
  '@types/express':
16
16
  specifier: 4.17.25
17
17
  version: 4.17.25
@@ -79,7 +79,7 @@ importers:
79
79
  devDependencies:
80
80
  '@tbox.cn/app-sdk-server':
81
81
  specifier: 'catalog:'
82
- version: 0.26.0
82
+ version: 0.26.2
83
83
  eslint:
84
84
  specifier: 'catalog:'
85
85
  version: 9.39.5
@@ -134,7 +134,7 @@ importers:
134
134
  dependencies:
135
135
  '@tbox.cn/app-sdk-server':
136
136
  specifier: 'catalog:'
137
- version: 0.26.0
137
+ version: 0.26.2
138
138
  express:
139
139
  specifier: 'catalog:'
140
140
  version: 4.22.2
@@ -959,8 +959,12 @@ packages:
959
959
  resolution: {integrity: sha512-8sqP/23MoUlbTX9enFNotP5bu7XKFfigDUJ6sEn1Ff2a0rRlSTWzLWmDv9lP70cfZMPjh4MHoLKFoukr8QPvMA==}
960
960
  engines: {node: '>=20.0.0'}
961
961
 
962
- '@tbox.cn/app-contracts@0.13.1':
963
- resolution: {integrity: sha512-Cty4qoknyihli6ZMlxOqqTgRqwg0NOh0WOMfIWdB4rHua0QzZkP1jUoeffq5imnpIh7vXdfLhDpv/JwTrHd1XQ==}
962
+ '@tbox.cn/app-contracts@0.13.2':
963
+ resolution: {integrity: sha512-0lY9g29ice7xYbmV5XDnEiMmM70jvSzeK2cciUZVpzHgGykWqZiPRlqXIGkIRY7uObDQ1cICHC4mS67HuNQ8Jg==}
964
+ engines: {node: '>=20.0.0'}
965
+
966
+ '@tbox.cn/app-contracts@0.13.3':
967
+ resolution: {integrity: sha512-P16LFd+ZzIASrujs6fyaOEwRnsLg7Lh5k1qOVDNblmohrvUbVIOK5ntn+7mupJxnjK7SY43RUT4mtWtfM85/rQ==}
964
968
  engines: {node: '>=20.0.0'}
965
969
 
966
970
  '@tbox.cn/app-sdk-client@0.21.3':
@@ -971,13 +975,17 @@ packages:
971
975
  resolution: {integrity: sha512-4kcoxnZnPgsO0RwAsjsodOXRhZNQcr9r3INN3Z03/JR2e3E+izkW2YHsgGcdbVSVX81s8gZrkaBbE+xco3wSqg==}
972
976
  engines: {node: '>=20.0.0'}
973
977
 
974
- '@tbox.cn/app-sdk-server@0.26.0':
975
- resolution: {integrity: sha512-VpV3sf4K/2MEsnkuK5EqZUyf9KoSVHeJUm4Al0M6R4Wumg6183apnxB2f38S5wuP30JSJShN/ww63EzRniTrjw==}
978
+ '@tbox.cn/app-sdk-core@0.20.5':
979
+ resolution: {integrity: sha512-HLLRg1y2jB32uJPL3/a387eABdNZUxrmkGoJwIv44XV9B94DXmTgb9vxYzbyBa0FazxXG0WudyzFnmH5eeqqrw==}
980
+ engines: {node: '>=20.0.0'}
981
+
982
+ '@tbox.cn/app-sdk-server@0.26.2':
983
+ resolution: {integrity: sha512-TY9oo3VnsHtLv5im9eu9UUBzDJoluk/YRR7MFwU98G1ZzUDoSLagelb0kamhx5j/R9sXZjwV0NY3Kv6dz/WVmw==}
976
984
  engines: {node: '>=20.0.0'}
977
985
  hasBin: true
978
986
 
979
- '@tbox.cn/app-toolkit@0.8.0':
980
- resolution: {integrity: sha512-urefCf5DCWbH9wM8dSGavA9MNdY4gx7LY16+s9jIlwhahq83mfrCP2h9ombn44ljMrv04G7mnb3vMtNeWs5/Ug==}
987
+ '@tbox.cn/app-toolkit@0.8.3':
988
+ resolution: {integrity: sha512-i+rz8tUwndygwCw/T5dp/59p2JKW+Xpfy2UznKOY8vuKbqbe2ANCUTDUuNf8IDuyfvy158Iw/+5H/hLVNAD/3w==}
981
989
  engines: {node: '>=20.0.0'}
982
990
 
983
991
  '@types/babel__core@7.20.5':
@@ -2823,7 +2831,13 @@ snapshots:
2823
2831
  react: 18.3.1
2824
2832
  zod: 3.25.76
2825
2833
 
2826
- '@tbox.cn/app-contracts@0.13.1':
2834
+ '@tbox.cn/app-contracts@0.13.2':
2835
+ dependencies:
2836
+ '@ag-ui/core': 0.0.47
2837
+ react: 18.3.1
2838
+ zod: 3.25.76
2839
+
2840
+ '@tbox.cn/app-contracts@0.13.3':
2827
2841
  dependencies:
2828
2842
  '@ag-ui/core': 0.0.47
2829
2843
  react: 18.3.1
@@ -2840,19 +2854,23 @@ snapshots:
2840
2854
  dependencies:
2841
2855
  '@tbox.cn/app-contracts': 0.13.0
2842
2856
 
2843
- '@tbox.cn/app-sdk-server@0.26.0':
2857
+ '@tbox.cn/app-sdk-core@0.20.5':
2858
+ dependencies:
2859
+ '@tbox.cn/app-contracts': 0.13.2
2860
+
2861
+ '@tbox.cn/app-sdk-server@0.26.2':
2844
2862
  dependencies:
2845
2863
  '@ag-ui/core': 0.0.47
2846
- '@tbox.cn/app-contracts': 0.13.1
2847
- '@tbox.cn/app-sdk-core': 0.20.4
2848
- '@tbox.cn/app-toolkit': 0.8.0
2864
+ '@tbox.cn/app-contracts': 0.13.3
2865
+ '@tbox.cn/app-sdk-core': 0.20.5
2866
+ '@tbox.cn/app-toolkit': 0.8.3
2849
2867
  express: 4.22.2
2850
2868
  jose: 6.2.8
2851
2869
  zod: 3.25.76
2852
2870
  transitivePeerDependencies:
2853
2871
  - supports-color
2854
2872
 
2855
- '@tbox.cn/app-toolkit@0.8.0':
2873
+ '@tbox.cn/app-toolkit@0.8.3':
2856
2874
  dependencies:
2857
2875
  ajv: 8.20.0
2858
2876
  zod: 3.25.76
@@ -35,11 +35,11 @@ catalog:
35
35
  "@types/express": 4.17.25
36
36
  "@tbox.cn/app-sdk-core": 0.20.5
37
37
  "@tbox.cn/app-sdk-client": 0.21.3
38
- "@tbox.cn/app-sdk-server": 0.26.0
39
- "@tbox.cn/app-agent-sdk-server": 0.3.1
38
+ "@tbox.cn/app-sdk-server": 0.26.2
39
+ "@tbox.cn/app-agent-sdk-server": 0.3.3
40
40
  "@tbox.cn/app-agent-sdk-client": 0.2.0
41
- "@tbox.cn/app-contracts": 0.13.2
42
- "@tbox.cn/app-contracts-mall": 0.13.1
41
+ "@tbox.cn/app-contracts": 0.13.3
42
+ "@tbox.cn/app-contracts-mall": 0.13.2
43
43
  eslint: 9.39.5
44
44
  typescript-eslint: 8.67.0
45
45
  eslint-plugin-react-hooks: 5.2.0
@@ -31,6 +31,24 @@ const nestedLockfiles = new Set([
31
31
  ]);
32
32
  const viteConfigPattern = /^vite\.config\.(?:js|mjs|cjs|ts|mts|cts)$/;
33
33
 
34
+ /**
35
+ * CLI 裸简写防线:应用文档里不得出现 `tbox-app <cmd>`(agent 照抄后 PATH 无 bin → 命令失败)。
36
+ * 唯一合法形态 = `npx --yes @tbox.cn/app-cli <cmd>`;`tbox-app-dev`(私有 CLI)不匹配。
37
+ */
38
+ const bareCliPattern = /\btbox-app\s+(?:module|provider|theme|starter|new|create|schema|skills|doctor|miniapp-container)\b/g;
39
+ const cliDocFiles = ['AGENTS.md', 'README.md', 'ENV.md'];
40
+
41
+ async function checkCliShorthand(findings) {
42
+ for (const rel of cliDocFiles) {
43
+ const file = path.join(projectDir, rel);
44
+ if (!existsSync(file)) continue;
45
+ const text = await readFile(file, 'utf8');
46
+ for (const match of text.matchAll(bareCliPattern)) {
47
+ findings.bareCliShorthands.push(`${rel}: ${match[0]}`);
48
+ }
49
+ }
50
+ }
51
+
34
52
  function relativeDir(filePath) {
35
53
  const relative = path.relative(projectDir, path.dirname(filePath));
36
54
  return relative === '' ? '.' : relative.split(path.sep).join('/');
@@ -74,6 +92,10 @@ function printFailure(findings) {
74
92
  console.error('\n检测到 apps/client/ 之外的 Vite 项目配置:');
75
93
  for (const file of findings.detachedViteConfigs) console.error(` - ${file}`);
76
94
  }
95
+ if (findings.bareCliShorthands.length > 0) {
96
+ console.error('\n检测到 CLI 裸简写(须写全 npx --yes @tbox.cn/app-cli <cmd>):');
97
+ for (const item of findings.bareCliShorthands) console.error(` - ${item}`);
98
+ }
77
99
 
78
100
  console.error('');
79
101
  process.exitCode = 1;
@@ -102,9 +124,11 @@ async function main() {
102
124
  const findings = {
103
125
  nestedLockfiles: [],
104
126
  detachedViteConfigs: [],
127
+ bareCliShorthands: [],
105
128
  };
106
129
 
107
130
  await walk(projectDir, findings);
131
+ await checkCliShorthand(findings);
108
132
 
109
133
  if (Object.values(findings).some((items) => items.length > 0)) {
110
134
  printFailure(findings);
@@ -1,18 +0,0 @@
1
- // @vitest-environment happy-dom
2
- import { describe, expect, it } from 'vitest';
3
- import { createRoot } from 'react-dom/client';
4
- import { flushSync } from 'react-dom';
5
- import { createElement } from 'react';
6
- import BusinessApp from './App';
7
-
8
- describe('BusinessApp', () => {
9
- it('渲染中性入口', () => {
10
- const container = document.createElement('div');
11
- document.body.appendChild(container);
12
- flushSync(() => {
13
- createRoot(container).render(createElement(BusinessApp));
14
- });
15
- expect(container.querySelector('main')?.textContent).toBe('应用从这里开始');
16
- container.remove();
17
- });
18
- });