create-bubbles 0.1.27 → 0.1.28
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/dist/index.js +4 -4
- package/package.json +10 -2
- package/template-pnpm-vp-monorepo/.changeset/README.md +8 -0
- package/template-pnpm-vp-monorepo/.changeset/config.json +11 -0
- package/template-pnpm-vp-monorepo/.gitattributes +5 -0
- package/template-pnpm-vp-monorepo/.github/workflows/ci.yml +33 -0
- package/template-pnpm-vp-monorepo/.github/workflows/docs.yml +55 -0
- package/template-pnpm-vp-monorepo/.github/workflows/release.yml +54 -0
- package/template-pnpm-vp-monorepo/.vite-hooks/commit-msg +1 -0
- package/template-pnpm-vp-monorepo/.vite-hooks/pre-commit +1 -0
- package/template-pnpm-vp-monorepo/.vite-hooks/run.mjs +17 -0
- package/template-pnpm-vp-monorepo/.vscode/settings.json +23 -0
- package/{LICENSE → template-pnpm-vp-monorepo/LICENSE} +2 -2
- package/template-pnpm-vp-monorepo/README.md +93 -0
- package/template-pnpm-vp-monorepo/_gitignore +43 -0
- package/template-pnpm-vp-monorepo/apps/docs/.vitepress/config.mts +69 -0
- package/template-pnpm-vp-monorepo/apps/docs/guide/getting-started.md +70 -0
- package/template-pnpm-vp-monorepo/apps/docs/guide/release.md +73 -0
- package/template-pnpm-vp-monorepo/apps/docs/guide/workspace.md +84 -0
- package/template-pnpm-vp-monorepo/apps/docs/index.md +22 -0
- package/template-pnpm-vp-monorepo/apps/docs/package.json +23 -0
- package/template-pnpm-vp-monorepo/apps/docs/tsconfig.json +7 -0
- package/template-pnpm-vp-monorepo/apps/docs/vite.config.ts +12 -0
- package/template-pnpm-vp-monorepo/apps/playground/index.html +14 -0
- package/template-pnpm-vp-monorepo/apps/playground/package.json +24 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/App.vue +214 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/env.d.ts +6 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/main.ts +6 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/style.css +728 -0
- package/template-pnpm-vp-monorepo/apps/playground/tsconfig.json +10 -0
- package/template-pnpm-vp-monorepo/apps/playground/vite.config.ts +29 -0
- package/template-pnpm-vp-monorepo/commitlint.config.mjs +3 -0
- package/template-pnpm-vp-monorepo/eslint.config.mjs +22 -0
- package/template-pnpm-vp-monorepo/mise.toml +3 -0
- package/template-pnpm-vp-monorepo/package.json +40 -0
- package/template-pnpm-vp-monorepo/packages/utils/LICENSE +21 -0
- package/template-pnpm-vp-monorepo/packages/utils/README.md +26 -0
- package/template-pnpm-vp-monorepo/packages/utils/_gitignore +4 -0
- package/template-pnpm-vp-monorepo/packages/utils/package.json +42 -0
- package/template-pnpm-vp-monorepo/packages/utils/scripts/verify-package.mjs +127 -0
- package/template-pnpm-vp-monorepo/packages/utils/src/index.ts +12 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/commonjs.cts +20 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/esm.mts +20 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/tsconfig.json +10 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/index.test.ts +30 -0
- package/template-pnpm-vp-monorepo/packages/utils/tsconfig.json +4 -0
- package/template-pnpm-vp-monorepo/packages/utils/vite.config.ts +20 -0
- package/template-pnpm-vp-monorepo/pnpm-workspace.yaml +27 -0
- package/template-pnpm-vp-monorepo/tsconfig/base.json +22 -0
- package/template-pnpm-vp-monorepo/tsconfig/node.json +8 -0
- package/template-pnpm-vp-monorepo/tsconfig/vue.json +7 -0
- package/template-pnpm-vp-monorepo/tsconfig.json +4 -0
- package/template-pnpm-vp-monorepo/vite.config.ts +38 -0
- package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/212/200/346/234/257/345/245/221/347/272/246.md +5 -3
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//344/272/244/344/273/230/350/256/260/345/275/225.md +9 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//345/217/221/345/270/203/350/257/204/344/274/260.md +93 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//345/267/245/345/205/267//350/277/220/350/241/214/346/227/266/345/217/221/345/270/203/346/243/200/346/237/245.mjs +340 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/346/212/245/345/221/212.md +28 -6
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/catalog/en_US.json +4 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/i18n.config.mjs +9 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/report.json +16 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/source/app.ts +2 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/catalog/en_US.json +4 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/i18n.config.mjs +9 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/report.json +19 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/output.json +84 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//345/275/223/345/211/215/345/244/215/351/252/214.json +86 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//346/243/200/346/237/245/347/273/223/346/236/234.json +30 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//346/263/250/351/207/212/345/233/236/345/275/222.json +40 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-core-0.0.0.tgz +0 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-react-0.0.0.tgz +0 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-vue-0.0.1.tgz +0 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203//344/272/247/347/211/251/345/244/215/351/252/214.json +419 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203//346/243/200/346/237/245/347/273/223/346/236/234.json +339 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//350/277/220/350/241/214/346/227/266/345/217/221/345/270/203/346/243/200/346/237/245.json +131 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//350/256/276/350/256/241/346/226/271/346/241/210.md +19 -0
- package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//351/234/200/346/261/202/346/226/207/346/241/243.md +21 -3
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/274/232/350/257/235/347/256/241/347/220/206//346/212/200/346/234/257/345/245/221/347/272/246.md +5 -2
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/274/232/350/257/235/347/256/241/347/220/206//351/234/200/346/261/202/346/226/207/346/241/243.md +4 -3
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201/PRD.md +2 -1
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//346/212/200/346/234/257/345/245/221/347/272/246.md +3 -2
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//346/265/213/350/257/225/346/212/245/345/221/212.md +15 -12
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//350/201/224/350/260/203/350/256/260/345/275/225.md +6 -5
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//350/256/276/350/256/241/346/226/271/346/241/210.md +2 -1
- package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//351/234/200/346/261/202/346/226/207/346/241/243.md +4 -3
- package/template-vp-monorepo-react-nestjs/.spaces/README.md +3 -2
- package/template-vp-monorepo-react-nestjs/apps/web/test/{password-actions.spec.ts → password/password-actions.spec.ts} +3 -3
- package/template-vp-monorepo-react-nestjs/apps/web/test/{password-reset-action.spec.ts → password/password-reset-action.spec.ts} +4 -2
- package/template-vp-monorepo-react-nestjs/apps/web/test/{workspaces-password-entry.spec.tsx → password/workspaces-password-entry.spec.tsx} +7 -7
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/README.md +2 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.test.ts +88 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +34 -11
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +36 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/use-store.ts +15 -5
- package/template-vp-monorepo-react-nestjs/tsconfig.lib.json +1 -1
- package/template-vp-react/package.json +5 -5
- package/template-vp-vue-eslint-vapor/.vscode/settings.json +53 -0
- package/template-vp-vue-eslint-vapor/package.json +1 -0
- package/template-vp-vue-eslint-vapor/pnpm-workspace.yaml +0 -24
- package/template-vp-vue-eslint-vapor/src/main.ts +2 -3
- package/template-vp-vue-eslint-vapor/vite.config.ts +26 -31
- package/template-vp-react/.vscode/settings.json +0 -18
- /package/{template-vp-vue-eslint-vapor → template-pnpm-vp-monorepo}/.vscode/extensions.json +0 -0
- /package/template-vp-monorepo-react-nestjs/apps/server/test/auth/{password-operations.spec.ts → password/password-operations.spec.ts} +0 -0
- /package/template-vp-monorepo-react-nestjs/apps/server/test/auth/{password.integration.spec.ts → password/password.integration.spec.ts} +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# 工作区约定
|
|
2
|
+
|
|
3
|
+
## 目录职责
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
apps/
|
|
7
|
+
playground/ 示例应用
|
|
8
|
+
docs/ VitePress 文档站点
|
|
9
|
+
packages/
|
|
10
|
+
utils/ 内部共享工具包
|
|
11
|
+
tsconfig/ 共享 TypeScript 配置(base / node / vue)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`apps/*` 和 `packages/*` 由 `pnpm-workspace.yaml` 纳入工作区。根目录负责公共命令、依赖版本目录、锁文件、质量检查和 CI;每个子项目维护自己的入口、依赖和脚本。
|
|
15
|
+
|
|
16
|
+
根项目、`docs`、`playground` 和 `@bubblesjs/utils` 均为 `private: true`,目前没有 npm 发布对象。应用名称可继续使用 `playground`、`docs` 等,`@bubblesjs` scope 同样用于内部共享包标识。共享包放在 `packages/`,提供明确的 `exports` 和类型入口。共享 TypeScript 配置放在根目录 `tsconfig/`,通过相对路径复用。
|
|
17
|
+
|
|
18
|
+
## 外部依赖使用 `catalog:`
|
|
19
|
+
|
|
20
|
+
所有工作区共享的第三方依赖版本统一声明在根 `pnpm-workspace.yaml` 的 `catalog` 中:
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
catalog:
|
|
24
|
+
vue: ^3.5.0
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
子项目只声明需要哪些依赖:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"vue": "catalog:"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
上面的版本仅用于展示格式;以仓库内的目录配置为准。添加外部依赖时,先在 `catalog` 中确定版本,再在实际使用它的项目中写 `catalog:`。运行 `pnpm install`,将清单和根锁文件一起提交。
|
|
38
|
+
|
|
39
|
+
## 内部依赖使用 `workspace:*`
|
|
40
|
+
|
|
41
|
+
应用或其他包依赖共享包时,按包名声明。例如 Playground 的内部依赖:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@bubblesjs/utils": "workspace:*"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`workspace:*` 要求使用当前仓库内的包,避免安装同名的远程包。打包或发布时,pnpm 会把该协议转换为实际版本。
|
|
52
|
+
|
|
53
|
+
应用可配置源码别名获得即时开发反馈;发布包仍需要正确的 `exports`、构建结果和类型声明。使用者导入包名,避免引用其他项目的内部文件路径。
|
|
54
|
+
|
|
55
|
+
## 添加共享包
|
|
56
|
+
|
|
57
|
+
1. 在 `packages/` 中创建目录,例如 `packages/math/`。
|
|
58
|
+
2. 添加 `package.json`,设置唯一的包名,例如 `@bubblesjs/math`。内部共享包设置 `private: true`。若将来需要 npm 发布,须显式移除 `private: true`,设置 `publishConfig.access` 为 `public`,并完善 `version`、`type`、`files`、`exports` 和发布元信息;复制 utils 创建公开包时同样需要这些步骤。
|
|
59
|
+
3. 添加 `src/index.ts` 作为公共入口,将需要对外开放的 API 显式导出。
|
|
60
|
+
4. 参考 `packages/utils/` 配置构建、测试和类型检查,继承根目录 `tsconfig/` 中适用的配置。
|
|
61
|
+
5. 在使用它的项目中添加 `workspace:*` 依赖。需要源码开发时,同步配置 Vite 与 TypeScript 别名。
|
|
62
|
+
6. 执行 `pnpm install`、`pnpm typecheck`、`pnpm test`、`pnpm build`。为新共享包补充本地产物检查,再执行 `pnpm verify:packages`;这个命令不执行 npm 发布。
|
|
63
|
+
7. 如需 npm 发布,补充发布元信息,并添加 changeset。
|
|
64
|
+
|
|
65
|
+
一个包只对外公开稳定的入口。把业务代码拆成包时,先确认它需要独立复用或发布,再划定依赖边界。
|
|
66
|
+
|
|
67
|
+
## 添加应用
|
|
68
|
+
|
|
69
|
+
1. 在 `apps/` 中创建目录,例如 `apps/admin/`。
|
|
70
|
+
2. 添加唯一的 `package.json` 名称和 `private: true`。声明 `dev`、`build`、`typecheck` 等实际需要的脚本。
|
|
71
|
+
3. 使用 `catalog:` 引用外部依赖,使用 `workspace:*` 引用共享包。
|
|
72
|
+
4. 继承共享 TypeScript 配置,并添加对应框架的构建配置。
|
|
73
|
+
5. 执行 `pnpm install`,然后通过 `pnpm --filter admin dev` 启动该应用。
|
|
74
|
+
6. 将常用入口补充到根脚本或文档中,确保全工作区构建和类型检查都能运行。
|
|
75
|
+
|
|
76
|
+
应用之间通过共享包复用代码,避免一个应用直接导入另一个应用的源码。
|
|
77
|
+
|
|
78
|
+
## 共享配置和文档
|
|
79
|
+
|
|
80
|
+
Vue 应用与文档通过 `"extends": "../../tsconfig/vue.json"` 继承共享配置;Node / 库使用 `tsconfig/node.json`,基础约束定义在 `tsconfig/base.json`。覆盖配置时只声明项目所需的差异。
|
|
81
|
+
|
|
82
|
+
`tsconfig/` 是普通配置目录,没有 `package.json`,不参与工作区依赖管理或 npm 发布。子项目通过相对路径继承,无需声明配置包依赖。
|
|
83
|
+
|
|
84
|
+
文档页面放在 `apps/docs/`,使用 Markdown 编写并由 VitePress 构建。当前文档站点独立运行;共享包的实际使用由 Playground 示例应用展示。
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: home
|
|
3
|
+
title: 首页
|
|
4
|
+
hero:
|
|
5
|
+
name: Monorepo Starter
|
|
6
|
+
text: 把应用、共享包与文档放进同一个工作区
|
|
7
|
+
tagline: pnpm 管理依赖,Vite+ 编排质量与构建,Changesets 记录版本变更。复制模板后即可开始自己的项目。
|
|
8
|
+
actions:
|
|
9
|
+
- theme: brand
|
|
10
|
+
text: 开始使用
|
|
11
|
+
link: /guide/getting-started
|
|
12
|
+
- theme: alt
|
|
13
|
+
text: 查看工作区约定
|
|
14
|
+
link: /guide/workspace
|
|
15
|
+
features:
|
|
16
|
+
- title: 应用与共享包
|
|
17
|
+
details: apps/ 放置应用和独立运行的文档站点,packages/ 放置可独立构建的内部共享代码。
|
|
18
|
+
- title: 集中管理依赖
|
|
19
|
+
details: 外部依赖使用 catalog:,工作区依赖使用 workspace:*,在根目录维护版本与锁文件。
|
|
20
|
+
- title: 可验证的包产物
|
|
21
|
+
details: 类型、测试、构建与包产物检查贯穿本地和 CI,Changesets 为将来的公开包保留版本变更流程。
|
|
22
|
+
---
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "docs",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "vp run bundle",
|
|
8
|
+
"dev": "vitepress dev . --port 5174 --strictPort",
|
|
9
|
+
"preview": "vitepress preview .",
|
|
10
|
+
"typecheck": "vue-tsc -p tsconfig.json --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"vue": "catalog:"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/node": "catalog:",
|
|
17
|
+
"typescript": "catalog:",
|
|
18
|
+
"vite": "catalog:",
|
|
19
|
+
"vite-plus": "catalog:",
|
|
20
|
+
"vitepress": "catalog:",
|
|
21
|
+
"vue-tsc": "catalog:"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="theme-color" content="#edf3f9" />
|
|
7
|
+
<meta name="description" content="Vue 与共享工具包组成的 Monorepo 模板开发工作台。" />
|
|
8
|
+
<title>Mono · 开发工作台</title>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app"></div>
|
|
12
|
+
<script type="module" src="/src/main.ts"></script>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "playground",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "vp run bundle",
|
|
8
|
+
"dev": "vp dev",
|
|
9
|
+
"preview": "vp preview",
|
|
10
|
+
"typecheck": "vue-tsc -p tsconfig.json --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@bubblesjs/utils": "workspace:*",
|
|
14
|
+
"vue": "catalog:"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "catalog:",
|
|
18
|
+
"@vitejs/plugin-vue": "catalog:",
|
|
19
|
+
"typescript": "catalog:",
|
|
20
|
+
"vite": "catalog:",
|
|
21
|
+
"vite-plus": "catalog:",
|
|
22
|
+
"vue-tsc": "catalog:"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { clamp } from "@bubblesjs/utils";
|
|
3
|
+
import { computed, ref } from "vue";
|
|
4
|
+
|
|
5
|
+
const inputValue = ref<number | string>(128);
|
|
6
|
+
const minimum = ref<number | string>(0);
|
|
7
|
+
const maximum = ref<number | string>(100);
|
|
8
|
+
const presets = [
|
|
9
|
+
{ label: "低于下限", value: -24 },
|
|
10
|
+
{ label: "落在区间", value: 48 },
|
|
11
|
+
{ label: "高于上限", value: 128 },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
function isValidNumber(value: number | string) {
|
|
15
|
+
return value !== "" && Number.isFinite(Number(value)) && Math.abs(Number(value)) <= 1000;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const error = computed(() => {
|
|
19
|
+
if (![inputValue.value, minimum.value, maximum.value].every(isValidNumber)) {
|
|
20
|
+
return "请为三个输入填写 −1000 到 1000 之间的数值。";
|
|
21
|
+
}
|
|
22
|
+
if (Number(minimum.value) > Number(maximum.value)) {
|
|
23
|
+
return "下限不能大于上限,请调整区间。";
|
|
24
|
+
}
|
|
25
|
+
return "";
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const result = computed(() =>
|
|
29
|
+
error.value
|
|
30
|
+
? null
|
|
31
|
+
: clamp(Number(inputValue.value), Number(minimum.value), Number(maximum.value)),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const scale = computed(() => {
|
|
35
|
+
if (error.value) return { start: -40, end: 160 };
|
|
36
|
+
const start = Math.min(Number(inputValue.value), Number(minimum.value), 0);
|
|
37
|
+
const end = Math.max(Number(inputValue.value), Number(maximum.value), 100);
|
|
38
|
+
const padding = Math.max((end - start) * 0.12, 10);
|
|
39
|
+
return { start: start - padding, end: end + padding };
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
function position(value: number | string) {
|
|
43
|
+
return `${((Number(value) - scale.value.start) / (scale.value.end - scale.value.start)) * 100}%`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function displayNumber(value: number) {
|
|
47
|
+
return String(value);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const ticks = computed(() =>
|
|
51
|
+
Array.from({ length: 9 }, (_, index) => ({
|
|
52
|
+
position: `${(index / 8) * 100}%`,
|
|
53
|
+
label: new Intl.NumberFormat("zh-CN", { maximumFractionDigits: 1 }).format(
|
|
54
|
+
scale.value.start + ((scale.value.end - scale.value.start) * index) / 8,
|
|
55
|
+
),
|
|
56
|
+
})),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const resultHint = computed(() => {
|
|
60
|
+
if (result.value === null) return "填写有效数值后查看结果";
|
|
61
|
+
if (Number(inputValue.value) < Number(minimum.value)) return "低于下限,返回区间起点";
|
|
62
|
+
if (Number(inputValue.value) > Number(maximum.value)) return "高于上限,返回区间终点";
|
|
63
|
+
return "位于区间内,保留原值";
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
function selectPreset(value: number) {
|
|
67
|
+
inputValue.value = value;
|
|
68
|
+
minimum.value = 0;
|
|
69
|
+
maximum.value = 100;
|
|
70
|
+
}
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<template>
|
|
74
|
+
<div class="workbench">
|
|
75
|
+
<header class="site-header">
|
|
76
|
+
<a class="brand" href="#main" aria-label="Mono 开发工作台,跳至主要内容">
|
|
77
|
+
<span class="brand-symbol" aria-hidden="true"><span /><span /><span /></span>
|
|
78
|
+
<span class="brand-name">mono<span class="brand-dot">.</span></span>
|
|
79
|
+
<span class="brand-caption">开发工作台</span>
|
|
80
|
+
</a>
|
|
81
|
+
<div class="workspace-tag"><span aria-hidden="true" />Vue · pnpm workspace</div>
|
|
82
|
+
</header>
|
|
83
|
+
|
|
84
|
+
<main id="main">
|
|
85
|
+
<section class="intro" aria-labelledby="page-title">
|
|
86
|
+
<p class="eyebrow">你的下一个项目,从这里开始</p>
|
|
87
|
+
<h1 id="page-title">应用各司其职,<br />代码共同生长。</h1>
|
|
88
|
+
<p class="intro-copy">
|
|
89
|
+
在应用中探索,在共享包中沉淀。这个工作台展示了它们如何连接,也为你的下一步留好了位置。
|
|
90
|
+
</p>
|
|
91
|
+
<a class="text-link" href="#workspace">查看工作区分工 <span aria-hidden="true">↗</span></a>
|
|
92
|
+
</section>
|
|
93
|
+
|
|
94
|
+
<section class="demo-panel" aria-labelledby="demo-title">
|
|
95
|
+
<div class="panel-heading">
|
|
96
|
+
<div>
|
|
97
|
+
<p class="eyebrow">共享包 · 即时演示</p>
|
|
98
|
+
<h2 id="demo-title">把数值留在区间内。</h2>
|
|
99
|
+
</div>
|
|
100
|
+
<code class="package-tag">@bubblesjs/utils</code>
|
|
101
|
+
</div>
|
|
102
|
+
<p class="demo-description">调整数值与上下限,看看 <code>clamp()</code> 如何处理边界。</p>
|
|
103
|
+
|
|
104
|
+
<div class="presets" role="group" aria-label="选择示例数值">
|
|
105
|
+
<button v-for="preset in presets" :key="preset.value" type="button" :aria-pressed="Number(inputValue) === preset.value &&
|
|
106
|
+
Number(minimum) === 0 &&
|
|
107
|
+
Number(maximum) === 100
|
|
108
|
+
" @click="selectPreset(preset.value)">
|
|
109
|
+
{{ preset.label }}
|
|
110
|
+
</button>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<div class="number-fields">
|
|
114
|
+
<div class="number-field input-field">
|
|
115
|
+
<label for="value">输入值 <span>value</span></label>
|
|
116
|
+
<input id="value" v-model="inputValue" type="number" min="-1000" max="1000" step="any"
|
|
117
|
+
:aria-invalid="!isValidNumber(inputValue)" aria-describedby="demo-help demo-error" />
|
|
118
|
+
</div>
|
|
119
|
+
<div class="number-field">
|
|
120
|
+
<label for="minimum">下限 <span>min</span></label>
|
|
121
|
+
<input id="minimum" v-model="minimum" type="number" min="-1000" max="1000" step="any"
|
|
122
|
+
:aria-invalid="!isValidNumber(minimum) || Number(minimum) > Number(maximum)"
|
|
123
|
+
aria-describedby="demo-help demo-error" />
|
|
124
|
+
</div>
|
|
125
|
+
<div class="number-field">
|
|
126
|
+
<label for="maximum">上限 <span>max</span></label>
|
|
127
|
+
<input id="maximum" v-model="maximum" type="number" min="-1000" max="1000" step="any"
|
|
128
|
+
:aria-invalid="!isValidNumber(maximum) || Number(minimum) > Number(maximum)"
|
|
129
|
+
aria-describedby="demo-help demo-error" />
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
<p id="demo-help" class="field-help">
|
|
133
|
+
支持 −1000 到 1000,可输入小数;下限应小于或等于上限。
|
|
134
|
+
</p>
|
|
135
|
+
<p id="demo-error" class="field-error" role="status">
|
|
136
|
+
{{ error }}
|
|
137
|
+
</p>
|
|
138
|
+
|
|
139
|
+
<div class="ruler" aria-hidden="true">
|
|
140
|
+
<div v-if="!error" class="allowed-range" :style="{
|
|
141
|
+
left: position(minimum),
|
|
142
|
+
width: `${Number.parseFloat(position(maximum)) - Number.parseFloat(position(minimum))}%`,
|
|
143
|
+
}" />
|
|
144
|
+
<div class="ruler-line" />
|
|
145
|
+
<div v-for="tick in ticks" :key="tick.position" class="ruler-tick" :style="{ left: tick.position }">
|
|
146
|
+
<span>{{ tick.label }}</span>
|
|
147
|
+
</div>
|
|
148
|
+
<div v-if="!error" class="input-marker" :style="{ left: position(inputValue) }">
|
|
149
|
+
<span>输入 {{ inputValue }}</span><i />
|
|
150
|
+
</div>
|
|
151
|
+
<div v-if="result !== null" class="result-marker" :style="{ left: position(result) }">
|
|
152
|
+
<i /><span>结果 {{ displayNumber(result) }}</span>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<div class="result-row" aria-live="polite" aria-atomic="true">
|
|
157
|
+
<div>
|
|
158
|
+
<span class="result-label">返回值</span><output for="value minimum maximum">{{
|
|
159
|
+
result === null ? "—" : displayNumber(result)
|
|
160
|
+
}}</output>
|
|
161
|
+
</div>
|
|
162
|
+
<p>{{ resultHint }}</p>
|
|
163
|
+
</div>
|
|
164
|
+
<div class="code-line">
|
|
165
|
+
<code>clamp({{ inputValue === "" ? "value" : inputValue }},
|
|
166
|
+
{{ minimum === "" ? "min" : minimum }}, {{ maximum === "" ? "max" : maximum }})</code><span>来自共享包源码</span>
|
|
167
|
+
</div>
|
|
168
|
+
</section>
|
|
169
|
+
|
|
170
|
+
<section id="workspace" class="workspace-section" aria-labelledby="workspace-title">
|
|
171
|
+
<div class="section-heading">
|
|
172
|
+
<h2 id="workspace-title">一个仓库,清楚的分工。</h2>
|
|
173
|
+
<p>应用消费包,配置统一管理。</p>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="workspace-grid">
|
|
176
|
+
<article class="workspace-item">
|
|
177
|
+
<span class="folder-label">apps/</span>
|
|
178
|
+
<h3>让想法可见</h3>
|
|
179
|
+
<p>Playground 用来交互演示,Docs 用来记录约定。应用通过工作区依赖连接共享包。</p>
|
|
180
|
+
<code>playground · docs</code>
|
|
181
|
+
</article>
|
|
182
|
+
<article class="workspace-item">
|
|
183
|
+
<span class="folder-label">packages/</span>
|
|
184
|
+
<h3>让代码可复用</h3>
|
|
185
|
+
<p>把通用逻辑放进独立包,按需构建、测试与发布。上方的数值示例就来自这里。</p>
|
|
186
|
+
<code>@bubblesjs/utils</code>
|
|
187
|
+
</article>
|
|
188
|
+
<article class="workspace-item">
|
|
189
|
+
<span class="folder-label">tsconfig/</span>
|
|
190
|
+
<h3>让约定保持一致</h3>
|
|
191
|
+
<p>集中维护 TypeScript 配置。格式、检查与任务编排由根目录统一管理。</p>
|
|
192
|
+
<code>tsconfig</code>
|
|
193
|
+
</article>
|
|
194
|
+
</div>
|
|
195
|
+
</section>
|
|
196
|
+
|
|
197
|
+
<section class="next-step" aria-labelledby="next-title">
|
|
198
|
+
<div>
|
|
199
|
+
<p class="eyebrow">接下来</p>
|
|
200
|
+
<h2 id="next-title">从一个共享函数开始。</h2>
|
|
201
|
+
<p>编辑 <code>packages/utils/src/index.ts</code>,回到这里查看变化。</p>
|
|
202
|
+
</div>
|
|
203
|
+
<div class="command-list">
|
|
204
|
+
<div><span>运行工作台</span><code>pnpm dev</code></div>
|
|
205
|
+
<div><span>检查整个仓库</span><code>pnpm check</code></div>
|
|
206
|
+
</div>
|
|
207
|
+
</section>
|
|
208
|
+
</main>
|
|
209
|
+
|
|
210
|
+
<footer class="site-footer">
|
|
211
|
+
<span>少一点重复,多一点专注。</span><span>MONOREPO STARTER / PLAYGROUND</span>
|
|
212
|
+
</footer>
|
|
213
|
+
</div>
|
|
214
|
+
</template>
|