@farris/cli 2.3.7 → 2.3.8

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.
Files changed (103) hide show
  1. package/lib/commands/add-app.js +1 -1
  2. package/lib/commands/add-app.js.map +1 -1
  3. package/lib/commands/add-lib.js +1 -1
  4. package/lib/commands/add-lib.js.map +1 -1
  5. package/lib/commands/add-micro.js +12 -0
  6. package/lib/commands/add-micro.js.map +1 -0
  7. package/lib/commands/add-project.js +12 -10
  8. package/lib/commands/add-project.js.map +1 -1
  9. package/lib/commands/build-components.js +2 -2
  10. package/lib/commands/build-components.js.map +1 -1
  11. package/lib/commands/build-lib.js +1 -1
  12. package/lib/commands/build-lib.js.map +1 -1
  13. package/lib/commands/create-app-options.js +14 -3
  14. package/lib/commands/create-app-options.js.map +1 -1
  15. package/lib/commands/create-options.js +36 -10
  16. package/lib/commands/create-options.js.map +1 -1
  17. package/lib/commands/create.js +21 -11
  18. package/lib/commands/create.js.map +1 -1
  19. package/lib/commands/workspace/create.js +2 -2
  20. package/lib/commands/workspace/create.js.map +1 -1
  21. package/lib/common/constant.js +1 -1
  22. package/lib/common/constant.js.map +1 -1
  23. package/lib/common/generate-app.js +3 -6
  24. package/lib/common/generate-app.js.map +1 -1
  25. package/lib/common/project-layout.js +33 -61
  26. package/lib/common/project-layout.js.map +1 -1
  27. package/lib/common/safety.js +2 -3
  28. package/lib/common/safety.js.map +1 -1
  29. package/lib/common/template-manifest.js +4 -0
  30. package/lib/common/template-manifest.js.map +1 -1
  31. package/lib/common/verifier.js +21 -35
  32. package/lib/common/verifier.js.map +1 -1
  33. package/lib/common/workspace-contract.js +57 -23
  34. package/lib/common/workspace-contract.js.map +1 -1
  35. package/lib/config/vite-lib.js +1 -1
  36. package/lib/config/vite-lib.js.map +1 -1
  37. package/lib/index.js +33 -10
  38. package/lib/index.js.map +1 -1
  39. package/package.json +1 -1
  40. package/templates/create/.gitignore.tpl +28 -8
  41. package/templates/create/AGENTS.md +75 -45
  42. package/templates/create/README.md +44 -11
  43. package/templates/create/package.json +2 -1
  44. package/templates/lib/.gitignore.tpl +31 -1
  45. package/templates/lib/.gitlab-ci.yml +2 -2
  46. package/templates/lib/README.md +24 -1
  47. package/templates/lib/{test → components/__tests__}/index.spec.ts +1 -1
  48. package/templates/lib/{test → components/__tests__}/index.spec.tsx +2 -2
  49. package/templates/lib/farris.config.mjs +2 -2
  50. package/templates/lib/package.json +1 -1
  51. package/templates/lib/tsconfig.json +1 -2
  52. package/templates/lib/vitest.config.ts +4 -2
  53. package/templates/micro/.eslintrc.cjs +15 -0
  54. package/templates/micro/.gitignore.tpl +33 -0
  55. package/templates/micro/.gitlab-ci.yml +59 -0
  56. package/templates/micro/.prettierrc.json +8 -0
  57. package/templates/micro/farris.config.mjs +34 -0
  58. package/templates/micro/index.html +12 -0
  59. package/templates/micro/mock/README.md +40 -0
  60. package/templates/micro/package.json +46 -0
  61. package/templates/micro/src/App.tsx +25 -0
  62. package/templates/micro/src/locales/index.ts +5 -0
  63. package/templates/micro/src/locales/zh-CHS.json +1 -0
  64. package/templates/micro/src/main.ts +47 -0
  65. package/templates/micro/src/router/index.ts +24 -0
  66. package/templates/micro/src/views/AboutView.tsx +12 -0
  67. package/templates/micro/src/views/HomeView.tsx +13 -0
  68. package/templates/micro/src/views/__tests__/AboutView.spec.tsx +11 -0
  69. package/templates/micro/src/views/__tests__/HomeView.spec.tsx +11 -0
  70. package/templates/micro/tsconfig.json +18 -0
  71. package/templates/micro/vitest.config.ts +12 -0
  72. package/templates/mobile/.gitignore.tpl +25 -24
  73. package/templates/mobile/farris.config.mjs +2 -2
  74. package/templates/mobile/mock/README.md +10 -4
  75. package/templates/mobile/package.json +4 -2
  76. package/templates/mobile/src/main.ts +5 -40
  77. package/templates/mobile/src/views/HomeView.tsx +2 -2
  78. package/templates/mobile/src/views/__tests__/AboutView.spec.tsx +11 -0
  79. package/templates/mobile/src/views/__tests__/HomeView.spec.tsx +11 -0
  80. package/templates/mobile/tsconfig.json +1 -2
  81. package/templates/mobile/vitest.config.ts +4 -2
  82. package/templates/web/.gitignore.tpl +25 -24
  83. package/templates/web/farris.config.mjs +2 -2
  84. package/templates/web/mock/README.md +10 -4
  85. package/templates/web/package.json +4 -2
  86. package/templates/web/src/App.tsx +0 -4
  87. package/templates/web/src/main.ts +5 -40
  88. package/templates/web/src/views/HomeView.tsx +2 -2
  89. package/templates/web/src/views/__tests__/AboutView.spec.tsx +11 -0
  90. package/templates/web/src/views/__tests__/HomeView.spec.tsx +11 -0
  91. package/templates/web/tsconfig.json +1 -2
  92. package/templates/web/vitest.config.ts +4 -2
  93. package/templates/mobile/src/components/TheButton.tsx +0 -9
  94. package/templates/mobile/test/src/components/TheButton.spec.ts +0 -15
  95. package/templates/mobile/test/src/components/TheButton.spec.tsx +0 -15
  96. package/templates/web/src/components/TheButton.tsx +0 -9
  97. package/templates/web/src/micro-app.d.ts +0 -20
  98. package/templates/web/src/styles/index.css +0 -0
  99. package/templates/web/test/src/components/TheButton.spec.ts +0 -15
  100. package/templates/web/test/src/components/TheButton.spec.tsx +0 -15
  101. /package/templates/{web → micro}/src/micro/context.ts +0 -0
  102. /package/templates/{mobile → micro}/src/micro-app.d.ts +0 -0
  103. /package/templates/{mobile/src/styles/index.css → micro/src/styles/index.scss} +0 -0
@@ -1,32 +1,33 @@
1
- # Logs
2
- logs
3
- *.log
4
- npm-debug.log*
5
- yarn-debug.log*
6
- yarn-error.log*
7
- pnpm-debug.log*
8
- lerna-debug.log*
1
+ # 依赖与产物
2
+ node_modules/
3
+ dist/
4
+ dist-es/
5
+ dist-ssr/
6
+ coverage/
7
+ *.tsbuildinfo
8
+ .pnpm-store/
9
9
 
10
- node_modules
11
- package-lock.json
10
+ # 日志与本地文件
11
+ *.log
12
12
  .DS_Store
13
- dist
14
- dist-es
15
- dist-ssr
16
- coverage
17
13
  *.local
14
+ .env
15
+ .env.*
16
+ !.env.example
17
+ package-lock.json
18
18
 
19
- /cypress/videos/
20
- /cypress/screenshots/
21
-
22
- # Editor directories and files
19
+ # 编辑器
23
20
  .vscode/*
24
21
  !.vscode/extensions.json
25
- .idea
26
- *.suo
27
- *.ntvs*
28
- *.njsproj
29
- *.sln
22
+ !.vscode/settings.json
23
+ .idea/
24
+ .history
30
25
  *.sw?
31
26
 
32
- *.tsbuildinfo
27
+ # AI 工具
28
+ .codebuddy/
29
+ .cursor/
30
+ .claude/
31
+ .windsurf/
32
+ .trae/
33
+ .opencode/
@@ -4,9 +4,9 @@ export default {
4
4
  // 相对路径 base:微前端(IBP)与 iframe 嵌入场景都适用
5
5
  base: './',
6
6
  routerMode: 'hash',
7
- // iife: IBP 微前端单文件产物(默认);如需普通 ESM 站点产物,执行 pnpm build:es
7
+ // 默认交付格式;pnpm build 会依次产出 es / umd / systemjs(iife 见 --format iife)
8
8
  format: "<%= format %>",
9
- // 输出目录 App模式默认值 './dist' Lib模式 './lib'
9
+ // 输出目录 App/Lib 模式默认值均为 './dist'
10
10
  // outDir: fileURLToPath(new URL('./dist', import.meta.url)),
11
11
  // 最小化 默认值 true
12
12
  minify: true,
@@ -17,7 +17,14 @@ export default [
17
17
  ];
18
18
  ```
19
19
 
20
- 规则:
20
+ ## 加一条 mock 并验证
21
+
22
+ 1. 先在 `src/api/` 里确认请求路径(例如 `/api/v1/users`),逐字抄进 `url`。
23
+ 2. 新建或追加 `mock/<领域>.mock.ts`,按上面的形状写 `url` / `method` / `response`。
24
+ 3. 在工程目录执行 `pnpm dev`,打开用到该接口的页面,**验证**返回的是 mock 数据。
25
+ 4. 需要联调真实后端时:`pnpm dev --no-mock`(或 `MOCK=none pnpm dev`),业务代码不改。
26
+
27
+ ## 规则
21
28
 
22
29
  - url 必须与代码中的请求路径逐字一致,见 `src/api/` 下的接口模块。
23
30
  - 路径参数在 url 里用 `:参数名` 表示,例如 `/api/v1/users/:id`;查询参数不写进 url,在 response 的 `query` 里读取。
@@ -25,10 +32,9 @@ export default [
25
32
  - 同一 url 不允许在多个 mock 文件中重复定义,重复时开发服务启动即报错。
26
33
  - mock 只用于开发期:不进构建产物,也不要在组件里散落假数据。
27
34
 
28
- 行为:
35
+ ## 行为与开关
29
36
 
30
37
  - 命中 mock → 返回 mock 数据。
31
38
  - 未命中 → 按 `farris.config.mjs` 的 `proxy` 配置转发真实后端。
32
39
  - 未命中且未配代理的 `/api` 路径 → 返回 404 并提示,便于排查漏配。
33
-
34
- 开关:在工程目录执行 `pnpm dev` 默认生效;`pnpm dev --no-mock` 或 `MOCK=none pnpm dev` 进入真实后端联调。
40
+ - 开关:工程目录内 `pnpm dev` 默认生效;`pnpm dev --no-mock` 或 `MOCK=none pnpm dev` 进真实后端联调。
@@ -5,8 +5,10 @@
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "farris-cli dev",
8
- "build": "farris-cli build -ep",
9
- "build:es": "farris-cli build --format es --outDir dist-es",
8
+ "build": "pnpm run build:es && pnpm run build:umd && pnpm run build:systemjs",
9
+ "build:es": "farris-cli build -ep --format es",
10
+ "build:umd": "farris-cli build -ep --format umd --outDir dist-umd",
11
+ "build:systemjs": "farris-cli build -ep --format systemjs --outDir dist-systemjs",
10
12
  "preview": "farris-cli preview",
11
13
  "test": "vitest run",
12
14
  "test:watch": "vitest",
@@ -1,13 +1,9 @@
1
1
  import { defineComponent } from 'vue';
2
2
  import { RouterLink, RouterView } from 'vue-router';
3
- import { setupMicroAppContext } from './micro/context';
4
3
 
5
4
  export default defineComponent({
6
5
  name: 'App',
7
6
  setup() {
8
- // 微前端环境:订阅主应用下发的上下文(语言 / 主题)
9
- setupMicroAppContext();
10
-
11
7
  return () => (
12
8
  <>
13
9
  <header>
@@ -1,47 +1,12 @@
1
- import { createApp, type App as VueApp } from 'vue';
1
+ import { createApp } from 'vue';
2
2
  import FarrisVue from '@farris/ui-vue';
3
3
  import '@farris/ui-vue/index.css';
4
4
  import App from './App';
5
5
  import router from './router';<%= styleImport %>
6
6
  import { localResources } from './locales';
7
7
 
8
- let app: VueApp | null = null;
8
+ const app = createApp(App);
9
9
 
10
- /** 挂载应用(微前端宿主会调用 window.mount) */
11
- function mount(): void {
12
- if (app) {
13
- return;
14
- }
15
- app = createApp(App);
16
- app.use(FarrisVue, { basePath: '', locale: 'zh-CHS', localResources });
17
- app.use(router);
18
- app.mount('#app');
19
-
20
- // 微前端环境:按平台下发的 initialPath 定位菜单配置的页面(fullPath)
21
- // hash 路由必须保留这段兜底;history 路由下平台 defaultPage 已能直接命中,这里是幂等兜底
22
- if (window.__MICRO_APP_ENVIRONMENT__) {
23
- const rawPath = window.microApp?.getData?.()?.initialPath;
24
- if (typeof rawPath === 'string' && rawPath !== '') {
25
- // 平台下发的 initialPath 通常不带前导斜杠(如 'form'),这里统一归一化
26
- const initialPath = rawPath.startsWith('/') ? rawPath : '/' + rawPath;
27
- if (initialPath !== '/') {
28
- router.isReady().then(() => router.replace(initialPath)).catch(() => undefined);
29
- }
30
- }
31
- }
32
- }
33
-
34
- /** 卸载应用(微前端宿主会调用 window.unmount) */
35
- function unmount(): void {
36
- app?.unmount();
37
- app = null;
38
- }
39
-
40
- // 微前端(micro-app)生命周期契约:必须暴露到 window
41
- window.mount = mount;
42
- window.unmount = unmount;
43
-
44
- // 独立运行(浏览器直接访问 / iframe 嵌入)时自动挂载
45
- if (!window.__MICRO_APP_ENVIRONMENT__) {
46
- mount();
47
- }
10
+ app.use(FarrisVue, { basePath: '', locale: 'zh-CHS', localResources });
11
+ app.use(router);
12
+ app.mount('#app');
@@ -1,12 +1,12 @@
1
1
  import { defineComponent } from 'vue';
2
- import TheButton from '../components/TheButton';
3
2
 
4
3
  export default defineComponent({
5
4
  name: 'HomeView',
6
5
  setup() {
7
6
  return () => (
8
7
  <main>
9
- <TheButton />
8
+ <h1>Home</h1>
9
+ <p>在 src/views/ 下新增页面;通用组件按需创建在 src/components/ 下。</p>
10
10
  </main>
11
11
  );
12
12
  }
@@ -0,0 +1,11 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, expect, it } from 'vitest';
3
+ import AboutView from '../AboutView';
4
+
5
+ describe('AboutView', () => {
6
+ it('mounts', () => {
7
+ const wrapper = mount(AboutView);
8
+
9
+ expect(wrapper.exists()).toBe(true);
10
+ });
11
+ });
@@ -0,0 +1,11 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, expect, it } from 'vitest';
3
+ import HomeView from '../HomeView';
4
+
5
+ describe('HomeView', () => {
6
+ it('mounts', () => {
7
+ const wrapper = mount(HomeView);
8
+
9
+ expect(wrapper.exists()).toBe(true);
10
+ });
11
+ });
@@ -3,8 +3,7 @@
3
3
  "include": [
4
4
  "env.d.ts",
5
5
  "src/**/*",
6
- "src/**/*.vue",
7
- "test/**/*"
6
+ "src/**/*.vue"
8
7
  ],
9
8
  "compilerOptions": {
10
9
  "composite": true,
@@ -1,10 +1,12 @@
1
1
  import vue from '@vitejs/plugin-vue';
2
- import { defineConfig } from 'vitest/config';
2
+ import { configDefaults, defineConfig } from 'vitest/config';
3
3
 
4
4
  export default defineConfig({
5
5
  plugins: [vue()],
6
6
  test: {
7
7
  environment: 'jsdom',
8
- include: ['test/**/*.spec.{ts,tsx}']
8
+ // 官方默认收集范围(**/*.{test,spec}.*),源码旁的测试才会被收集
9
+ include: [...configDefaults.include],
10
+ exclude: [...configDefaults.exclude, '**/__sandbox_*/**']
9
11
  }
10
12
  });
@@ -1,9 +0,0 @@
1
- import { defineComponent } from 'vue';
2
- import { Button } from '@farris/mobile-ui-vue';
3
-
4
- export default defineComponent({
5
- name: 'TheButton',
6
- setup() {
7
- return () => <Button>按钮</Button>;
8
- }
9
- });
@@ -1,15 +0,0 @@
1
- import { mount } from '@vue/test-utils';
2
- import { describe, expect, it } from 'vitest';
3
- import TheButton from '../../../src/components/TheButton';
4
-
5
- describe('TheButton', () => {
6
- it('mounts and renders its default slot', () => {
7
- const wrapper = mount(TheButton, {
8
- global: {
9
- stubs: { FmButton: { template: '<button><slot /></button>' } }
10
- }
11
- });
12
-
13
- expect(wrapper.text()).toContain('按钮');
14
- });
15
- });
@@ -1,15 +0,0 @@
1
- import { mount } from '@vue/test-utils';
2
- import { describe, expect, it } from 'vitest';
3
- import TheButton from '../../../src/components/TheButton';
4
-
5
- describe('TheButton (tsx collection)', () => {
6
- it('is collected by the unified vitest include', () => {
7
- const wrapper = mount(TheButton, {
8
- global: {
9
- stubs: { FmButton: { template: '<button><slot /></button>' } }
10
- }
11
- });
12
-
13
- expect(wrapper.text()).toContain('按钮');
14
- });
15
- });
@@ -1,9 +0,0 @@
1
- import { defineComponent } from 'vue';
2
- import { FButton } from '@farris/ui-vue';
3
-
4
- export default defineComponent({
5
- name: 'TheButton',
6
- setup() {
7
- return () => <FButton>按钮</FButton>;
8
- }
9
- });
@@ -1,20 +0,0 @@
1
- export {};
2
-
3
- declare global {
4
- interface Window {
5
- /** micro-app 子应用环境标记(由宿主注入) */
6
- __MICRO_APP_ENVIRONMENT__?: boolean;
7
- /** 宿主注入的 micro-app API */
8
- microApp?: {
9
- addGlobalDataListener?: (callback: (data: any) => void, immediately?: boolean) => void;
10
- setGlobalData?: (data: Record<string, any>) => void;
11
- getData?: () => Record<string, any> | null;
12
- router?: {
13
- getBaseAppRouter?: () => any;
14
- };
15
- };
16
- /** 微前端生命周期:宿主会调用这两个方法 */
17
- mount?: () => void;
18
- unmount?: () => void;
19
- }
20
- }
File without changes
@@ -1,15 +0,0 @@
1
- import { mount } from '@vue/test-utils';
2
- import { describe, expect, it } from 'vitest';
3
- import TheButton from '../../../src/components/TheButton';
4
-
5
- describe('TheButton', () => {
6
- it('mounts and renders its default slot', () => {
7
- const wrapper = mount(TheButton, {
8
- global: {
9
- stubs: { FButton: { template: '<button><slot /></button>' } }
10
- }
11
- });
12
-
13
- expect(wrapper.text()).toContain('按钮');
14
- });
15
- });
@@ -1,15 +0,0 @@
1
- import { mount } from '@vue/test-utils';
2
- import { describe, expect, it } from 'vitest';
3
- import TheButton from '../../../src/components/TheButton';
4
-
5
- describe('TheButton (tsx collection)', () => {
6
- it('is collected by the unified vitest include', () => {
7
- const wrapper = mount(TheButton, {
8
- global: {
9
- stubs: { FButton: { template: '<button><slot /></button>' } }
10
- }
11
- });
12
-
13
- expect(wrapper.text()).toContain('按钮');
14
- });
15
- });
File without changes
File without changes