diff --git a/.buildrc.ts b/.buildrc.ts
new file mode 100644
index 000000000..da97ca26e
--- /dev/null
+++ b/.buildrc.ts
@@ -0,0 +1,12 @@
+export default {
+ target: 'node',
+ cjs: { type: 'babel', lazy: true },
+ excludePkgs: [
+ 'core/build',
+ 'core/cli',
+ 'core/create-nocobase-app',
+ 'core/devtools',
+ 'core/dumi-theme-nocobase',
+ 'app/client',
+ ],
+};
diff --git a/.env.example b/.env.example
index 1aadcc4d5..2cf38ae16 100644
--- a/.env.example
+++ b/.env.example
@@ -7,17 +7,14 @@ VERDACCIO_PORT=10104
################# NOCOBASE APPLICATION #################
-NOCOBASE_ENV=development
+APP_ENV=development
+APP_PORT=13000
+APP_KEY=test-key
-SERVER_PORT=3000
+API_BASE_PATH=/api/
+API_BASE_URL=
-# api base path endpoint for app(web)
-SERVER_BASE_PATH=/api/
-
-# api server access point for app(web when build)
-SERVER_BASE_URL=
-
-JWT_SECRET=09f26e402586e2faa8da4c98a35f1b20d6b033c60
+PROXY_TARGET_URL=
################# DATABASE #################
@@ -28,15 +25,18 @@ DB_STORAGE=storage/db/nocobase.sqlite
# DB_DATABASE=postgres
# DB_USER=nocobase
# DB_PASSWORD=nocobase
-# DB_LOG_SQL=on
+# DB_LOGGING=on
################# STORAGE (Initialization only) #################
+INIT_ROOT_EMAIL=admin@nocobase.com
+INIT_ROOT_PASSWORD=admin123
+INIT_ROOT_NICKNAME=Super Admin
+
# local or ali-oss
DEFAULT_STORAGE_TYPE=local
# LOCAL STORAGE
-LOCAL_STORAGE_USE_STATIC_SERVER=true
LOCAL_STORAGE_BASE_URL=
LOCAL_STORAGE_DEST=storage/uploads
diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml
index cd291ff30..7471eb082 100644
--- a/.github/workflows/node-ci.yml
+++ b/.github/workflows/node-ci.yml
@@ -40,10 +40,9 @@ jobs:
node-version: ${{ matrix.node_version }}
cache: 'yarn'
- run: yarn install
- - run: yarn bootstrap
- run: yarn build
- name: Test with postgres
- run: yarn test -i
+ run: yarn test
env:
DB_DIALECT: postgres
DB_HOST: postgres
@@ -52,12 +51,12 @@ jobs:
DB_PASSWORD: password
DB_DATABASE: nocobase
- name: Test with Sqlite
- run: yarn test -i
+ run: yarn test
env:
DB_DIALECT: sqlite
DB_STORAGE: /tmp/db.sqlite
- name: Test with MySQL
- run: yarn test -i
+ run: yarn test
env:
DB_DIALECT: mysql
DB_HOST: mysql
diff --git a/.gitignore b/.gitignore
index 550a49e9b..315ab3b4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
node_modules/
lib/
-!packages/core/create-nocobase-app/lib
esm/
+es/
.env
.DS_Store
yarn-error.log
diff --git a/.umirc.ts b/.umirc.ts
index bd2a7be7b..d1fae6822 100644
--- a/.umirc.ts
+++ b/.umirc.ts
@@ -1,14 +1,103 @@
+import transformer from '@umijs/preset-dumi/lib/transformer';
import { defineConfig } from 'dumi';
+import fs from 'fs';
+import path from 'path';
+import menus from './docs/menus';
+
+const lang = process.env.DOC_LANG || 'en-US';
+
+console.log('process.env.DOC_LANG', process.env.DOC_LANG);
+
+const findFilePath = (filename, lang) => {
+ const filePath = path.resolve(__dirname, `docs/${lang}/${filename}`);
+ if (fs.existsSync(`${filePath}.md`)) {
+ return `${filePath}.md`;
+ }
+ return;
+};
+
+const markdown = (filename, lang) => {
+ const filePath = findFilePath(filename, lang);
+ if (!filePath) {
+ return;
+ }
+ return transformer.markdown(fs.readFileSync(filePath, 'utf8').toString(), filePath);
+};
+
+const getPath = (value: string) => {
+ if (!value) {
+ return '';
+ }
+ const keys = value.split('/');
+ if (keys.pop() === 'index') {
+ return keys.join('/') || '/';
+ }
+ return value;
+};
+
+const getTitle = (item, lang) => {
+ if (lang) {
+ return item[`title.${lang}`] || item.title;
+ }
+ return item.title;
+};
+
+const parseMenuItems = (items, lang = null) => {
+ const menuItems = [];
+ for (const item of items) {
+ if (typeof item === 'string') {
+ const result = markdown(item, lang);
+ if (result) {
+ menuItems.push({
+ title: result.meta.title,
+ disabled: result.meta.disabled,
+ path: getPath(item),
+ });
+ }
+ } else if (item.children) {
+ menuItems.push({
+ ...item,
+ title: getTitle(item, lang),
+ children: parseMenuItems(item.children, lang),
+ });
+ } else if (item.path) {
+ menuItems.push({
+ ...item,
+ title: getTitle(item, lang),
+ path: getPath(item.path),
+ });
+ } else {
+ menuItems.push({
+ title: getTitle(item, lang),
+ ...item,
+ });
+ }
+ }
+ return menuItems;
+};
export default defineConfig({
title: 'NocoBase',
- favicon: 'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png',
- logo: 'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png',
- outputPath: 'docs-dist',
+ outputPath: `./docs/dist/${lang}`,
mode: 'site',
resolve: {
- includes: ['docs', 'packages/client'],
+ includes: [`./docs/${lang}`],
},
+ locales: [[lang, lang]],
hash: true,
- // more config: https://d.umijs.org/config
+ logo: 'https://www.nocobase.com/images/logo.png',
+ navs: [
+ {
+ title: 'Docs',
+ path: '/',
+ hidden: true,
+ },
+ {
+ title: 'GitHub',
+ path: 'https://github.com/nocobase/nocobase',
+ },
+ ],
+ menus: {
+ '/': parseMenuItems(menus, lang),
+ },
});
diff --git a/README.md b/README.md
index f8ff8f6c4..f87157edf 100644
--- a/README.md
+++ b/README.md
@@ -64,172 +64,16 @@ NocoBase is designed for you if you have the following needs.
## Installation
-NocoBase supports both Docker and CLI installation methods. Docker is recommended if you are new to NocoBase.
+NocoBase supports three installation methods:
-### Docker (👍Recommended)
+- Installing With Docker (👍Recommended)
-#### 0. Before start
+ Suitable for no-code scenarios, no code to write. When upgrading, just download the latest image and reboot.
-⚡⚡ Please make sure you have installed [Docker](https://docs.docker.com/get-docker/)
+- Installing from create-nocobase-app CLI
-#### 1. Download NocoBase
+ The business code of the project is completely independent and supports low-code development.
-Download with Git (or Download Zip,and extract it to the nocobase directory)
+- Installing from Git source code
-```bash
-git clone https://github.com/nocobase/nocobase.git nocobase
-```
-
-#### 2. Select database (choose one)
-
-Supports SQLite, MySQL, PostgreSQL
-
-```bash
-# SQLite
-cd nocobase/docker/app-sqlite
-# MySQL
-cd nocobase/docker/app-mysql
-# PostgreSQL
-cd nocobase/docker/app-postgres
-```
-
-#### 3. Install and start NocoBase
-
-It may take dozens of seconds
-
-```bash
-# run in the background
-$ docker-compose up -d
-# view app logs
-$ docker-compose logs app
-
-app-sqlite-app-1 | nginx started
-app-sqlite-app-1 | yarn run v1.22.15
-app-sqlite-app-1 | $ cross-env DOTENV_CONFIG_PATH=.env node -r dotenv/config packages/app/server/lib/index.js install -s
-app-sqlite-app-1 | Done in 2.72s.
-app-sqlite-app-1 | yarn run v1.22.15
-app-sqlite-app-1 | $ pm2-runtime start --node-args="-r dotenv/config" packages/app/server/lib/index.js -- start
-app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: Launching in no daemon mode
-app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] starting in -fork mode-
-app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] online
-app-sqlite-app-1 | 🚀 NocoBase server running at: http://localhost:13000/
-```
-
-#### 4. Log in to NocoBase
-
-Open [http://localhost:13000](http://localhost:13000) in a web browser. The initial account and password are `admin@nocobase.com` and `admin123`.
-
-
-### CLI
-
-#### 0. Before start
-
-Please make sure you have Node.js 12.x or above installed. You can download and install the latest LTS version from the official website. It is recommended to use nvm (or nvm-windows for Win systems) to manage Node.js versions if you plan to work with Node.js for a long time.
-
-```bash
-$ node -v
-
-v16.13.2
-```
-
-yarn package manager is recommend.
-
-```bash
-$ npm install --global yarn
-$ yarn -v
-
-1.22.10
-```
-
-Also, make sure you have configured and started the required database, which supports SQLite, MySQL, PostgreSQL.
-
-#### 1. Create a NocoBase project
-
-```bash
-# SQLite
-yarn create nocobase-app my-nocobase-app -d sqlite
-# MySQL
-yarn create nocobase-app my-nocobase-app -d mysql \
- -e DB_HOST=localhost \
- -e DB_PORT=3356 \
- -e DB_DATABASE=nocobase \
- -e DB_USER=nocobase \
- -e DB_PASSWORD=nocobase
-# PostgreSQL
-yarn create nocobase-app my-nocobase-app -d postgres \
- -e DB_HOST=localhost \
- -e DB_PORT=5432 \
- -e DB_DATABASE=nocobase \
- -e DB_USER=nocobase \
- -e DB_PASSWORD=nocobase
-```
-
-#### 2. Switch to the project directory
-
-```bash
-cd my-nocobase-app
-```
-
-#### 3. Install dependencies
-
-```bash
-yarn install
-```
-
-#### 4. Install & Start NocoBase
-
-```bash
-yarn nocobase install --lang=en-US
-yarn start
-```
-
-#### 5. Log in to NocoBase
-
-Open [http://localhost:8000](http://localhost:8000) in a web browser. The initial account and password are `admin@nocobase.com` and `admin123`.
-
-## Contributing
-
-- Fork the source code to your own repository
-- Modify source code
-- Submit pull request
-
-### Download
-
-```bash
-# Replace the following git address with your own repo
-git clone https://github.com/nocobase/nocobase.git
-cd nocobase
-cp .env.example .env
-yarn install
-```
-
-### Development and Testing
-
-```bash
-# Install NocoBase
-yarn nocobase install --lang=en-US
-# Start NocoBase
-yarn start
-# Run all tests
-yarn test
-# Run all test files in the folder
-yarn test
-# Run a single test file
-yarn test
-```
-
-### Documentation preview
-
-```bash
-# Start documentation
-yarn doc --lang=zh-CN
-yarn doc --lang=en-US
-```
-
-The documentation is in the docs directory and follows Markdown syntax
-
-```bash
-|- /docs/
- |- en-US
- |- zh-CN
-```
+ If you want to experience the latest unreleased version, or want to participate in the contribution, you need to make changes and debug on the source code, it is recommended to choose this installation method, which requires a high level of development skills, and if the code has been updated, you can git pull the latest code.
diff --git a/README.zh-CN.md b/README.zh-CN.md
index c6aa3cc6c..1cde97daa 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -2,8 +2,8 @@
![](https://www.nocobase.com/images/demo/11.png)
-NocoBase 是什么
-----------
+## NocoBase 是什么
+
NocoBase 是一个极易扩展的开源无代码开发平台。
无需编程,使用 NocoBase 搭建自己的协作平台、管理系统,只需要几分钟时间。
@@ -13,6 +13,9 @@ https://cn.nocobase.com/
在线体验:
https://demo-cn.nocobase.com/new
+文档:
+https://docs-cn.nocobase.com/
+
## 适用场景
如果你有以下需求,NocoBase 就是为你设计的:
@@ -24,8 +27,8 @@ https://demo-cn.nocobase.com/new
- 私有部署,掌控全部代码和数据
- 可免费使用,也可以付费获得更多技术支持
-为什么选择 NocoBase
-----------
+## 为什么选择 NocoBase
+
- **开源免费**
- 采用 Apache-2.0 许可协议,不限制商业使用
- 拥有全部代码,私有化部署,保障数据私有和安全
@@ -50,14 +53,13 @@ https://demo-cn.nocobase.com/new
- 渐进式开发,上手难度低,对新人友好
- 不绑架、不强依赖,可任意组合使用或扩展,可用于现有项目中
-NocoBase 架构
-----------
+## NocoBase 架构
+
![](https://www.nocobase.com/images/NocoBaseMindMapLite.png)
[点此查看完整图片](https://www.nocobase.com/images/NocoBaseMindMap.png)
-联系
-----------
+## 联系
如果你希望加入我们一起开发 NocoBase,或者需要提供商业服务,欢迎通过邮件联系我们:hello@nocobase.com
@@ -67,180 +69,16 @@ NocoBase 架构
## 安装
-NocoBase 支持 Docker 和 CLI 两种安装方法,如果你是新人推荐使用 Docker 安装。
+NocoBase 支持三种安装方式:
-### Docker (👍Recommended)
+- Docker 安装(推荐)
-#### 0. 先决条件
+ 适合无代码场景,不需要写代码。升级时,下载最新镜像并重启即可。
-⚡⚡ 请确保你已经安装了 [Docker](https://docs.docker.com/get-docker/)
+- create-nocobase-app 安装
-#### 1. 将 NocoBase 下载到本地
+ 项目的业务代码完全独立,支持低代码开发。
-使用 Git 下载(或直接[下载 Zip 包](https://github.com/nocobase/nocobase/archive/refs/heads/main.zip),并解压到 nocobase 目录下)
+- Git 源码安装
-```bash
-git clone https://github.com/nocobase/nocobase.git nocobase
-```
-
-#### 2. 选择数据库(任选其一)
-
-支持 SQLite、MySQL、PostgreSQL 数据库
-
-```bash
-# SQLite
-cd nocobase/docker/app-sqlite
-# MySQL
-cd nocobase/docker/app-mysql
-# PostgreSQL
-cd nocobase/docker/app-postgres
-```
-
-#### 3. 安装并启动 NocoBase
-
-安装过程可能需要等待几十秒钟
-
-```bash
-# 在后台运行
-$ docker-compose up -d
-# 查看 app 进程的情况
-$ docker-compose logs app
-
-app-sqlite-app-1 | nginx started
-app-sqlite-app-1 | yarn run v1.22.15
-app-sqlite-app-1 | $ cross-env DOTENV_CONFIG_PATH=.env node -r dotenv/config packages/app/server/lib/index.js install -s
-app-sqlite-app-1 | Done in 2.72s.
-app-sqlite-app-1 | yarn run v1.22.15
-app-sqlite-app-1 | $ pm2-runtime start --node-args="-r dotenv/config" packages/app/server/lib/index.js -- start
-app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: Launching in no daemon mode
-app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] starting in -fork mode-
-app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] online
-app-sqlite-app-1 | 🚀 NocoBase server running at: http://localhost:13000/
-```
-
-#### 4. 登录 NocoBase
-
-使用浏览器打开 http://localhost:13000/ 初始化账号和密码是 `admin@nocobase.com` 和 `admin123`。
-
-### CLI
-
-#### 0. 先决条件
-
-请确保你已经安装了 Node.js 12.x 或以上版本,如果你没有安装 Node.js 可以从官网下载并安装最新的 LTS 版本。如果你打算长期与 Node.js 打交道,推荐使用 nvm(Win 系统可以使用 nvm-windows )来管理 Node.js 版本。
-
-```bash
-$ node -v
-
-v16.13.2
-```
-
-推荐使用 yarn 包管理器。
-
-```bash
-$ npm install --global yarn
-$ yarn -v
-
-1.22.10
-```
-
-由于国内网络环境的原因,强烈建议你更换国内镜像。
-
-```bash
-$ yarn config set registry https://registry.npmmirror.com/
-$ yarn config set sqlite3_binary_host_mirror https://npmmirror.com/mirrors/sqlite3/
-```
-
-最后,请确保你已经配置并启动所需数据库,数据库支持 SQLite(无需安装启动)、MySQL、PostgreSQL。
-
-#### 1. 创建 NocoBase 项目
-
-```bash
-# SQLite
-yarn create nocobase-app my-nocobase-app -d sqlite
-# MySQL
-yarn create nocobase-app my-nocobase-app -d mysql \
- -e DB_HOST=localhost \
- -e DB_PORT=3356 \
- -e DB_DATABASE=nocobase \
- -e DB_USER=nocobase \
- -e DB_PASSWORD=nocobase
-# PostgreSQL
-yarn create nocobase-app my-nocobase-app -d postgres \
- -e DB_HOST=localhost \
- -e DB_PORT=5432 \
- -e DB_DATABASE=nocobase \
- -e DB_USER=nocobase \
- -e DB_PASSWORD=nocobase
-```
-
-#### 2. 切换目录
-
-```bash
-cd my-nocobase-app
-```
-
-#### 3. 安装依赖
-
-📢 由于网络环境、系统配置等因素影响,接下来这一步骤可能需要十几分钟时间。
-
-```bash
-yarn install
-```
-
-#### 4. 安装并启动 NocoBase
-
-```bash
-yarn nocobase install --lang=zh-CN
-yarn start
-```
-
-#### 5. 登录 NocoBase
-
-使用浏览器打开 http://localhost:13000/ 初始化账号和密码是 `admin@nocobase.com` 和 `admin123`。
-
-## 贡献
-
-- Fork 源代码到自己的仓库
-- 修改源代码
-- 提交 Pull Request
-
-### 下载项目
-
-```bash
-# 替换为自己的仓库地址
-git clone https://github.com/nocobase/nocobase.git
-cd nocobase
-cp .env.example .env
-yarn install
-```
-
-### 应用开发与测试
-
-```bash
-# 安装
-yarn nocobase install --lang=zh-CN
-# 启动应用
-yarn start
-# 运行所有测试
-yarn test
-# 运行文件夹下所有测试文件
-yarn test
-# 运行单个测试文件
-yarn test
-```
-
-### 文档预览
-
-```bash
-# 启动文档
-yarn doc --lang=zh-CN
-yarn doc --lang=en-US
-```
-
-文档在 docs 目录下,遵循 Markdown 语法
-
-```bash
-|- /docs/
- |- en-US
- |- zh-CN
-```
+ 如果你想体验最新未发布版本,或者想参与贡献,需要在源码上进行修改、调试,建议选择这种安装方式,对开发技术水平要求较高,如果代码有更新,可以走 git 流程拉取最新代码。
diff --git a/docker-compose.yml b/docker-compose.yml
index 89de6d580..284c7a8d4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -57,6 +57,6 @@ services:
volumes:
- ./:/app
expose:
- - ${SERVER_PORT}
+ - ${APP_PORT}
ports:
- - "${SERVER_PORT}:${SERVER_PORT}"
\ No newline at end of file
+ - "${APP_PORT}:${APP_PORT}"
\ No newline at end of file
diff --git a/docs/en-US/contributing.md b/docs/en-US/contributing.md
new file mode 100644
index 000000000..1e6536df2
--- /dev/null
+++ b/docs/en-US/contributing.md
@@ -0,0 +1,47 @@
+# Contributing
+
+- Fork the source code to your own repository
+- Modify source code
+- Submit pull request
+
+## Download
+
+```bash
+# Replace the following git address with your own repo
+git clone https://github.com/nocobase/nocobase.git
+cd nocobase
+yarn install
+```
+
+## Development and Testing
+
+```bash
+# Install and start the application
+yarn dev
+# Run all tests
+yarn test
+# Run all test files in the folder
+yarn test
+# Run a single test file
+yarn test
+```
+
+## Documentation preview
+
+```bash
+# Start documentation
+yarn doc --lang=zh-CN
+yarn doc --lang=en-US
+```
+
+The documentation is in the docs directory and follows Markdown syntax
+
+```bash
+|- /docs/
+ |- en-US
+ |- zh-CN
+```
+
+## Others
+
+For more CLI instructions, please [refer to the NocoBase CLI chapter](./development/nocobase-cli.md)
diff --git a/docs/en-US/development/directory-structure.md b/docs/en-US/development/directory-structure.md
new file mode 100644
index 000000000..2ed87129c
--- /dev/null
+++ b/docs/en-US/development/directory-structure.md
@@ -0,0 +1,89 @@
+# Directory structure
+
+## Application scaffolding
+
+```bash
+$ yarn create nocobase-app my-nocobase-app
+```
+
+The directory structure of the application scaffold created by `create-nocobase-app` is as follows
+
+```bash
+├── my-nocobase-app
+ ├── packages # Use the Monorepo approach to manage code, dividing different modules into packages
+ ├── app
+ ├── client # Client-side modules
+ ├── server # Server-side modules
+ ├── plugins # Plugins directory
+ ├── storages # For database files, attachments, cache, etc.
+ ├── db
+ ├── .env # Environment variables
+ ├── .buildrc.ts # Packaging configuration for packages, supports cjs, esm and umd packaging.
+ ├── jest.config.js
+ ├── jest.setup.ts
+ ├── lerna.json
+ ├── package.json
+ ├── tsconfig.jest.json
+ ├── tsconfig.json
+ ├── tsconfig.server.json
+```
+
+### packages directory
+
+```bash
+├── packages
+ ├── app
+ ├── client
+ ├── public
+ ├── src
+ ├── pages
+ ├── index.tsx
+ ├── .umirc.ts
+ ├── package.json
+ ├── server
+ ├── src
+ ├── config
+ ├── index.ts
+ ├── package.json
+ ├── /plugins
+ ├── my-plugin
+ ├── src
+ ├── package.json
+```
+
+NocoBase uses the Monorepo approach to manage the code, dividing the different modules into different packages.
+
+- `app/client` is the client-side module of the application, built on [umi](https://umijs.org).
+- `app/server` is the server-side module of the application.
+- `plugins/*` directory can hold various plugins.
+
+### storages directory
+
+Used to store database files, attachments, cache, etc.
+
+### .env file
+
+Environment variables
+
+### .buildrc.ts file
+
+Packaging configuration for packages, supports cjs, esm and umd packaging.
+
+## Plugins scaffolding
+
+```bash
+$ yarn nocobase create-plugin my-plugin
+```
+
+The plugin scaffolding directory initialized by `nocobase create-plugin` is as follows
+
+```bash
+├── my-nocobase-app
+ ├── packages
+ ├── plugins
+ ├── my-plugin
+ ├── src
+ ├── client
+ ├── server
+ ├── package.json
+```
diff --git a/docs/en-US/development/env.md b/docs/en-US/development/env.md
new file mode 100644
index 000000000..40a56d237
--- /dev/null
+++ b/docs/en-US/development/env.md
@@ -0,0 +1,207 @@
+# Environment variables
+
+## Global environment variables
+
+Saved in the `.env` file
+
+### APP_ENV
+
+Application environment, default value `development`, options include
+
+- `production` production environment
+- `development` development environment
+
+```bash
+APP_ENV=production
+```
+
+### APP_HOST
+
+Application host, default value `0.0.0.0`
+
+```bash
+APP_HOST=192.168.3.154
+```
+
+### APP_PORT
+
+Application port, default value `13000`
+
+```bash
+APP_PORT=13000
+```
+
+### APP_KEY
+
+Secret key for scenarios such as jwt
+
+```bash
+APP_KEY=app-key-test
+```
+
+### API_BASE_PATH
+
+NocoBase API address prefix, default value `/api/`
+
+```bash
+API_BASE_PATH=/api/
+```
+
+### DB_DIALECT
+
+Database type, default value `sqlite`,options include
+
+- `sqlite`
+- `mysql`
+- `postgres`
+
+```bash
+DB_DIALECT=mysql
+```
+
+### DB_STORAGE
+
+Database file path (configured when using SQLite)
+
+```bash
+# Relative path
+DB_HOST=storage/db/nocobase.db
+# Absolute path
+DB_HOST=/your/path/nocobase.db
+```
+
+### DB_HOST
+
+Database host (required when using MySQL or PostgreSQL)
+
+Default value `localhost`
+
+```bash
+DB_HOST=localhost
+```
+
+### DB_PORT
+
+Database port (required when using MySQL or PostgreSQL)
+
+- MySQL default port 3356
+- PostgreSQL default port 5432
+
+```bash
+DB_PORT=3356
+```
+
+### DB_DATABASE
+
+Database name (required when using MySQL or PostgreSQL)
+
+```bash
+DB_DATABASE=nocobase
+```
+
+### DB_USER
+
+Database user (required when using MySQL or PostgreSQL)
+
+```bash
+DB_USER=nocobase
+```
+
+### DB_PASSWORD
+
+Database password (required when using MySQL or PostgreSQL)
+
+```bash
+DB_PASSWORD=nocobase
+```
+
+### DB_TABLE_PREFIX
+
+Data Table Prefix
+
+```bash
+DB_TABLE_PREFIX=nocobase_
+```
+
+### DB_LOGGING
+
+Switching of logs, default value `off`, options include:
+
+- `on` On
+- `off` Off
+
+```bash
+DB_LOGGING=on
+```
+
+## Temporary environment variables
+
+When installing NocoBase, you can assist in the installation by setting temporary environment variables, such as
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=en-US \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ INIT_ROOT_PASSWORD=admin123 \
+ INIT_ROOT_NICKNAME="Super Admin" \
+ nocobase install
+
+# Equivalent to
+yarn nocobase install \
+ --lang=en-US \
+ --root-email=demo@nocobase.com \
+ --root-password=admin123 \
+ --root-nickname="Super Admin"
+
+# Equivalent to
+yarn nocobase install -l en-US -e demo@nocobase.com -p admin123 -n "Super Admin"
+```
+
+### INIT_APP_LANG
+
+Language at installation, default value `en-US`, options include
+
+- `en-US`
+- `zh-CN`
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=en-US \
+ nocobase install
+```
+
+### INIT_ROOT_EMAIL
+
+Root user's email
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=en-US \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ nocobase install
+```
+
+### INIT_ROOT_PASSWORD
+
+Root user's password
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=en-US \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ INIT_ROOT_PASSWORD=admin123 \
+ nocobase install
+```
+
+### INIT_ROOT_NICKNAME
+
+Root user's name
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=en-US \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ INIT_ROOT_PASSWORD=admin123 \
+ INIT_ROOT_NICKNAME="Super Admin" \
+ nocobase install
+```
diff --git a/docs/en-US/development/http-api/action-api.md b/docs/en-US/development/http-api/action-api.md
new file mode 100644
index 000000000..d71f3a6f9
--- /dev/null
+++ b/docs/en-US/development/http-api/action-api.md
@@ -0,0 +1,146 @@
+# Action API
+
+## Common
+
+---
+
+Collection and Association resources are common.
+
+### `create`
+
+```bash
+POST /api/users:create?whitelist=a,b&blacklist=c,d
+
+{} # Request Body
+```
+
+- Parameters
+ - whitelist White list
+ - blacklist Black list
+- Request body: JSON data to be inserted
+- Response body data: Created data JSON
+
+#### Add a User
+
+```bash
+POST /api/users:create
+
+Request Body
+{
+ "email": "demo@nocobase.com",
+ "name": "Admin"
+}
+
+Response 200 (application/json)
+{
+ "data": {},
+ "meta": {}
+}
+```
+
+#### Add a user's article
+
+```bash
+POST /api/users/1/posts:create
+
+Request Body
+{
+ "title": "My first post"
+}
+
+Response 200 (application/json)
+{
+ "data": {},
+ "meta": {}
+}
+```
+
+#### Association in Request Body
+
+```bash
+POST /api/posts:create
+
+Request Body
+{
+ "title": "My first post",
+ "user": 1
+}
+
+Response 200 (application/json)
+{
+ "data": {
+ "id": 1,
+ "title": "My first post",
+ "userId": 1,
+ "user": {
+ "id": 1
+ }
+ },
+ "meta": {}
+}
+```
+
+### `update`
+
+```bash
+POST /api/users:create?filterByTk=1&whitelist=a,b&blacklist=c,d
+
+{} # Request Body
+```
+
+- Parameters
+ - whitelist White list
+ - blacklist Black list
+ - filterByTk Filter by tk field, by default tk is the primary key of the data table
+ - filter Filter,support json string
+- Request body: JSON data to be updated
+
+#### Association in Request Body
+
+```bash
+POST /api/posts:update/1
+
+Request Body
+{
+ "title": "My first post 2",
+ "user": 2
+}
+
+Response 200 (application/json)
+{
+ "data": [
+ {
+ "id": 1,
+ "title": "My first post 2",
+ "userId": 2,
+ "user": {
+ "id": 2
+ }
+ }
+ ],
+ "meta": {}
+}
+```
+
+### `list`
+
+### `get`
+
+### `destroy`
+
+### `move`
+
+## Association
+
+---
+
+### `add`
+
+### `set`
+
+### `remove`
+
+### `toggle`
+
+
+
diff --git a/docs/en-US/development/http-api/filter-operators.md b/docs/en-US/development/http-api/filter-operators.md
new file mode 100644
index 000000000..13e9f7beb
--- /dev/null
+++ b/docs/en-US/development/http-api/filter-operators.md
@@ -0,0 +1,59 @@
+# Filter operators
+
+## Common
+
+- $eq
+- $ne
+- $gte
+- $gt
+- $lte
+- $lt
+- $not
+- $is
+- $in
+- $notIn
+- $like
+- $notLike
+- $iLike
+- $notILike
+- $and
+- $or
+- $empty
+- $notEmpty
+
+## array
+
+- $match
+- $notMatch
+- $anyOf
+- $noneOf
+- $arrayEmpty
+- $arrayNotEmpty
+
+## association
+
+- $exists
+- $notExists
+
+## boolean
+
+- $truthy
+- $falsy
+
+## date
+
+- $dateOn
+- $dateNotOn
+- $dateBefore
+- $dateNotBefore
+- $dateAfter
+- $dateNotAfter
+
+## string
+
+- $includes
+- $notIncludes
+- $startsWith
+- $notStartsWith
+- $endWith
+- $notEndWith
diff --git a/docs/en-US/development/http-api/index.md b/docs/en-US/development/http-api/index.md
new file mode 100644
index 000000000..ace76a369
--- /dev/null
+++ b/docs/en-US/development/http-api/index.md
@@ -0,0 +1,307 @@
+# Overview
+
+NocoBase HTTP API is designed based on Resource & Action, it is a superset of REST API. The operation is not limited to add, delete, change, and check, Resource Action can be extended arbitrarily in NocoBase.
+
+## Resource
+
+Resource has two expressions in NocoBase.
+
+- ``
+- `.`
+
+
+
+- collection is the set of all abstract data
+- association is the association data for the collection
+- resource includes both collection and collection.association
+
+
+
+### Example
+
+- `posts` Post
+- `posts.user` Post user
+- `posts.tags` Post tags
+
+## Action
+
+Representing resource operations as `:`
+
+- `:`
+- `.:`
+
+Built-in global operations for collection or association
+
+- `create`
+- `get`
+- `list`
+- `update`
+- `destroy`
+- `move`
+
+Built-in association operation for association only
+
+- `set`
+- `add`
+- `remove`
+- `toggle`
+
+### Example
+
+- `posts:create` Create posts
+- `posts.user:get` View posts user
+- `posts.tags:add` Attach post tags (associate existing tags with post)
+
+## Request URL
+
+```bash
+ /api/:
+ /api/:/
+ /api///:
+ /api///:/
+```
+
+### Example
+
+posts resource
+
+```bash
+POST /api/posts:create
+GET /api/posts:list
+GET /api/posts:get/1
+POST /api/posts:update/1
+POST /api/posts:destroy/1
+```
+
+posts.comments resource
+
+```bash
+POST /api/posts/1/comments:create
+GET /api/posts/1/comments:list
+GET /api/posts/1/comments:get/1
+POST /api/posts/1/comments:update/1
+POST /api/posts/1/comments:destroy/1
+```
+
+posts.tags resource
+
+```bash
+POST /api/posts/1/tags:create
+GET /api/posts/1/tags:get
+GET /api/posts/1/tags:list
+POST /api/posts/1/tags:update
+POST /api/posts/1/tags:destroy
+POST /api/posts/1/tags:add
+GET /api/posts/1/tags:remove
+```
+
+## Resource location
+
+- collection resource, locates the data to be processed by `collectionIndex`, `collectionIndex` must be unique
+- association resource, locates the data to be processed by `collectionIndex` and `associationIndex` jointly, `associationIndex` may not be unique, but `collectionIndex` and `associationIndex`'s association indexes must be unique
+
+When viewing association resource details, the requested URL needs to provide both `` and ``, `` is not redundant because `` may not be unique.
+
+For example, `tables.fields` indicates the fields of a data table
+
+```bash
+GET /api/tables/table1/fields/title
+GET /api/tables/table2/fields/title
+```
+
+Both table1 and table2 have a title field. The title is unique in table1, but other tables may also have a title field
+
+## Request parameters
+
+Request parameters can be placed in the request's headers, parameters (query string), and body (GET requests do not have a body).
+
+A few special request parameters
+
+- `filter` Data filtering, used in query-related operations.
+- `filterByTk` filter by tk field, used in operations that specify details of the data.
+- `sort` Sorting, used in query-related operations.
+- `fields` which data to output, for use in query-related operations.
+- `appends` additional relationship fields for use in query-related operations.
+- `except` which fields to exclude (no output), used in query-related operations.
+- `whitelist` fields whitelist, used in data creation and update related operations.
+- `blacklist` fields blacklist, used in data creation and update related operations.
+
+### filter
+
+Data filter
+
+```bash
+# simple
+GET /api/posts?filter[status]=publish
+# Recommend using the json string format, which requires encodeURIComponent encoding
+GET /api/posts?filter={"status":"published"}
+
+# filter operators
+GET /api/posts?filter[status.$eq]=publish
+GET /api/posts?filter={"status.$eq":"published"}
+
+# $and
+GET /api/posts?filter={"$and": [{"status.$eq":"published"}, {"title.$includes":"a"}]}
+# $or
+GET /api/posts?filter={"$or": [{"status.$eq":"pending"}, {"status.$eq":"draft"}]}
+
+# association field
+GET /api/posts?filter[user.email.$includes]=gmail
+GET /api/posts?filter={"user.email.$includes":"gmail"}
+```
+
+[Click here for more infomation about filter operators](http-api/filter-operators)
+
+### filterByTk
+
+Filter by tk field. By default
+
+- collection resource, tk is the primary key of the data table.
+- association resource, tk is the targetKey field of the association.
+
+```bash
+GET /api/posts:get?filterByTk=1&fields=name,title&appends=tags
+```
+
+### sort
+
+Sorting. When sorting in descending order, the fields are preceded by the minus sign `-`.
+
+```bash
+# createAt field in ascending order
+GET /api/posts:get?sort=createdAt
+# createAt field descending
+GET /api/posts:get?sort=-createdAt
+# Multiple fields sorted jointly, createAt field descending, title A-Z ascending
+GET /api/posts:get?sort=-createdAt,title
+```
+
+### fields
+
+Which fields to output
+
+```bash
+GET /api/posts:list?fields=name,title
+
+Response 200 (application/json)
+{
+ "data": [
+ {
+ "name": "",
+ "title": ""
+ }
+ ],
+ "meta": {}
+}
+```
+
+### appends
+
+Appends a relationship field
+
+### except
+
+Which fields to exclude (not output) for use in query-related operations.
+
+### whitelist
+
+Whitelist
+
+```bash
+POST /api/posts:create?whitelist=title
+
+{
+ "title": "My first post",
+ "date": "2022-05-19" # The date field will be filtered out and will not be written to the database
+}
+```
+
+### blacklist
+
+Blacklist
+
+```bash
+POST /api/posts:create?blacklist=date
+
+{
+ "title": "My first post",
+ "date": "2022-05-19" # The date field will be filtered out and will not be written to the database
+}
+```
+
+## Request Response
+
+Format of the response
+
+```ts
+type ResponseResult = {
+ data?: any; // Master data
+ meta?: any; // Additional Data
+ errors?: ResponseError[]; // Errors
+};
+
+type ResponseError = {
+ code?: string;
+ message: string;
+};
+```
+
+### Example
+
+View list
+
+```bash
+GET /api/posts:list
+
+Response 200 (application/json)
+
+{
+ data: [
+ {
+ id: 1
+ }
+ ],
+ meta: {
+ count: 1
+ page: 1,
+ pageSize: 1,
+ totalPage: 1
+ },
+}
+```
+
+View details
+
+```bash
+GET /api/posts:get/1
+
+Response 200 (application/json)
+
+{
+ data: {
+ id: 1
+ },
+ meta: {
+ count: 1
+ page: 1,
+ pageSize: 1,
+ totalPage: 1
+ },
+}
+```
+
+Error
+
+```bash
+POST /api/posts:create
+
+Response 400 (application/json)
+
+{
+ errors: [
+ {
+ message: 'name must be required',
+ },
+ ],
+}
+```
diff --git a/docs/en-US/development/http-api/javascript-sdk.md b/docs/en-US/development/http-api/javascript-sdk.md
new file mode 100644
index 000000000..764510834
--- /dev/null
+++ b/docs/en-US/development/http-api/javascript-sdk.md
@@ -0,0 +1,229 @@
+# JavaScript SDK
+
+## APIClient
+
+```ts
+class APIClient {
+ // axios instance
+ axios: AxiosInstance;
+ // constructors
+ constructor(instance?: AxiosInstance | AxiosRequestConfig);
+ // Client-side requests, support for AxiosRequestConfig and ResourceActionOptions
+ request, D = any>(config: AxiosRequestConfig | ResourceActionOptions): Promise;
+ // Get Resources
+ resource(name: string, of?: any): R;
+}
+```
+
+Initialize instance
+
+```ts
+import axios from 'axios';
+import { APIClient } from '@nocobase/sdk';
+
+// Provide AxiosRequestConfig configuration parameters
+const api = new APIClient({
+ baseURL: 'https://localhost:8000/api',
+});
+
+// Provide AxiosInstance
+const instance = axios.create({
+ baseURL: 'https://localhost:8000/api',
+});
+const api = new APIClient(instance);
+```
+
+## Mock
+
+```ts
+import { APIClient } from '@nocobase/sdk';
+import MockAdapter from 'axios-mock-adapter';
+
+const api = new APIClient({
+ baseURL: 'https://localhost:8000/api',
+});
+
+const mock = new MockAdapter(api.axios);
+
+mock.onGet('users:get').reply(200, {
+ data: { id: 1, name: 'John Smith' },
+});
+
+await api.request({ url: 'users:get' });
+```
+
+## Auth
+
+```ts
+// Pass token directly
+api.auth.token = '123';
+// Or sign in via signIn
+api.auth.signIn();
+// Log out and delete the token cache
+api.auth.signOut();
+```
+
+## Request
+
+```ts
+// url
+await api.request({
+ url: 'users:list',
+ // request params
+ params: {
+ filter: {
+ 'email.$includes': 'noco',
+ },
+ },
+ // request body
+ data,
+});
+
+// resource & action
+await api.request({
+ resource: 'users',
+ action: 'list',
+ // action params
+ params: {
+ filter: {
+ 'email.$includes': 'noco',
+ },
+ page: 1,
+ },
+});
+```
+
+## Resource action
+
+```ts
+await api.resource('collection')[action]();
+await api.resource('collection.association', collectionId)[action]();
+```
+
+## Action API
+
+```ts
+await api.resource('collection').create();
+await api.resource('collection').get();
+await api.resource('collection').list();
+await api.resource('collection').update();
+await api.resource('collection').destroy();
+await api.resource('collection.association', collectionId).create();
+await api.resource('collection.association', collectionId).get();
+await api.resource('collection.association', collectionId).list();
+await api.resource('collection.association', collectionId).update();
+await api.resource('collection.association', collectionId).destroy();
+```
+
+### `get`
+
+```ts
+interface Resource {
+ get: (options?: GetActionOptions) => Promise;
+}
+
+interface GetActionOptions {
+ filter?: any;
+ filterByTk?: any;
+ fields?: string || string[];
+ appends?: string || string[];
+ expect?: string || string[];
+ sort?: string[];
+}
+```
+
+### `list`
+
+```ts
+interface Resource {
+ list: (options?: ListActionOptions) => Promise;
+}
+
+interface ListActionOptions {
+ filter?: any;
+ filterByTk?: any;
+ fields?: string || string[];
+ appends?: string || string[];
+ expect?: string || string[];
+ sort?: string[];
+ page?: number;
+ pageSize?: number;
+ paginate?: boolean;
+}
+```
+
+### `create`
+
+```ts
+interface Resource {
+ create: (options?: CreateActionOptions) => Promise;
+}
+
+interface CreateActionOptions {
+ whitelist?: string[];
+ blacklist?: string[];
+ values?: {[key: sting]: any};
+}
+```
+
+### `update`
+
+```ts
+interface Resource {
+ update: (options?: UpdateActionOptions) => Promise;
+}
+
+interface UpdateActionOptions {
+ filter?: any;
+ filterByTk?: any;
+ whitelist?: string[];
+ blacklist?: string[];
+ values?: {[key: sting]: any};
+}
+```
+
+### `destroy`
+
+```ts
+interface Resource {
+ destroy: (options?: DestroyActionOptions) => Promise;
+}
+
+interface DestroyActionOptions {
+ filter?: any;
+ filterByTk?: any;
+}
+```
+
+### `move`
+
+```ts
+interface Resource {
+ move: (options?: MoveActionOptions) => Promise;
+}
+
+interface MoveActionOptions {
+ sourceId: any;
+ targetId?: any;
+ /** @default 'sort' */
+ sortField?: any;
+ targetScope?: {[key: string]: any};
+ sticky?: boolean;
+ method?: 'insertAfter' | 'prepend';
+}
+```
+
+### ``
+
+```ts
+interface AttachmentResource {
+
+}
+
+interface UploadActionOptions {
+
+}
+
+api.resource('attachments').upload();
+api.resource('attachments').upload();
+```
diff --git a/docs/en-US/development/http-api/rest-api.md b/docs/en-US/development/http-api/rest-api.md
new file mode 100644
index 000000000..cda97cafd
--- /dev/null
+++ b/docs/en-US/development/http-api/rest-api.md
@@ -0,0 +1,184 @@
+# REST API
+
+NocoBase's HTTP API is a superset of the REST API, and the standard CRUD API also supports the RESTful style.
+
+## Collection rescources
+
+---
+
+### Create collection
+
+HTTP API
+
+```bash
+POST /api/:create
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+POST /api/
+
+{} # JSON body
+```
+
+### List collection
+
+HTTP API
+
+```bash
+GET /api/:list
+```
+
+REST API
+
+```bash
+GET /api/
+```
+
+### View collection details
+
+HTTP API
+
+```bash
+GET /api/:get?filterByTk=
+GET /api/:get/
+```
+
+REST API
+
+```bash
+GET /api//
+```
+
+### Update collection
+
+HTTP API
+
+```bash
+POST /api/:update?filterByTk=
+
+{} # JSON body
+
+# Or
+POST /api/:update/
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+PUT /api//
+
+{} # JSON body
+```
+
+### Delete collection
+
+HTTP API
+
+```bash
+POST /api/:destroy?filterByTk=
+# Or
+POST /api/:destroy/
+```
+
+REST API
+
+```bash
+DELETE /api//
+```
+
+## Association resources
+
+---
+
+### Create Association
+
+HTTP API
+
+```bash
+POST /api///:create
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+POST /api///
+
+{} # JSON body
+```
+
+### List Association
+
+HTTP API
+
+```bash
+GET /api///:list
+```
+
+REST API
+
+```bash
+GET /api///
+```
+
+### View Association details
+
+HTTP API
+
+```bash
+GET /api///:get?filterByTk=
+# Or
+GET /api///:get/
+```
+
+REST API
+
+```bash
+GET /api///:get/
+```
+
+### Update Association
+
+HTTP API
+
+```bash
+POST /api///:update?filterByTk=
+
+{} # JSON body
+
+# Or
+POST /api///:update/
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+PUT /api///:update/
+
+{} # JSON
+```
+
+### Delete Association
+
+HTTP API
+
+```bash
+POST /api///:destroy?filterByTk=
+# Or
+POST /api///:destroy/
+```
+
+REST API
+
+```bash
+DELETE /api////
+```
diff --git a/docs/en-US/development/nocobase-cli.md b/docs/en-US/development/nocobase-cli.md
new file mode 100644
index 000000000..bfcefb89a
--- /dev/null
+++ b/docs/en-US/development/nocobase-cli.md
@@ -0,0 +1,310 @@
+---
+order: 2
+---
+
+# NocoBase CLI
+
+NocoBase CLI is designed to help you develop, build, and deploy NocoBase applications.
+
+
+
+NocoBase CLI supports both ts-node and node modes
+
+- ts-node mode (default): used for development environment, supports real-time compilation, but slow response
+- node mode: for production environment, fast response, but need to execute `yarn nocobase build` to compile all source code first
+
+
+
+## Instructions
+
+```bash
+$ yarn nocobase -h
+
+Usage: nocobase [command] [options]
+
+Options:
+ -h, --help
+
+Commands:
+ create-plugin Create plugin scaffolding
+ console
+ db:auth Verify that the database connection is successful
+ db:sync Generate relevant data tables and fields from collections configuration
+ install Install
+ start Start the application in the production environment
+ build Compile and package
+ clean Delete the compiled files
+ dev Start the application for the development environment and supports live compilation
+ doc Documentation development
+ test Test
+ umi
+ upgrade Upgrade
+ help
+```
+
+## Use in scaffolding
+
+The `scripts` in the application scaffolding `package.json` are as follows
+
+```json
+{
+ "scripts": {
+ "dev": "nocobase dev",
+ "start": "nocobase start",
+ "clean": "nocobase clean",
+ "build": "nocobase build",
+ "test": "nocobase test",
+ "postinstall": "nocobase umi generate tmp"
+ }
+}
+```
+
+## Extensions
+
+NocoBase CLI is built on [commander](https://github.com/tj/commander.js), you can freely extend the command, the extended command can be written in `app/server/index.ts`.
+
+```ts
+const app = new Application(config);
+
+app.command('hello').action(() => {});
+```
+
+Alternatively, write in the plugin.
+
+```ts
+class MyPlugin extends Plugin {
+ beforeLoad() {
+ this.app.command('hello').action(() => {});
+ }
+}
+```
+
+Terminal runs
+
+```bash
+$ yarn nocobase hello
+```
+
+## Built-in command line
+
+Sort by frequency of use
+
+### `dev`
+
+Start the application in the development environment and the code is compiled in real time.
+
+
+NocoBase will be installed automatically if it is not installed (refer to the install command)
+
+
+```bash
+Usage: nocobase dev [options]
+
+Options:
+ -p, --port [port]
+ --client
+ --server
+ -h, --help
+```
+
+Example
+
+```bash
+# Start application for development environment, live compile
+yarn nocobase dev
+# Start only the server side
+yarn nocobase dev --server
+# Start only the client side
+yarn nocobase dev --client
+```
+
+### `start`
+
+Start the application in a production environment, the code needs to be yarn build.
+
+
+
+- NocoBase will be installed automatically if it is not installed (refer to the install command)
+- If the source code has been modified, it needs to be repackaged (refer to the build command)
+
+
+
+```bash
+$ yarn nocobase start -h
+
+Usage: nocobase start [options]
+
+Options:
+ -p, --port
+ -s, --silent
+ -h, --help
+```
+
+Example
+
+```bash
+# Start the application in a production environment
+yarn nocobase start
+```
+
+### `install`
+
+Install
+
+```bash
+$ yarn nocobase install -h
+
+Usage: nocobase install [options]
+
+Options:
+ -f, --force
+ -c, --clean
+ -s, --silent
+ -l, --lang [lang]
+ -e, --root-email
+ -p, --root-password
+ -n, --root-nickname [rootNickname]
+ -h, --help
+```
+
+Example
+
+```bash
+# Initial Installation
+yarn nocobase install -l en-US -e admin@nocobase.com -p admin123
+# Delete all data tables of NocoBase and reinstall
+yarn nocobase install -f -l en-US -e admin@nocobase.com -p admin123
+# Empty the database and reinstall
+yarn nocobase install -c -l en-US -e admin@nocobase.com -p admin123
+```
+
+
+
+Difference between `-f/--force` and `-c/--clean`
+- `-f/--force` Delete all data tables of NocoBase
+- `-c/--clean` Delete all data tables of the database
+
+
+
+### `upgrade`
+
+Upgrade
+
+```bash
+yarn nocobase upgrade
+```
+
+### `test`
+
+jest tests, supports all [jest-cli](https://jestjs.io/docs/cli) options, and extends `-c, --db-clean` support in addition.
+
+```bash
+$ yarn nocobase test -h
+
+Usage: nocobase test [options]
+
+Options:
+ -c, --db-clean Empty the database before running all tests
+ -h, --help
+```
+
+Example
+
+```bash
+# Run all test files
+yarn nocobase test
+# Run all test files in the specified folder
+yarn nocobase test packages/core/server
+# Run all tests in the specified file
+yarn nocobase test packages/core/database/src/__tests__/database.test.ts
+
+# Empty the database before running tests
+yarn nocobase test -c
+yarn nocobase test packages/core/server -c
+```
+
+### `build`
+
+Before deployed to the production environment, the source code needs to be compiled and packaged. It needs to be rebuilt if there are changes to the code.
+
+```bash
+# All packages
+yarn nocobase build
+# Specified package
+yarn nocobase build app/server app/client
+```
+
+### `clean`
+
+Delete the compiled file
+
+```bash
+yarn clean
+# Equivalent to
+yarn rimraf -rf packages/*/*/{lib,esm,es,dist}
+```
+
+### `doc`
+
+Documentation development
+
+```bash
+# Start documentation
+yarn doc --lang=en-US # Equivalent to yarn doc dev
+# Build the documentation and output it to . /docs/dist/ directory by default
+yarn doc build
+# View the final result of the document output by dist
+yarn doc serve --lang=en-US
+```
+
+### `db:auth`
+
+Verify that the database is successfully connected
+
+```bash
+$ yarn nocobase db:auth -h
+
+Usage: nocobase db:auth [options]
+
+Options:
+ -r, --repeat [repeat] Number of reconnections
+ -h, --help
+```
+
+### `db:sync`
+
+Generate data tables and fields via collections configuration
+
+```bash
+$ yarn nocobase db:sync -h
+
+Usage: nocobase db:sync [options]
+
+Options:
+ -f, --force
+ -h, --help display help for command
+```
+
+### `umi`
+
+`app/client` is built based on [umi](https://umijs.org/) and can be used to execute other related commands via `nocobase umi`.
+
+```bash
+# Generate the .umi cache required by the development environment
+yarn nocobase umi generate tmp
+```
+
+### `help`
+
+The help command, also available with the option parameter, `-h` and `--help`
+
+```bash
+# View all cli
+yarn nocobase help
+# You can also use -h
+yarn nocobase -h
+# or --help
+yarn nocobase --help
+# Option to view the db:sync command
+yarn nocobase db:sync -h
+```
diff --git a/docs/en-US/development/plugin-development/client/overview.md b/docs/en-US/development/plugin-development/client/overview.md
new file mode 100644
index 000000000..4bba659eb
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/overview.md
@@ -0,0 +1 @@
+# Overview
\ No newline at end of file
diff --git "a/docs/en-US/development/plugin-development/client/providers/\bapi-client.md" "b/docs/en-US/development/plugin-development/client/providers/\bapi-client.md"
new file mode 100644
index 000000000..3dac00645
--- /dev/null
+++ "b/docs/en-US/development/plugin-development/client/providers/\bapi-client.md"
@@ -0,0 +1 @@
+# APIClient
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/client/providers/acl.md b/docs/en-US/development/plugin-development/client/providers/acl.md
new file mode 100644
index 000000000..45cdee8d8
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/acl.md
@@ -0,0 +1 @@
+# ACL
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/client/providers/antd.md b/docs/en-US/development/plugin-development/client/providers/antd.md
new file mode 100644
index 000000000..a80a47303
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/antd.md
@@ -0,0 +1 @@
+# Ant Design
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/client/providers/china-region.md b/docs/en-US/development/plugin-development/client/providers/china-region.md
new file mode 100644
index 000000000..3706bbe44
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/china-region.md
@@ -0,0 +1 @@
+# ChianRegion
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/client/providers/collection-manager.md b/docs/en-US/development/plugin-development/client/providers/collection-manager.md
new file mode 100644
index 000000000..da019d550
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/collection-manager.md
@@ -0,0 +1 @@
+# CollectionManager
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/client/providers/i18n.md b/docs/en-US/development/plugin-development/client/providers/i18n.md
new file mode 100644
index 000000000..a4f29d977
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/i18n.md
@@ -0,0 +1 @@
+# I18n
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/client/providers/route-switch.md b/docs/en-US/development/plugin-development/client/providers/route-switch.md
new file mode 100644
index 000000000..3bfc5a330
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/route-switch.md
@@ -0,0 +1 @@
+# RouteSwitch
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/client/providers/schema-component.md b/docs/en-US/development/plugin-development/client/providers/schema-component.md
new file mode 100644
index 000000000..90d3aa4d8
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/schema-component.md
@@ -0,0 +1 @@
+# SchemaComponent
diff --git a/docs/en-US/development/plugin-development/client/providers/schema-initializer.md b/docs/en-US/development/plugin-development/client/providers/schema-initializer.md
new file mode 100644
index 000000000..bd2e33b59
--- /dev/null
+++ b/docs/en-US/development/plugin-development/client/providers/schema-initializer.md
@@ -0,0 +1 @@
+# SchemaInitializer
diff --git a/docs/en-US/development/plugin-development/index.md b/docs/en-US/development/plugin-development/index.md
new file mode 100644
index 000000000..05cf8c1fd
--- /dev/null
+++ b/docs/en-US/development/plugin-development/index.md
@@ -0,0 +1 @@
+# Quick Start
diff --git a/docs/en-US/development/plugin-development/server/acl.md b/docs/en-US/development/plugin-development/server/acl.md
new file mode 100644
index 000000000..8cd8bbcac
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/acl.md
@@ -0,0 +1 @@
+# ACL
diff --git a/docs/en-US/development/plugin-development/server/app-manager.md b/docs/en-US/development/plugin-development/server/app-manager.md
new file mode 100644
index 000000000..76a11afbe
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/app-manager.md
@@ -0,0 +1 @@
+# AppManager
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/server/cli.md b/docs/en-US/development/plugin-development/server/cli.md
new file mode 100644
index 000000000..db3cc6737
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/cli.md
@@ -0,0 +1 @@
+# CLI
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/server/database.md b/docs/en-US/development/plugin-development/server/database.md
new file mode 100644
index 000000000..4a79ce0cd
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/database.md
@@ -0,0 +1 @@
+# Database
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/server/events.md b/docs/en-US/development/plugin-development/server/events.md
new file mode 100644
index 000000000..b649f948c
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/events.md
@@ -0,0 +1 @@
+# Event
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/server/i18n.md b/docs/en-US/development/plugin-development/server/i18n.md
new file mode 100644
index 000000000..05b5b6193
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/i18n.md
@@ -0,0 +1 @@
+# I18n
diff --git a/docs/en-US/development/plugin-development/server/middleware.md b/docs/en-US/development/plugin-development/server/middleware.md
new file mode 100644
index 000000000..c5033ed0e
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/middleware.md
@@ -0,0 +1 @@
+# Middleware
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/server/overview.md b/docs/en-US/development/plugin-development/server/overview.md
new file mode 100644
index 000000000..4bba659eb
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/overview.md
@@ -0,0 +1 @@
+# Overview
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/server/plugin-manager.md b/docs/en-US/development/plugin-development/server/plugin-manager.md
new file mode 100644
index 000000000..b98d016d5
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/plugin-manager.md
@@ -0,0 +1 @@
+# PluginManager
\ No newline at end of file
diff --git a/docs/en-US/development/plugin-development/server/resourcer.md b/docs/en-US/development/plugin-development/server/resourcer.md
new file mode 100644
index 000000000..5c0d22865
--- /dev/null
+++ b/docs/en-US/development/plugin-development/server/resourcer.md
@@ -0,0 +1 @@
+# Resource & Action
\ No newline at end of file
diff --git a/docs/en-US/faq.md b/docs/en-US/faq.md
new file mode 100644
index 000000000..a39c1bc0d
--- /dev/null
+++ b/docs/en-US/faq.md
@@ -0,0 +1,2 @@
+# FAQ
+
diff --git a/docs/en-US/getting-started/installation/create-nocobase-app.md b/docs/en-US/getting-started/installation/create-nocobase-app.md
new file mode 100644
index 000000000..4f15d0a69
--- /dev/null
+++ b/docs/en-US/getting-started/installation/create-nocobase-app.md
@@ -0,0 +1,86 @@
+# `create-nocobase-app`
+
+## 0. Prerequisites
+
+Make sure you have:
+
+- Node.js 14+, Yarn 1.22.x installed
+- Configured and started the required database SQLite 3.x, MySQL 8.x, PostgreSQL 10.x choose one
+
+Please make sure you have Node.js 14.x or above installed. You can download and install the latest LTS version from the official website. It is recommended to use nvm (or nvm-windows for Win systems) to manage Node.js versions if you plan to work with Node.js for a long time.
+
+```bash
+$ node -v
+
+v16.13.2
+```
+
+Install yarn package manager
+
+```bash
+$ npm install --global yarn
+$ yarn -v
+
+1.22.10
+```
+
+## 1. Create a NocoBase project
+
+```bash
+# SQLite
+yarn create nocobase-app my-nocobase-app -d sqlite
+# MySQL
+yarn create nocobase-app my-nocobase-app -d mysql \
+ -e DB_HOST=localhost \
+ -e DB_PORT=3356 \
+ -e DB_DATABASE=nocobase \
+ -e DB_USER=nocobase \
+ -e DB_PASSWORD=nocobase
+# PostgreSQL
+yarn create nocobase-app my-nocobase-app -d postgres \
+ -e DB_HOST=localhost \
+ -e DB_PORT=5432 \
+ -e DB_DATABASE=nocobase \
+ -e DB_USER=nocobase \
+ -e DB_PASSWORD=nocobase
+```
+
+## 2. Switch to the project directory
+
+```bash
+cd my-nocobase-app
+```
+
+## 3. Install dependencies
+
+📢 This next step may take more than ten minutes due to network environment, system configuration, and other factors.
+
+```bash
+yarn install
+```
+
+## 4. Install NocoBase
+
+```bash
+yarn nocobase install --lang=zh-CN
+```
+
+## 5. Start NocoBase
+
+Development
+
+```bash
+yarn dev
+```
+
+Production
+
+```bash
+yarn start
+```
+
+Note: For production, if the code has been modified, you need to execute `yarn build` and restart NocoBase.
+
+## 6. Log in to NocoBase
+
+Open [http://localhost:13000](http://localhost:13000) in a web browser. The initial account and password are `admin@nocobase.com` and `admin123`.
diff --git a/docs/en-US/getting-started/installation/docker-compose.md b/docs/en-US/getting-started/installation/docker-compose.md
new file mode 100644
index 000000000..3e748f762
--- /dev/null
+++ b/docs/en-US/getting-started/installation/docker-compose.md
@@ -0,0 +1,52 @@
+# Docker (👍 Recommended)
+
+## 0. Prerequisites
+
+⚡⚡ Please make sure you have installed [Docker](https://docs.docker.com/get-docker/)
+
+## 1. Download NocoBase
+
+Download with Git (or Download Zip,and extract it to the nocobase directory)
+
+```bash
+git clone https://github.com/nocobase/nocobase.git nocobase
+```
+
+## 2. Select database (choose one)
+
+Supports SQLite, MySQL, PostgreSQL
+
+```bash
+# SQLite
+cd nocobase/docker/app-sqlite
+# MySQL
+cd nocobase/docker/app-mysql
+# PostgreSQL
+cd nocobase/docker/app-postgres
+```
+
+## 3. Install and start NocoBase
+
+It may take dozens of seconds
+
+```bash
+# run in the background
+$ docker-compose up -d
+# view app logs
+$ docker-compose logs app
+
+app-sqlite-app-1 | nginx started
+app-sqlite-app-1 | yarn run v1.22.15
+app-sqlite-app-1 | $ cross-env DOTENV_CONFIG_PATH=.env node -r dotenv/config packages/app/server/lib/index.js install -s
+app-sqlite-app-1 | Done in 2.72s.
+app-sqlite-app-1 | yarn run v1.22.15
+app-sqlite-app-1 | $ pm2-runtime start --node-args="-r dotenv/config" packages/app/server/lib/index.js -- start
+app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: Launching in no daemon mode
+app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] starting in -fork mode-
+app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] online
+app-sqlite-app-1 | 🚀 NocoBase server running at: http://localhost:13000/
+```
+
+## 4. Log in to NocoBase
+
+Open [http://localhost:13000](http://localhost:13000) in a web browser. The initial account and password are `admin@nocobase.com` and `admin123`.
diff --git a/docs/en-US/getting-started/installation/git-clone.md b/docs/en-US/getting-started/installation/git-clone.md
new file mode 100644
index 000000000..ba259884a
--- /dev/null
+++ b/docs/en-US/getting-started/installation/git-clone.md
@@ -0,0 +1,64 @@
+# Git source code
+
+## 0. Prerequisites
+
+Make sure you have:
+
+- Git, Node.js 14+, Yarn 1.22.x installed
+- Configured and started the required database SQLite 3.x, MySQL 8.x, PostgreSQL 10.x choose one
+
+## 1. Download with Git
+
+```bash
+git clone https://github.com/nocobase/nocobase.git my-nocobase-app
+```
+
+## 2. Switch to the project directory
+
+```bash
+cd my-nocobase-app
+```
+
+## 3. Install dependencies
+
+```bash
+yarn install
+```
+
+## 4. Set environment variables
+
+The environment variables required by NocoBase are stored in the root `.env` file, modify the environment variables according to the actual situation, if you don't know how to change them, [click here for environment variables description](./development/env.md), or you can leave it as default.
+
+```bash
+# Using sqlite database
+DB_DIALECT=sqlite
+# sqlite file path
+DB_STORAGE=storage/db/nocobase.sqlite
+```
+
+## 5. Install NocoBase
+
+```bash
+yarn nocobase install --lang=zh-CN
+```
+
+## 6. Start NocoBase
+
+Development
+
+```bash
+yarn dev
+```
+
+Production
+
+```bash
+# Compile
+yarn build
+# Start
+yarn start
+```
+
+## 7. Log in to NocoBase
+
+Open [http://localhost:13000](http://localhost:13000) in a web browser. The initial account and password are `admin@nocobase.com` and `admin123`.
diff --git a/docs/en-US/getting-started/installation/overview.md b/docs/en-US/getting-started/installation/overview.md
new file mode 100644
index 000000000..c029d7ec9
--- /dev/null
+++ b/docs/en-US/getting-started/installation/overview.md
@@ -0,0 +1,23 @@
+# Overview
+
+## Installation Methods
+
+NocoBase supports three installation methods.
+
+- [Docker (recommended)](./docker-compose.md)
+- [create-nocobase-app](./create-nocobase-app.md)
+- [Git source code](./git-clone.md)
+
+## How to choose
+
+**Docker (recommended)**:
+
+Suitable for no-code scenarios, no code to write. When upgrading, just download the latest image and reboot.
+
+**create-nocobase-app**:
+
+The business code of the project is completely independent and supports low-code development.
+
+**Git source code**:
+
+If you want to experience the latest unreleased version, or want to participate in the contribution, you need to make changes and debug on the source code, it is recommended to choose this installation method, which requires a high level of development skills, and if the code has been updated, you can git pull the latest code.
diff --git a/docs/en-US/getting-started/upgrading.md b/docs/en-US/getting-started/upgrading.md
new file mode 100644
index 000000000..8cd7b924f
--- /dev/null
+++ b/docs/en-US/getting-started/upgrading.md
@@ -0,0 +1,55 @@
+# Upgrading
+
+Make sure to back up your database before upgrading
+
+## Docker
+
+Switch to the project directory
+
+```bash
+# SQLite
+cd nocobase/docker/app-sqlite
+# MySQL
+cd nocobase/docker/app-mysql
+# PostgreSQL
+cd nocobase/docker/app-postgres
+```
+
+Use `docker-compose` to stop, delete the application, and download the latest image
+
+```bash
+# Stop the app
+docker-compose stop app
+# Delete the app
+docker-compose rm app
+# Download the latest image and start it
+docker-compose up -d app
+# Check the status of the app process
+docker-compose logs app
+```
+
+## create-nocobase-app
+
+Execute the `nocobase upgrad` command
+
+```bash
+# Switch to the project directory
+cd my-nocobase-app
+# Execute the update command
+yarn nocobase upgrade
+# Start
+yarn start
+```
+
+## Git source code
+
+```bash
+# Switch to the project directory
+cd my-nocobase-app
+# Pull latest source code
+git pull
+# Execute the update command
+yarn nocobase upgrade
+# Start
+yarn start
+```
diff --git a/docs/en-US/index.md b/docs/en-US/index.md
new file mode 100644
index 000000000..1b0051ea6
--- /dev/null
+++ b/docs/en-US/index.md
@@ -0,0 +1,48 @@
+# Introduction
+
+![](https://nocobase.oss-cn-beijing.aliyuncs.com/bbcedd403d31cd1ccc4e9709581f5c2f.png)
+
+## What is NocoBase
+
+NocoBase is a scalability-first, open-source no-code development platform. No programming required, build your own collaboration platform, management system with NocoBase in minutes.
+
+Homepage:
+https://www.nocobase.com/
+
+Online Demo:
+https://demo.nocobase.com/new
+
+Contact Us:
+hello@nocobase.com
+
+## Features
+
+- **Open source and free**
+ - Unrestricted commercial use under the Apache-2.0 license
+ - Full code ownership, private deployment, private and secure data
+ - Free to expand and develop for actual needs
+ - Good ecological support
+- **Strong no-code capability**
+ - Data Model
+ - Create independent data models using dozens of field types such as text, date, number, attachment, option, icon, etc., and various association relationships such as one-to-one, one-to-many, many-to-many, etc.
+ - Block
+ - Display and manipulate data within a page using a free combination of block types such as tables, forms, kanban, calendars, details, etc.
+ - ACL
+ - Role-based control of user's system configuration rights, data action rights and menu access rights.
+ - Workflow
+ - Repetitive tasks are replaced by automation to increase efficiency. Manual approval is required for important matters.
+ - Menu
+ - You can group menus, support adding pages and links, and support unlimited submenus.
+ - Action
+ - Support filtering, exporting, adding, deleting, modifying, viewing and other operations to process data, which can be extended to more types.
+- **Built for extended development**
+ - Microkernel architecture, flexible and easy to extend, with a robust plug-in system
+ - Node.js-based, with popular frameworks and technologies, including Koa, Sequelize, React, Formily, Ant Design, etc.
+ - Progressive development, easy for getting-started, friendly to newcomers
+ - No binding, no strong dependencies, can be used in any combination or extensions, can be used in existing projects
+
+## Architecture
+
+![](https://www.nocobase.com/images/NocoBaseMindMapLite.png)
+
+[Click here to view the full image](https://www.nocobase.com/images/NocoBaseMindMap.png)
diff --git a/docs/en-US/release-notes.md b/docs/en-US/release-notes.md
new file mode 100644
index 000000000..1ba16278b
--- /dev/null
+++ b/docs/en-US/release-notes.md
@@ -0,0 +1,71 @@
+# Release Notes
+
+## Ready for release
+
+### New features
+- Packaging tool `@nocobase/build`
+- CLI `@nocobase/cli`
+- devtools `@nocobase/devtools`
+- JavaScript SDK `@nocobase/sdk`
+- Documents(v0.7)
+
+### Bug fixes & improvements
+- `@nocobase/preset-nocobase`
+- create scaffolding `create-nocobase-app`
+- Documents theme `dumi-theme-nocobase`
+
+## 2022/05/14 ~ v0.7.0-alpha.34
+
+- feat: add plugins:getPinned action api
+- fix(plugin workflow): cannot get job result properties (#382)
+- feat: exist on server start throw error (#374)
+- chore: application options (#375)
+- fix: not in operator with null value record (#377)
+
+## 2022/05/13 ~ v0.7.0-alpha.33
+
+- fix: link-to field data scope error (#1337)
+- feat(plugin workflow): revisions (#379)
+- fix(database): fix option-parser include list index (#371)
+- fix(plugin-worklfow): fix duplicated description in fields values (#368)
+- fix(database): fix type and transaction in repository (#366)
+- fix(plugin workflow): fix transaction of execution (#364)
+
+## 2022/05/05 ~ v0.7.0-alpha.30
+
+- fix(client): upgrade formily packages
+- fix(client): setFormValueChanged must be defined
+
+## 2022/05/01 ~ v0.7.0-alpha.27
+
+- fix: use wrapper when greater than one column
+- fix: props for CreateFormBlockInitializers
+- fix: add schema initializer icon
+- fix: plugin workflow (#349)
+- fix: db:sync not working (#348)
+- fix(plugin-workflow): fix trigger bind logic to avoid duplication (#347)
+- fix(plugin workflow) (#346)
+- fix: action open mode
+- fix: menu url style (#344)
+- feat: action loading
+- fix: compile the label field
+- fix: invalid drag and drop sort
+
+## 2022/04/25 ~ v0.7.0-alpha.16
+
+- fix: cannot find module mkdirp (#330)
+- fix(plugin workflow): UX issues (#329)
+- fix(plugin-file-manager): test failed
+- fix(app-server): dist options
+
+## 2022/04/25 ~ v0.7.0-alpha.0
+
+- Alpha Version
+
+## 2021/10/07 ~ v0.5.0
+
+- The second preview version
+
+## 2021/04/07 ~ v0.4.0
+
+- The first preview version
diff --git a/docs/en-US/roadmap.md b/docs/en-US/roadmap.md
new file mode 100644
index 000000000..b4cd1efc4
--- /dev/null
+++ b/docs/en-US/roadmap.md
@@ -0,0 +1,31 @@
+# Roadmap
+
+## Iterating
+
+- `core` Roles & Permissions
+- `core` Upgrading
+- `core` Relationships
+- `plugin` Workflow
+- `doc` Development Doc
+
+## Developing
+
+- `core` Custom actions
+- `plugin` Action logs
+- `plugin` Database connection
+
+## Planning
+
+- `ui` Mobile version
+- `plugin` Export
+- `plugin` Open API
+- `core` Plugins manager
+
+## Future
+
+- `plugin` Approval
+- `plugin` Full-text search
+- `plugin` Shared pages
+- `plugin` Reference and copy data from other tables
+- `plugin` Formula
+- `plugin` Data visualization
diff --git a/docs/en-US/thanks.md b/docs/en-US/thanks.md
new file mode 100644
index 000000000..325efc399
--- /dev/null
+++ b/docs/en-US/thanks.md
@@ -0,0 +1,12 @@
+# Acknowledgements
+
+NocoBase uses excellent and proven open source products, to whom we express our sincere gratitude.
+
+- [Ant Design](https://ant.design/)
+- [Dnd Kit](https://dndkit.com/)
+- [Formily](https://github.com/alibaba/formily)
+- [I18next](https://www.i18next.com/)
+- [Koa](https://koajs.com/)
+- [React](https://reactjs.org/)
+- [Sequelize](https://sequelize.org/)
+- [UmiJS](https://umijs.org/)
diff --git a/docs/en-US/user-manual/advanced-guide/actions.md b/docs/en-US/user-manual/advanced-guide/actions.md
new file mode 100644
index 000000000..f48d91130
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/actions.md
@@ -0,0 +1,3 @@
+# Actions
+
+TO DO
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/blocks.md b/docs/en-US/user-manual/advanced-guide/blocks.md
new file mode 100644
index 000000000..b3aba1d55
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/blocks.md
@@ -0,0 +1,63 @@
+# Blocks
+
+Blocks are views that are used to display and manipulate data. Blocks can be placed in pages and popups. A block consists of three parts.
+
+1. content area: the body of the block
+2. action area: various action buttons can be placed to manipulate the block data
+3. configuration area: buttons for operating the block configuration
+
+![6.block.jpg](./blocks/6.block.jpg)
+
+## Add block
+
+Enter the UI Editor mode and click the Add block button on the page and in the pop-up window to add the block. The options are divided into 4 steps.
+
+1. Select block type: Currently available block types include Table, Form, Details, Calendar, Kanban, Markdown
+2. Select Collection: All collections will be listed here
+3. Choose the creation method: create a blank block, or duplicate a block template , or reference a block template
+4. Select Template: If you selected Create from Template in step 3, select the template in step 4
+
+![6.block-add.jpg](./blocks/6.block-add.jpg)
+
+## Configure Blocks
+
+The configuration of blocks consists of three elements.
+
+- Configure block content
+- Configure block actions
+- Configure block properties
+
+### Configure block content
+
+Take the table block as an example, the content of the block is the columns to be displayed in the table. Click Configure columns to configure the columns to be displayed.
+
+![6.block-content.gif](./blocks/6.block-content.gif)
+
+### Configure block actions
+
+Take table block as an example, there are filter, add, delete, view, edit, customize and other actions available. Click the Configure actions button to configure the actions. Each of the action buttons can be configured for their own properties.
+
+![6.block-content.gif](./blocks/6.block-content%201.gif)
+
+### Configure block properties
+
+Move the cursor to the upper right corner of the block and you will see the block configuration button. Using the table block as an example, the following properties can be configured.
+
+- Drag & drop sorting
+- Set the data scope
+- Set default sorting rules
+- Records per page
+
+![6.collection-setting.gif](./blocks/6.collection-setting.gif)
+
+## Block Types
+
+Currently NocoBase supports the following types of blocks.
+
+- Table
+- Form
+- Details
+- Kanban
+- Calendar
+- Related Data
+- Markdown
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/blocks/6.block-add.jpg b/docs/en-US/user-manual/advanced-guide/blocks/6.block-add.jpg
new file mode 100755
index 000000000..cd609413f
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/blocks/6.block-add.jpg differ
diff --git a/docs/en-US/user-manual/advanced-guide/blocks/6.block-content 1.gif b/docs/en-US/user-manual/advanced-guide/blocks/6.block-content 1.gif
new file mode 100755
index 000000000..8f79be9fa
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/blocks/6.block-content 1.gif differ
diff --git a/docs/en-US/user-manual/advanced-guide/blocks/6.block-content.gif b/docs/en-US/user-manual/advanced-guide/blocks/6.block-content.gif
new file mode 100755
index 000000000..8f79be9fa
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/blocks/6.block-content.gif differ
diff --git a/docs/en-US/user-manual/advanced-guide/blocks/6.block.jpg b/docs/en-US/user-manual/advanced-guide/blocks/6.block.jpg
new file mode 100755
index 000000000..b609af5a0
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/blocks/6.block.jpg differ
diff --git a/docs/en-US/user-manual/advanced-guide/blocks/6.collection-setting.gif b/docs/en-US/user-manual/advanced-guide/blocks/6.collection-setting.gif
new file mode 100755
index 000000000..d969e34e8
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/blocks/6.collection-setting.gif differ
diff --git a/docs/en-US/user-manual/advanced-guide/collections.md b/docs/en-US/user-manual/advanced-guide/collections.md
new file mode 100644
index 000000000..1b20a6835
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/collections.md
@@ -0,0 +1,42 @@
+# Collections
+
+Before developing a system, we usually have to abstract the business and build a data model. In NocoBase, the concept of a data collection is similar to that of a table in a relational database.
+
+Click the "Collections & Fields" button to enter the configuration interface. Here, you can add, edit and delete data collections.
+
+![4.collections.gif](./collections/4.collections.gif)
+
+## Field Types
+
+- Basic
+ - Single line text
+ - Long text
+ - Phone
+ - Email
+ - Number
+ - Percent
+ - Password
+ - Icon
+- Choices
+ - Checkbox
+ - Single select
+ - Multiple select
+ - Radio group
+ - Checkbox group
+ - China region
+- Media
+ - Attachment
+ - Markdown
+ - Rich Text
+- Date & Time
+ - Date
+ - Time
+- Relationship Type
+ - Link to
+ - Sub-table
+- System Info
+ - ID
+ - Created at
+ - Last updated at
+ - Created by
+ - Last updated by
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/collections/4.collections.gif b/docs/en-US/user-manual/advanced-guide/collections/4.collections.gif
new file mode 100755
index 000000000..dd0f01a4d
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/collections/4.collections.gif differ
diff --git a/docs/en-US/user-manual/advanced-guide/file-storages.md b/docs/en-US/user-manual/advanced-guide/file-storages.md
new file mode 100644
index 000000000..56970cc4d
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/file-storages.md
@@ -0,0 +1,11 @@
+# File Storages
+
+NocoBase file storage currently supports the following three methods
+
+- Local storage
+- Aliyun OSS
+- Amazon S3
+
+Click File storage to enter the configuration interface and add the appropriate information.
+
+![8.storage.gif](./file-storages/8.storage.gif)
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/file-storages/8.storage.gif b/docs/en-US/user-manual/advanced-guide/file-storages/8.storage.gif
new file mode 100755
index 000000000..c9edfa8f9
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/file-storages/8.storage.gif differ
diff --git a/docs/en-US/user-manual/advanced-guide/functional-zoning.md b/docs/en-US/user-manual/advanced-guide/functional-zoning.md
new file mode 100644
index 000000000..13b7c75b1
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/functional-zoning.md
@@ -0,0 +1,9 @@
+# Functional zoning
+
+NocoBase has a built-in layout template by default, and the interface of this layout template is divided into three main areas.
+
+1. Configuration entry area. Users with permissions can see the UI Editor, Collections & Fields, Roles and Permissions, block templates, Workflows, and other extended configuration options here.
+2. Menu area. At the top is the first level menu, and on the left side are the menus for the second level and lower tiers. Each menu item can be configured as a menu group, page, or link.
+3. Block container. This is the block container for the page, in which various blocks can be placed.
+
+![3.zone.jpg](./functional-zoning/3.zone.jpg)
diff --git a/docs/en-US/user-manual/advanced-guide/functional-zoning/3.zone.jpg b/docs/en-US/user-manual/advanced-guide/functional-zoning/3.zone.jpg
new file mode 100755
index 000000000..9507d2c7e
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/functional-zoning/3.zone.jpg differ
diff --git a/docs/en-US/user-manual/advanced-guide/menus.md b/docs/en-US/user-manual/advanced-guide/menus.md
new file mode 100644
index 000000000..08ae51210
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/menus.md
@@ -0,0 +1,32 @@
+# Menus
+
+The default menu location for NocoBase is at the top and on the left. The top is the first level menu and the left side is the menu for the second level and lower levels.
+
+Three types of menu items are supported.
+
+- Menu groups
+- Pages
+- Links
+
+Once you enter the UI Editor mode, you can add and edit menus, as well as sort menu items.
+
+## Add Menu Item
+
+![5.menu-add.jpg](./menus/5.menu-add.jpg)
+
+Click Add menu item to select the type to add. Support infinite level submenu.
+
+## Configure and Sort
+
+Move the cursor over the menu item and the Sort and Configure buttons will appear in the upper right corner. Press and hold the Sort button to drag and drop the sorting.
+
+Configurations that are operable on menu items:
+
+- Edit
+- Move to
+- Insert before
+- Insert after
+- Insert Inner
+- Delete
+
+![5.menu-edit.jpg](./menus/5.menu-edit.jpg)
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/menus/5.menu-add.jpg b/docs/en-US/user-manual/advanced-guide/menus/5.menu-add.jpg
new file mode 100755
index 000000000..da89a6f93
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/menus/5.menu-add.jpg differ
diff --git a/docs/en-US/user-manual/advanced-guide/menus/5.menu-edit.jpg b/docs/en-US/user-manual/advanced-guide/menus/5.menu-edit.jpg
new file mode 100755
index 000000000..0252465f7
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/menus/5.menu-edit.jpg differ
diff --git a/docs/en-US/user-manual/advanced-guide/plugins.md b/docs/en-US/user-manual/advanced-guide/plugins.md
new file mode 100644
index 000000000..779d515c6
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/plugins.md
@@ -0,0 +1 @@
+# Plugins
diff --git a/docs/en-US/user-manual/advanced-guide/plugins/Workflow 7229c53cffc8429dbf7acb58cac90a76.md b/docs/en-US/user-manual/advanced-guide/plugins/Workflow 7229c53cffc8429dbf7acb58cac90a76.md
new file mode 100755
index 000000000..d9afb34e2
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/plugins/Workflow 7229c53cffc8429dbf7acb58cac90a76.md
@@ -0,0 +1,3 @@
+# Workflow
+
+TO DO
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/roles-permissions.md b/docs/en-US/user-manual/advanced-guide/roles-permissions.md
new file mode 100644
index 000000000..1a9001f27
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/roles-permissions.md
@@ -0,0 +1,3 @@
+# Roles & Permissions
+
+TO DO
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/system-settings.md b/docs/en-US/user-manual/advanced-guide/system-settings.md
new file mode 100644
index 000000000..c9fc3da68
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/system-settings.md
@@ -0,0 +1,10 @@
+# System Settings
+
+Click System settings, the properties that can be configured include:
+
+- System title
+- Logo
+- Language
+- Allow sign up
+
+![9.system.gif](./system-settings/9.system.gif)
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/system-settings/9.system.gif b/docs/en-US/user-manual/advanced-guide/system-settings/9.system.gif
new file mode 100755
index 000000000..e1d26b471
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/system-settings/9.system.gif differ
diff --git a/docs/en-US/user-manual/advanced-guide/tabs.md b/docs/en-US/user-manual/advanced-guide/tabs.md
new file mode 100644
index 000000000..5ede09e00
--- /dev/null
+++ b/docs/en-US/user-manual/advanced-guide/tabs.md
@@ -0,0 +1,9 @@
+# Tabs
+
+In a single record page or popup, you can add multiple tabs and add different blocks to each tab to display different content and actions. For example, in a customer information popup, add 3 tabs to display customer's personal information, order history, customer reviews.
+
+![7.tabs.gif](./tabs/7.tabs.gif)
+
+Or, in an order record to be shipped, place a form block in the first tab for quick shipping, a block of associated data in the second tab to display the order items for the current order, and an order details block in the third tab.
+
+![7.tabs-2.gif](./tabs/7.tabs-2.gif)
\ No newline at end of file
diff --git a/docs/en-US/user-manual/advanced-guide/tabs/7.tabs-2.gif b/docs/en-US/user-manual/advanced-guide/tabs/7.tabs-2.gif
new file mode 100755
index 000000000..3699ad9e7
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/tabs/7.tabs-2.gif differ
diff --git a/docs/en-US/user-manual/advanced-guide/tabs/7.tabs.gif b/docs/en-US/user-manual/advanced-guide/tabs/7.tabs.gif
new file mode 100755
index 000000000..df7c895aa
Binary files /dev/null and b/docs/en-US/user-manual/advanced-guide/tabs/7.tabs.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started.md b/docs/en-US/user-manual/introduction/5-minutes-to-get-started.md
new file mode 100644
index 000000000..79140da38
--- /dev/null
+++ b/docs/en-US/user-manual/introduction/5-minutes-to-get-started.md
@@ -0,0 +1,91 @@
+# 5 minutes to get started
+
+Let's take 5 minutes to build an order management system using NocoBase.
+
+## 1. Create data collections and fields
+
+In this order management system, we need to have the information of `Customers`,`Products`,`Orders` which are interrelated with each other. We need to create 4 data tables and their fields as follows:
+
+- Customers
+ - Name
+ - Birthday
+ - Gender
+ - Phone
+ - Orders (All orders purchased, data from `Orders`, each customer data contains multiple order data)
+- Products
+ - Product name
+ - Description
+ - Images
+ - Price
+ - Order Details (In which orders the product was purchased, data from `Order Details`, each product data belongs to multiple order details data)
+- Orders
+ - Serial number
+ - Total
+ - Note
+ - Address
+ - Customer (Customers who own the order, data from `Customers`, each order data belongs to a customer data)
+ - Order details (The products in the order, data from `Order Details`, each order data contains multiple order details data)
+- Order Details
+ - Order (The order to which the detail belongs, data from `Orders`, each order detail data belongs to an order data)
+ - Product (The products contained in this detail, data from `Products`, each order detail data contains a product data)
+ - Quantity
+
+Where the fields with underscores are relational fields, associated to other data tables.
+
+Next, click the "Collections & Fields" button to enter the Configuration screen and create the first Collection `Customers`.
+
+![1.customers.gif](./5-minutes-to-get-started/1.customers.gif)
+
+Then click on "Configure fields" to add a name field for `Customers`, which is a Single line text type.
+
+![2.field.gif](./5-minutes-to-get-started/2.field.gif)
+
+In the same way, add Birthday, Gender, and Phone for `Customers`, which are the Datetime type, Radio group type, and Phone type respectively.
+
+![1.fields.jpg](./5-minutes-to-get-started/1.fields.jpg)
+
+In the same way, create Collections `Products`, `Orders`, `Order Details` and their fields.
+
+![1.collections.jpg](./5-minutes-to-get-started/1.collections.jpg)
+
+
+
+In this case, for the relationship fields, we have to select the Link to type, thus creating an association between the data collections. In this example, we associate `Products` with `Orders` and use `Order Details` as an junction collection.
+
+![1.relation.jpg](./5-minutes-to-get-started/1.relation.jpg)
+
+Once the data collections and fields are created, we start making the interface.
+
+## 2. Configure menus and pages
+
+We need three pages for customers, orders, and products to display and manage our data.
+
+Click the UI Editor button to enter the interface configuration mode. In this mode, we can add menu items, add pages, and arrange blocks within the pages.
+
+![1.editor.gif](./5-minutes-to-get-started/1.editor.gif)
+
+Click Add menu item, add menu groups "Customers" and "Orders & Products", then add submenu pages "All Orders" and "Products".
+
+![1.menu.gif](./5-minutes-to-get-started/1.menu.gif)
+
+After adding menus and pages, we can add and configure blocks within the pages.
+
+## 3. Adding and Configuring Blocks
+
+NocoBase currently supports table, kanban, calendar, form, details, and other types of blocks that present data from a data collection and allow manipulation of the data. Obviously, customers, orders, and products are suitable for displaying and manipulating in a table block.
+
+We add a table block to the "All Orders" page, select Collection `Orders` as the data source, and configure the columns to be displayed for this table block.
+
+![1.block.gif](./5-minutes-to-get-started/1.block.gif)
+
+Configure actions for this table block, including filter, add, delete, view, and edit.
+
+![1.action.gif](./5-minutes-to-get-started/1.action.gif)
+
+Configure form and detail blocks for add, edit, view actions.
+
+![1.action-block.gif](./5-minutes-to-get-started/1.action-block.gif)
+
+Then, lay out the form blocks on the Products and Customers pages with the same method. When you are done, exit the UI Editor mode and enter the usage mode, and a simple order management system is completed.
+
+![1.finished.gif](./5-minutes-to-get-started/1.finished.gif)
\ No newline at end of file
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.action-block.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.action-block.gif
new file mode 100755
index 000000000..db4d312de
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.action-block.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.action.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.action.gif
new file mode 100755
index 000000000..f8a8f2ba6
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.action.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.block.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.block.gif
new file mode 100755
index 000000000..b2cbbcb79
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.block.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.collections.jpg b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.collections.jpg
new file mode 100755
index 000000000..a03de2c37
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.collections.jpg differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.customers.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.customers.gif
new file mode 100755
index 000000000..eafca0b67
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.customers.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.editor.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.editor.gif
new file mode 100755
index 000000000..d5e7a84df
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.editor.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.fields.jpg b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.fields.jpg
new file mode 100755
index 000000000..79195e552
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.fields.jpg differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.finished.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.finished.gif
new file mode 100755
index 000000000..be301d4ea
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.finished.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.menu.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.menu.gif
new file mode 100755
index 000000000..d1f43c62a
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.menu.gif differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.relation.jpg b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.relation.jpg
new file mode 100755
index 000000000..8f5bce152
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/1.relation.jpg differ
diff --git a/docs/en-US/user-manual/introduction/5-minutes-to-get-started/2.field.gif b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/2.field.gif
new file mode 100755
index 000000000..c544c710a
Binary files /dev/null and b/docs/en-US/user-manual/introduction/5-minutes-to-get-started/2.field.gif differ
diff --git a/docs/en-US/user-manual/introduction/important-features.md b/docs/en-US/user-manual/introduction/important-features.md
new file mode 100644
index 000000000..9eb650f64
--- /dev/null
+++ b/docs/en-US/user-manual/introduction/important-features.md
@@ -0,0 +1,19 @@
+# Important Features
+
+## 1. Separate "data structure" and "user interface"
+
+Most form-, table-, or process-driven codeless products create data structures directly in the user interface, such as Airtable, where adding a new column to a table is adding a new field. This has the advantage of simplicity of use, but the disadvantage of limited functionality and flexibility to meet the needs of more complex scenarios.
+
+NocoBase adopts the design idea of separating the data structure from the user interface, allowing you to create any number of blocks (data views) for the data collections, with different type, styles, content, and actions in each block. This takes into account the simplicity of codeless operation, but also the flexibility of native development.
+
+![2.collection-block.png](./important-features/2.collection-block.png)
+
+## 2. Separate "system configuration" and "system usage"
+
+NocoBase is used to develop relatively complex business systems. In these scenarios, we want the system developers and the system users to be different roles. The user sees a mature, well-designed system, like a product developed natively, rather than a rigid, drag-and-drop free system that can be modified at any time; while the developer can quickly develop the system using a WYSIWYG approach.
+
+![2.user-root.gif](./important-features/2.user-root.gif)
+
+## 3. Everything is plugins
+
+NocoBase adopts plugin architecture, all new features can be implemented by developing and installing plugins. In the future, we will build a plug-in marketplace where extending functionality is as easy as installing an APP on your phone.
diff --git a/docs/en-US/user-manual/introduction/important-features/2.collection-block.png b/docs/en-US/user-manual/introduction/important-features/2.collection-block.png
new file mode 100755
index 000000000..7389064cb
Binary files /dev/null and b/docs/en-US/user-manual/introduction/important-features/2.collection-block.png differ
diff --git a/docs/en-US/user-manual/introduction/important-features/2.user-root.gif b/docs/en-US/user-manual/introduction/important-features/2.user-root.gif
new file mode 100755
index 000000000..92d668c14
Binary files /dev/null and b/docs/en-US/user-manual/introduction/important-features/2.user-root.gif differ
diff --git a/docs/en-US/user-manual/introduction/why-nocobase.md b/docs/en-US/user-manual/introduction/why-nocobase.md
new file mode 100644
index 000000000..8452e5027
--- /dev/null
+++ b/docs/en-US/user-manual/introduction/why-nocobase.md
@@ -0,0 +1,9 @@
+# Why NocoBase
+
+NocoBase is designed for you if you have the following needs.
+
+- Develop an internal management system
+- Meet most of your business needs with codeless development
+- Extremely easy to extend to meet your individual needs
+- Private deployment with full control of code and data
+- Free to use or you can pay for more technical support
\ No newline at end of file
diff --git a/docs/en-US/who.md b/docs/en-US/who.md
new file mode 100644
index 000000000..9030644f2
--- /dev/null
+++ b/docs/en-US/who.md
@@ -0,0 +1,10 @@
+# Who is NocoBase for
+
+NocoBase is designed for you if you have the following needs.
+
+- Develop an internal management system
+- Meet most of your business needs with no-code development
+- Meet particular needs with regular development
+- The system requires frequent changes
+- Private deployment with full control of code and data
+- Free to use or pay for more technical support
diff --git a/docs/en-US/why.md b/docs/en-US/why.md
new file mode 100644
index 000000000..c0ffe1204
--- /dev/null
+++ b/docs/en-US/why.md
@@ -0,0 +1,21 @@
+# Why NocoBase is different
+
+## 1. Separate "data structure" and "user interface"
+
+Most form-, table-, or process-driven codeless products create data structures directly in the user interface, such as Airtable, where adding a new column to a table is adding a new field. This has the advantage of simplicity of use, but the disadvantage of limited functionality and flexibility to meet the needs of more complex scenarios.
+
+NocoBase adopts the design idea of separating the data structure from the user interface, allowing you to create any number of blocks (data views) for the data collections, with different type, styles, content, and actions in each block. This takes into account the simplicity of codeless operation, but also the flexibility like native development.
+
+![2.collection-block.png](./user-manual/introduction/important-features/2.collection-block.png)
+
+## 2. Separate "system configuration" and "system usage"
+
+NocoBase is used to develop relatively complex business systems. In these scenarios, we want the system developers and the system users to be different roles. The user sees a mature, well-designed system, like a product developed natively, rather than a rigid, drag-and-drop free system that can be modified at any time; while the developer can quickly develop the system using a WYSIWYG approach.
+
+![2.user-root.gif](./user-manual/introduction/important-features/2.user-root.gif)
+
+## 3. Everything is plugins
+
+NocoBase adopts plugin architecture, all new features can be implemented by developing and installing plugins. In the future, we will build a plug-in marketplace where extending functionality is as easy as installing an APP on your phone.
+
+![](https://www.nocobase.com/images/NocoBaseMindMapLite.png)
diff --git a/docs/menus.ts b/docs/menus.ts
new file mode 100644
index 000000000..2bc77508b
--- /dev/null
+++ b/docs/menus.ts
@@ -0,0 +1,139 @@
+export default [
+ {
+ title: 'Welcome',
+ 'title.zh-CN': '欢迎',
+ type: 'group',
+ children: [
+ '/index',
+ '/why',
+ '/who',
+ '/roadmap',
+ ],
+ },
+ {
+ title: 'Getting started',
+ 'title.zh-CN': '快速开始',
+ type: 'group',
+ children: [
+ {
+ title: 'Installation',
+ 'title.zh-CN': '安装',
+ type: 'subMenu',
+ children: [
+ '/getting-started/installation/overview',
+ '/getting-started/installation/docker-compose',
+ '/getting-started/installation/create-nocobase-app',
+ '/getting-started/installation/git-clone',
+ ],
+ },
+ '/getting-started/upgrading',
+ ],
+ },
+ {
+ title: 'User manual',
+ 'title.zh-CN': '用户手册',
+ type: 'group',
+ children: [
+ '/user-manual/introduction/5-minutes-to-get-started',
+ {
+ title: 'Advanced guide',
+ 'title.zh-CN': '深入 NocoBase',
+ type: 'subMenu',
+ children: [
+ '/user-manual/advanced-guide/functional-zoning',
+ '/user-manual/advanced-guide/collections',
+ '/user-manual/advanced-guide/menus',
+ '/user-manual/advanced-guide/blocks',
+ '/user-manual/advanced-guide/actions',
+ '/user-manual/advanced-guide/roles-permissions',
+ '/user-manual/advanced-guide/tabs',
+ '/user-manual/advanced-guide/file-storages',
+ '/user-manual/advanced-guide/system-settings',
+ '/user-manual/advanced-guide/plugins',
+ ],
+ },
+ ],
+ },
+ {
+ title: 'Development',
+ 'title.zh-CN': '开发指南',
+ type: 'group',
+ children: [
+ '/development/directory-structure',
+ '/development/env',
+ '/development/nocobase-cli',
+ {
+ title: 'HTTP API',
+ 'title.zh-CN': 'HTTP API',
+ type: 'subMenu',
+ children: [
+ '/development/http-api/index',
+ '/development/http-api/rest-api',
+ '/development/http-api/action-api',
+ '/development/http-api/javascript-sdk',
+ '/development/http-api/filter-operators',
+ ],
+ },
+ '/development/javascript-sdk',
+ {
+ title: 'Plugin development',
+ 'title.zh-CN': '插件开发',
+ type: 'subMenu',
+ children: [
+ '/development/plugin-development/index',
+ {
+ title: 'Server',
+ 'title.zh-CN': 'Server',
+ type: 'subMenu',
+ children: [
+ '/development/plugin-development/server/overview',
+ '/development/plugin-development/server/database',
+ '/development/plugin-development/server/resourcer',
+ '/development/plugin-development/server/middleware',
+ '/development/plugin-development/server/acl',
+ '/development/plugin-development/server/events',
+ '/development/plugin-development/server/i18n',
+ '/development/plugin-development/server/cli',
+ '/development/plugin-development/server/app-manager',
+ '/development/plugin-development/server/plugin-manager',
+ ],
+ },
+ {
+ title: 'Client',
+ 'title.zh-CN': 'Client',
+ type: 'subMenu',
+ children: [
+ '/development/plugin-development/client/overview',
+ {
+ title: 'Providers',
+ 'title.zh-CN': 'Providers',
+ type: 'subMenu',
+ children: [
+ '/development/plugin-development/client/providers/acl',
+ '/development/plugin-development/client/providers/antd',
+ '/development/plugin-development/client/providers/api-client',
+ '/development/plugin-development/client/providers/collection-manager',
+ '/development/plugin-development/client/providers/i18n',
+ '/development/plugin-development/client/providers/route-switch',
+ '/development/plugin-development/client/providers/schema-component',
+ '/development/plugin-development/client/providers/schema-initializer',
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ title: 'Community',
+ 'title.zh-CN': '社区',
+ type: 'group',
+ children: [
+ '/contributing',
+ '/release-notes',
+ '/faq',
+ '/thanks',
+ ],
+ }
+];
diff --git a/docs/zh-CN/contributing.md b/docs/zh-CN/contributing.md
new file mode 100644
index 000000000..0c3e240be
--- /dev/null
+++ b/docs/zh-CN/contributing.md
@@ -0,0 +1,47 @@
+# 贡献
+
+- Fork 源代码到自己的仓库
+- 修改源代码
+- 提交 Pull Request
+
+## 下载项目
+
+```bash
+# 替换为自己的仓库地址
+git clone https://github.com/nocobase/nocobase.git
+cd nocobase
+yarn install
+```
+
+## 应用开发与测试
+
+```bash
+# 安装并启动应用
+yarn dev
+# 运行所有测试
+yarn test
+# 运行文件夹下所有测试文件
+yarn test
+# 运行单个测试文件
+yarn test
+```
+
+## 文档预览
+
+```bash
+# 启动文档
+yarn doc --lang=zh-CN
+yarn doc --lang=en-US
+```
+
+文档在 docs 目录下,遵循 Markdown 语法
+
+```bash
+|- /docs/
+ |- en-US
+ |- zh-CN
+```
+
+## 其他
+
+更多 Commands 使用说明 [参考 NocoBase CLI 章节](./development/nocobase-cli.md)
\ No newline at end of file
diff --git a/docs/zh-CN/development/directory-structure.md b/docs/zh-CN/development/directory-structure.md
new file mode 100644
index 000000000..1db911267
--- /dev/null
+++ b/docs/zh-CN/development/directory-structure.md
@@ -0,0 +1,89 @@
+# 目录结构
+
+## 应用脚手架
+
+```bash
+$ yarn create nocobase-app my-nocobase-app
+```
+
+通过 `create-nocobase-app` 创建的应用脚手架目录结构如下:
+
+```bash
+├── my-nocobase-app
+ ├── packages # 采用 Monorepo 的方式管理代码,将不同模块划分到不同包里
+ ├── app
+ ├── client # 客户端模块
+ ├── server # 服务端模块
+ ├── plugins # 插件目录
+ ├── storages # 用于存放数据库文件、附件、缓存等
+ ├── db
+ ├── .env # 环境变量
+ ├── .buildrc.ts # packages 的打包配置,支持 cjs、esm 和 umd 三种格式的打包。
+ ├── jest.config.js
+ ├── jest.setup.ts
+ ├── lerna.json
+ ├── package.json
+ ├── tsconfig.jest.json
+ ├── tsconfig.json
+ ├── tsconfig.server.json
+```
+
+### packages 目录
+
+```bash
+├── packages
+ ├── app
+ ├── client
+ ├── public
+ ├── src
+ ├── pages
+ ├── index.tsx
+ ├── .umirc.ts
+ ├── package.json
+ ├── server
+ ├── src
+ ├── config
+ ├── index.ts
+ ├── package.json
+ ├── /plugins
+ ├── my-plugin
+ ├── src
+ ├── package.json
+```
+
+NocoBase 采用 Monorepo 的方式管理代码,将不同模块划分到不同包里。
+
+- `app/client` 为应用的客户端模块,基于 [umi](https://umijs.org/zh-CN) 构建;
+- `app/server` 为应用的服务端模块;
+- `plugins/*` 目录里可以放各种插件。
+
+### storages 目录
+
+用于存放数据库文件、附件、缓存等。
+
+### .env 文件
+
+环境变量。
+
+### .buildrc.ts 文件
+
+packages 的打包配置,支持 cjs、esm 和 umd 三种格式的打包。
+
+## 插件脚手架
+
+```bash
+$ yarn nocobase create-plugin my-plugin
+```
+
+通过 `nocobase create-plugin` 初始化的插件脚手架目录如下:
+
+```bash
+├── my-nocobase-app
+ ├── packages
+ ├── plugins
+ ├── my-plugin
+ ├── src
+ ├── client
+ ├── server
+ ├── package.json
+```
diff --git a/docs/zh-CN/development/env.md b/docs/zh-CN/development/env.md
new file mode 100644
index 000000000..29e3c31af
--- /dev/null
+++ b/docs/zh-CN/development/env.md
@@ -0,0 +1,207 @@
+# 环境变量
+
+## 全局环境变量
+
+保存在 `.env` 文件里
+
+### APP_ENV
+
+应用环境,默认值 `development`,可选项包括:
+
+- `production` 生产环境
+- `development` 开发环境
+
+```bash
+APP_ENV=production
+```
+
+### APP_HOST
+
+应用主机,默认值 `0.0.0.0`
+
+```bash
+APP_HOST=192.168.3.154
+```
+
+### APP_PORT
+
+应用端口,默认值 `13000`
+
+```bash
+APP_PORT=13000
+```
+
+### APP_KEY
+
+秘钥,用于 jwt 等场景
+
+```bash
+APP_KEY=app-key-test
+```
+
+### API_BASE_PATH
+
+NocoBase API 地址前缀,默认值 `/api/`
+
+```bash
+API_BASE_PATH=/api/
+```
+
+### DB_DIALECT
+
+数据库类型,默认值 `sqlite`,可选项包括:
+
+- `sqlite`
+- `mysql`
+- `postgres`
+
+```bash
+DB_DIALECT=mysql
+```
+
+### DB_STORAGE
+
+数据库文件路径(使用 SQLite 数据库时配置)
+
+```bash
+# 相对路径
+DB_HOST=storage/db/nocobase.db
+# 绝对路径
+DB_HOST=/your/path/nocobase.db
+```
+
+### DB_HOST
+
+数据库主机(使用 mysql 或 postgres 数据库时需要配置)
+
+默认值 `localhost`
+
+```bash
+DB_HOST=localhost
+```
+
+### DB_PORT
+
+数据库端口(使用 mysql 或 postgres 数据库时需要配置)
+
+- MySQL 默认端口 3356
+- PostgreSQL 默认端口 5432
+
+```bash
+DB_PORT=3356
+```
+
+### DB_DATABASE
+
+数据库名(使用 mysql 或 postgres 数据库时需要配置)
+
+```bash
+DB_DATABASE=nocobase
+```
+
+### DB_USER
+
+数据库用户(使用 mysql 或 postgres 数据库时需要配置)
+
+```bash
+DB_USER=nocobase
+```
+
+### DB_PASSWORD
+
+数据库密码(使用 mysql 或 postgres 数据库时需要配置)
+
+```bash
+DB_PASSWORD=nocobase
+```
+
+### DB_TABLE_PREFIX
+
+数据表前缀
+
+```bash
+DB_TABLE_PREFIX=nocobase_
+```
+
+### DB_LOGGING
+
+数据库日志开关,默认值 `off`,可选项包括:
+
+- `on` 打开
+- `off` 关闭
+
+```bash
+DB_LOGGING=on
+```
+
+## 临时环境变量
+
+安装 NocoBase 时,可以通过设置临时的环境变量来辅助安装,如:
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=zh-CN \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ INIT_ROOT_PASSWORD=admin123 \
+ INIT_ROOT_NICKNAME="Super Admin" \
+ nocobase install
+
+# 等同于
+yarn nocobase install \
+ --lang=zh-CN \
+ --root-email=demo@nocobase.com \
+ --root-password=admin123 \
+ --root-nickname="Super Admin"
+
+# 等同于
+yarn nocobase install -l zh-CN -e demo@nocobase.com -p admin123 -n "Super Admin"
+```
+
+### INIT_APP_LANG
+
+安装时的语言,默认值 `en-US`,可选项包括:
+
+- `en-US`
+- `zh-CN`
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=zh-CN \
+ nocobase install
+```
+
+### INIT_ROOT_EMAIL
+
+Root 用户邮箱
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=zh-CN \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ nocobase install
+```
+
+### INIT_ROOT_PASSWORD
+
+Root 用户密码
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=zh-CN \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ INIT_ROOT_PASSWORD=admin123 \
+ nocobase install
+```
+
+### INIT_ROOT_NICKNAME
+
+Root 用户昵称
+
+```bash
+yarn cross-env \
+ INIT_APP_LANG=zh-CN \
+ INIT_ROOT_EMAIL=demo@nocobase.com \
+ INIT_ROOT_PASSWORD=admin123 \
+ INIT_ROOT_NICKNAME="Super Admin" \
+ nocobase install
+```
diff --git a/docs/zh-CN/development/http-api/action-api.md b/docs/zh-CN/development/http-api/action-api.md
new file mode 100644
index 000000000..a2208e2c3
--- /dev/null
+++ b/docs/zh-CN/development/http-api/action-api.md
@@ -0,0 +1,146 @@
+# Action API
+
+## Common
+
+---
+
+Collection 和 Association 资源通用。
+
+### `create`
+
+```bash
+POST /api/users:create?whitelist=a,b&blacklist=c,d
+
+{} # Request Body
+```
+
+- Parameters
+ - whitelist 白名单
+ - blacklist 黑名单
+- Request body: 待插入的 JSON 数据
+- Response body data: 已创建的数据 JSON
+
+#### 新增用户
+
+```bash
+POST /api/users:create
+
+Request Body
+{
+ "email": "demo@nocobase.com",
+ "name": "Admin"
+}
+
+Response 200 (application/json)
+{
+ "data": {},
+ "meta": {}
+}
+```
+
+#### 新增用户文章
+
+```bash
+POST /api/users/1/posts:create
+
+Request Body
+{
+ "title": "My first post"
+}
+
+Response 200 (application/json)
+{
+ "data": {},
+ "meta": {}
+}
+```
+
+#### Request Body 里的 association
+
+```bash
+POST /api/posts:create
+
+Request Body
+{
+ "title": "My first post",
+ "user": 1
+}
+
+Response 200 (application/json)
+{
+ "data": {
+ "id": 1,
+ "title": "My first post",
+ "userId": 1,
+ "user": {
+ "id": 1
+ }
+ },
+ "meta": {}
+}
+```
+
+### `update`
+
+```bash
+POST /api/users:create?filterByTk=1&whitelist=a,b&blacklist=c,d
+
+{} # Request Body
+```
+
+- Parameters
+ - whitelist 白名单
+ - blacklist 黑名单
+ - filterByTk 根据 tk 字段过滤,默认情况 tk 为数据表的主键
+ - filter 过滤,支持 json string
+- Request body: 待更新的 JSON 数据
+
+#### Request Body 里的 association
+
+```bash
+POST /api/posts:update/1
+
+Request Body
+{
+ "title": "My first post 2",
+ "user": 2
+}
+
+Response 200 (application/json)
+{
+ "data": [
+ {
+ "id": 1,
+ "title": "My first post 2",
+ "userId": 2,
+ "user": {
+ "id": 2
+ }
+ }
+ ],
+ "meta": {}
+}
+```
+
+### `list`
+
+### `get`
+
+### `destroy`
+
+### `move`
+
+## Association
+
+---
+
+### `add`
+
+### `set`
+
+### `remove`
+
+### `toggle`
+
+
+
diff --git a/docs/zh-CN/development/http-api/filter-operators.md b/docs/zh-CN/development/http-api/filter-operators.md
new file mode 100644
index 000000000..b74cc80ae
--- /dev/null
+++ b/docs/zh-CN/development/http-api/filter-operators.md
@@ -0,0 +1,59 @@
+# Filter operators
+
+## 通用
+
+- $eq
+- $ne
+- $gte
+- $gt
+- $lte
+- $lt
+- $not
+- $is
+- $in
+- $notIn
+- $like
+- $notLike
+- $iLike
+- $notILike
+- $and
+- $or
+- $empty
+- $notEmpty
+
+## array
+
+- $match
+- $notMatch
+- $anyOf
+- $noneOf
+- $arrayEmpty
+- $arrayNotEmpty
+
+## association
+
+- $exists
+- $notExists
+
+## boolean
+
+- $truthy
+- $falsy
+
+## date
+
+- $dateOn
+- $dateNotOn
+- $dateBefore
+- $dateNotBefore
+- $dateAfter
+- $dateNotAfter
+
+## string
+
+- $includes
+- $notIncludes
+- $startsWith
+- $notStartsWith
+- $endWith
+- $notEndWith
\ No newline at end of file
diff --git a/docs/zh-CN/development/http-api/index.md b/docs/zh-CN/development/http-api/index.md
new file mode 100644
index 000000000..328400898
--- /dev/null
+++ b/docs/zh-CN/development/http-api/index.md
@@ -0,0 +1,307 @@
+# 概述
+
+NocoBase 的 HTTP API 基于 Resource & Action 设计,是 REST API 的超集,操作不局限于增删改查,在 NocoBase 里,Resource Action 可以任意的扩展。
+
+## 资源 Resource
+
+在 NocoBase 里,资源(resource)有两种表达方式:
+
+- ``
+- `.`
+
+
+
+- collection 是所有抽象数据的集合
+- association 为 collection 的关联数据
+- resource 包括 collection 和 collection.association 两类
+
+
+
+### 示例
+
+- `posts` 文章
+- `posts.user` 文章用户
+- `posts.tags` 文章标签
+
+## 操作 Action
+
+以 `:` 的方式表示资源操作
+
+- `:`
+- `.:`
+
+内置的全局操作,可用于 collection 或 association
+
+- `create`
+- `get`
+- `list`
+- `update`
+- `destroy`
+- `move`
+
+内置的关联操作,仅用于 association
+
+- `set`
+- `add`
+- `remove`
+- `toggle`
+
+### 示例
+
+- `posts:create` 创建文章
+- `posts.user:get` 查看文章用户
+- `posts.tags:add` 附加文章标签(将现有的标签与文章关联)
+
+## 请求 URL
+
+```bash
+ /api/:
+ /api/:/
+ /api///:
+ /api///:/
+```
+
+### 示例
+
+posts 资源
+
+```bash
+POST /api/posts:create
+GET /api/posts:list
+GET /api/posts:get/1
+POST /api/posts:update/1
+POST /api/posts:destroy/1
+```
+
+posts.comments 资源
+
+```bash
+POST /api/posts/1/comments:create
+GET /api/posts/1/comments:list
+GET /api/posts/1/comments:get/1
+POST /api/posts/1/comments:update/1
+POST /api/posts/1/comments:destroy/1
+```
+
+posts.tags 资源
+
+```bash
+POST /api/posts/1/tags:create
+GET /api/posts/1/tags:get
+GET /api/posts/1/tags:list
+POST /api/posts/1/tags:update
+POST /api/posts/1/tags:destroy
+POST /api/posts/1/tags:add
+GET /api/posts/1/tags:remove
+```
+
+## 资源定位
+
+- collection 资源,通过 `collectionIndex` 定位到待处理的数据,`collectionIndex` 必须唯一
+- association 资源,通过 `collectionIndex` 和 `associationIndex` 联合定位待处理的数据,`associationIndex` 可能不是唯一的,但是 `collectionIndex` 和 `associationIndex` 的联合索引必须唯一
+
+查看 association 资源详情时,请求的 URL 需要同时提供 `` 和 ``,`` 并不多余,因为 `` 可能不是唯一的。
+
+例如 `tables.fields` 表示数据表的字段
+
+```bash
+GET /api/tables/table1/fields/title
+GET /api/tables/table2/fields/title
+```
+
+table1 和 table2 都有 title 字段,title 在 table1 里是唯一的,但是其他表也可能有 title 字段
+
+## 请求参数
+
+请求的参数可以放在 Request 的 headers、parameters(query string)、body(GET 请求没有 body) 里。
+
+几个特殊的 Parameters 请求参数
+
+- `filter` 数据过滤,用于查询相关操作里;
+- `filterByTk` 根据 tk 字段字过滤,用于指定详情数据的操作里;
+- `sort` 排序,用于查询相关操作里。
+- `fields` 输出哪些数据,用于查询相关操作里;
+- `appends` 附加关系字段,用于查询相关操作里;
+- `except` 排除哪些字段(不输出),用于查询相关操作里;
+- `whitelist` 字段白名单,用于数据的创建和更新相关操作里;
+- `blacklist` 字段黑名单,用于数据的创建和更新相关操作里;
+
+### filter
+
+数据过滤
+
+```bash
+# simple
+GET /api/posts?filter[status]=publish
+# 推荐使用 json string 的格式,需要 encodeURIComponent 编码
+GET /api/posts?filter={"status":"published"}
+
+# filter operators
+GET /api/posts?filter[status.$eq]=publish
+GET /api/posts?filter={"status.$eq":"published"}
+
+# $and
+GET /api/posts?filter={"$and": [{"status.$eq":"published"}, {"title.$includes":"a"}]}
+# $or
+GET /api/posts?filter={"$or": [{"status.$eq":"pending"}, {"status.$eq":"draft"}]}
+
+# association field
+GET /api/posts?filter[user.email.$includes]=gmail
+GET /api/posts?filter={"user.email.$includes":"gmail"}
+```
+
+[点此查看更多关于 filter operators 的内容](http-api/filter-operators)
+
+### filterByTk
+
+根据 tk 字段过滤,默认情况:
+
+- collection 资源,tk 为数据表的主键;
+- association 资源,tk 为 association 的 targetKey 字段。
+
+```bash
+GET /api/posts:get?filterByTk=1&fields=name,title&appends=tags
+```
+
+### sort
+
+排序。降序时,字段前面加上减号 `-`。
+
+```bash
+# createAt 字段升序
+GET /api/posts:get?sort=createdAt
+# createAt 字段降序
+GET /api/posts:get?sort=-createdAt
+# 多个字段联合排序,createAt 字段降序、title A-Z 升序
+GET /api/posts:get?sort=-createdAt,title
+```
+
+### fields
+
+输出哪些数据
+
+```bash
+GET /api/posts:list?fields=name,title
+
+Response 200 (application/json)
+{
+ "data": [
+ {
+ "name": "",
+ "title": ""
+ }
+ ],
+ "meta": {}
+}
+```
+
+### appends
+
+附加关系字段
+
+### except
+
+排除哪些字段(不输出),用于查询相关操作里;
+
+### whitelist
+
+白名单
+
+```bash
+POST /api/posts:create?whitelist=title
+
+{
+ "title": "My first post",
+ "date": "2022-05-19" # date 字段会被过滤掉,不会写入数据库
+}
+```
+
+### blacklist
+
+黑名单
+
+```bash
+POST /api/posts:create?blacklist=date
+
+{
+ "title": "My first post",
+ "date": "2022-05-19" # date 字段会被过滤掉,不会写入数据库
+}
+```
+
+## 请求响应
+
+响应的格式
+
+```ts
+type ResponseResult = {
+ data?: any; // 主体数据
+ meta?: any; // 附加数据
+ errors?: ResponseError[]; // 报错
+};
+
+type ResponseError = {
+ code?: string;
+ message: string;
+};
+```
+
+### 示例
+
+查看列表
+
+```bash
+GET /api/posts:list
+
+Response 200 (application/json)
+
+{
+ data: [
+ {
+ id: 1
+ }
+ ],
+ meta: {
+ count: 1
+ page: 1,
+ pageSize: 1,
+ totalPage: 1
+ },
+}
+```
+
+查看详情
+
+```bash
+GET /api/posts:get/1
+
+Response 200 (application/json)
+
+{
+ data: {
+ id: 1
+ },
+ meta: {
+ count: 1
+ page: 1,
+ pageSize: 1,
+ totalPage: 1
+ },
+}
+```
+
+报错
+
+```bash
+POST /api/posts:create
+
+Response 400 (application/json)
+
+{
+ errors: [
+ {
+ message: 'name must be required',
+ },
+ ],
+}
+```
\ No newline at end of file
diff --git a/docs/zh-CN/development/http-api/javascript-sdk.md b/docs/zh-CN/development/http-api/javascript-sdk.md
new file mode 100644
index 000000000..d14cf9cff
--- /dev/null
+++ b/docs/zh-CN/development/http-api/javascript-sdk.md
@@ -0,0 +1,229 @@
+# JavaScript SDK
+
+## APIClient
+
+```ts
+class APIClient {
+ // axios 实例
+ axios: AxiosInstance;
+ // 构造器
+ constructor(instance?: AxiosInstance | AxiosRequestConfig);
+ // 客户端请求,支持 AxiosRequestConfig 和 ResourceActionOptions
+ request, D = any>(config: AxiosRequestConfig | ResourceActionOptions): Promise;
+ // 获取资源
+ resource(name: string, of?: any): R;
+}
+```
+
+初始化实例
+
+```ts
+import axios from 'axios';
+import { APIClient } from '@nocobase/sdk';
+
+// 提供 AxiosRequestConfig 配置参数
+const api = new APIClient({
+ baseURL: 'https://localhost:8000/api',
+});
+
+// 提供 AxiosInstance
+const instance = axios.create({
+ baseURL: 'https://localhost:8000/api',
+});
+const api = new APIClient(instance);
+```
+
+## Mock
+
+```ts
+import { APIClient } from '@nocobase/sdk';
+import MockAdapter from 'axios-mock-adapter';
+
+const api = new APIClient({
+ baseURL: 'https://localhost:8000/api',
+});
+
+const mock = new MockAdapter(api.axios);
+
+mock.onGet('users:get').reply(200, {
+ data: { id: 1, name: 'John Smith' },
+});
+
+await api.request({ url: 'users:get' });
+```
+
+## Auth
+
+```ts
+// 直接传 token
+api.auth.token = '123';
+// 或者通过 signIn 登录
+api.auth.signIn();
+// 注销并删除 token 缓存
+api.auth.signOut();
+```
+
+## Request
+
+```ts
+// url
+await api.request({
+ url: 'users:list',
+ // request params
+ params: {
+ filter: {
+ 'email.$includes': 'noco',
+ },
+ },
+ // request body
+ data,
+});
+
+// resource & action
+await api.request({
+ resource: 'users',
+ action: 'list',
+ // action params
+ params: {
+ filter: {
+ 'email.$includes': 'noco',
+ },
+ page: 1,
+ },
+});
+```
+
+## Resource action
+
+```ts
+await api.resource('collection')[action]();
+await api.resource('collection.association', collectionId)[action]();
+```
+
+## Action API
+
+```ts
+await api.resource('collection').create();
+await api.resource('collection').get();
+await api.resource('collection').list();
+await api.resource('collection').update();
+await api.resource('collection').destroy();
+await api.resource('collection.association', collectionId).create();
+await api.resource('collection.association', collectionId).get();
+await api.resource('collection.association', collectionId).list();
+await api.resource('collection.association', collectionId).update();
+await api.resource('collection.association', collectionId).destroy();
+```
+
+### `get`
+
+```ts
+interface Resource {
+ get: (options?: GetActionOptions) => Promise;
+}
+
+interface GetActionOptions {
+ filter?: any;
+ filterByTk?: any;
+ fields?: string || string[];
+ appends?: string || string[];
+ expect?: string || string[];
+ sort?: string[];
+}
+```
+
+### `list`
+
+```ts
+interface Resource {
+ list: (options?: ListActionOptions) => Promise;
+}
+
+interface ListActionOptions {
+ filter?: any;
+ filterByTk?: any;
+ fields?: string || string[];
+ appends?: string || string[];
+ expect?: string || string[];
+ sort?: string[];
+ page?: number;
+ pageSize?: number;
+ paginate?: boolean;
+}
+```
+
+### `create`
+
+```ts
+interface Resource {
+ create: (options?: CreateActionOptions) => Promise;
+}
+
+interface CreateActionOptions {
+ whitelist?: string[];
+ blacklist?: string[];
+ values?: {[key: sting]: any};
+}
+```
+
+### `update`
+
+```ts
+interface Resource {
+ update: (options?: UpdateActionOptions) => Promise;
+}
+
+interface UpdateActionOptions {
+ filter?: any;
+ filterByTk?: any;
+ whitelist?: string[];
+ blacklist?: string[];
+ values?: {[key: sting]: any};
+}
+```
+
+### `destroy`
+
+```ts
+interface Resource {
+ destroy: (options?: DestroyActionOptions) => Promise;
+}
+
+interface DestroyActionOptions {
+ filter?: any;
+ filterByTk?: any;
+}
+```
+
+### `move`
+
+```ts
+interface Resource {
+ move: (options?: MoveActionOptions) => Promise;
+}
+
+interface MoveActionOptions {
+ sourceId: any;
+ targetId?: any;
+ /** @default 'sort' */
+ sortField?: any;
+ targetScope?: {[key: string]: any};
+ sticky?: boolean;
+ method?: 'insertAfter' | 'prepend';
+}
+```
+
+### ``
+
+```ts
+interface AttachmentResource {
+
+}
+
+interface UploadActionOptions {
+
+}
+
+api.resource('attachments').upload();
+api.resource('attachments').upload();
+```
diff --git a/docs/zh-CN/development/http-api/rest-api.md b/docs/zh-CN/development/http-api/rest-api.md
new file mode 100644
index 000000000..2d7fd86d5
--- /dev/null
+++ b/docs/zh-CN/development/http-api/rest-api.md
@@ -0,0 +1,184 @@
+# REST API
+
+NocoBase 的 HTTP API 是 REST API 的超集,标准的 CRUD API 也支持 RESTful 风格。
+
+## Collection 资源
+
+---
+
+### 创建 collection
+
+HTTP API
+
+```bash
+POST /api/:create
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+POST /api/
+
+{} # JSON body
+```
+
+### 查看 collection 列表
+
+HTTP API
+
+```bash
+GET /api/:list
+```
+
+REST API
+
+```bash
+GET /api/
+```
+
+### 查看 collection 详情
+
+HTTP API
+
+```bash
+GET /api/:get?filterByTk=
+GET /api/:get/
+```
+
+REST API
+
+```bash
+GET /api//
+```
+
+### 更新 collection
+
+HTTP API
+
+```bash
+POST /api/:update?filterByTk=
+
+{} # JSON body
+
+# 或者
+POST /api/:update/
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+PUT /api//
+
+{} # JSON body
+```
+
+### 删除 collection
+
+HTTP API
+
+```bash
+POST /api/:destroy?filterByTk=
+# 或者
+POST /api/:destroy/
+```
+
+REST API
+
+```bash
+DELETE /api//
+```
+
+## Association 资源
+
+---
+
+### 创建 Association
+
+HTTP API
+
+```bash
+POST /api///:create
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+POST /api///
+
+{} # JSON body
+```
+
+### 查看 Association 列表
+
+HTTP API
+
+```bash
+GET /api///:list
+```
+
+REST API
+
+```bash
+GET /api///
+```
+
+### 查看 Association 详情
+
+HTTP API
+
+```bash
+GET /api///:get?filterByTk=
+# 或者
+GET /api///:get/
+```
+
+REST API
+
+```bash
+GET /api///:get/
+```
+
+### 更新 Association
+
+HTTP API
+
+```bash
+POST /api///:update?filterByTk=
+
+{} # JSON body
+
+# 或者
+POST /api///:update/
+
+{} # JSON body
+```
+
+REST API
+
+```bash
+PUT /api///:update/
+
+{} # JSON 数据
+```
+
+### 删除 Association
+
+HTTP API
+
+```bash
+POST /api///:destroy?filterByTk=
+# 或者
+POST /api///:destroy/
+```
+
+REST API
+
+```bash
+DELETE /api////
+```
diff --git a/docs/zh-CN/development/nocobase-cli.md b/docs/zh-CN/development/nocobase-cli.md
new file mode 100644
index 000000000..16338019c
--- /dev/null
+++ b/docs/zh-CN/development/nocobase-cli.md
@@ -0,0 +1,310 @@
+---
+order: 2
+---
+
+# NocoBase CLI
+
+NocoBase CLI 旨在帮助你开发、构建和部署 NocoBase 应用。
+
+
+
+NocoBase CLI 支持 ts-node 和 node 两种运行模式
+
+- ts-node 模式(默认):用于开发环境,支持实时编译,但是响应较慢
+- node 模式:用于生产环境,响应迅速,但需要先执行 `yarn nocobase build` 将全部源码进行编译
+
+
+
+## 使用说明
+
+```bash
+$ yarn nocobase -h
+
+Usage: nocobase [command] [options]
+
+Options:
+ -h, --help
+
+Commands:
+ create-plugin 创建插件脚手架
+ console
+ db:auth 校验数据库是否连接成功
+ db:sync 通过 collections 配置生成相关数据表和字段
+ install 安装
+ start 生产环境启动应用
+ build 编译打包
+ clean 删除编译之后的文件
+ dev 启动应用,用于开发环境,支持实时编译
+ doc 文档开发
+ test 测试
+ umi
+ upgrade 升级
+ help
+```
+
+## 在脚手架里应用
+
+应用脚手架 `package.json` 里的 `scripts` 如下:
+
+```json
+{
+ "scripts": {
+ "dev": "nocobase dev",
+ "start": "nocobase start",
+ "clean": "nocobase clean",
+ "build": "nocobase build",
+ "test": "nocobase test",
+ "postinstall": "nocobase umi generate tmp"
+ }
+}
+```
+
+## 命令行扩展
+
+NocoBase CLI 基于 [commander](https://github.com/tj/commander.js) 构建,你可以自由扩展命令,扩展的 command 可以写在 `app/server/index.ts` 里:
+
+```ts
+const app = new Application(config);
+
+app.command('hello').action(() => {});
+```
+
+或者,写在插件里:
+
+```ts
+class MyPlugin extends Plugin {
+ beforeLoad() {
+ this.app.command('hello').action(() => {});
+ }
+}
+```
+
+终端运行
+
+```bash
+$ yarn nocobase hello
+```
+
+## 内置命令行
+
+按使用频率排序
+
+### `dev`
+
+开发环境下,启动应用,代码实时编译。
+
+
+NocoBase 未安装时,会自动安装(参考 install 命令)
+
+
+```bash
+Usage: nocobase dev [options]
+
+Options:
+ -p, --port [port]
+ --client
+ --server
+ -h, --help
+```
+
+示例
+
+```bash
+# 启动应用,用于开发环境,实时编译
+yarn nocobase dev
+# 只启动服务端
+yarn nocobase dev --server
+# 只启动客户端
+yarn nocobase dev --client
+```
+
+### `start`
+
+生产环境下,启动应用,代码需要 yarn build。
+
+
+
+- NocoBase 未安装时,会自动安装(参考 install 命令)
+- 源码有修改时,需要重新打包(参考 build 命令)
+
+
+
+```bash
+$ yarn nocobase start -h
+
+Usage: nocobase start [options]
+
+Options:
+ -p, --port
+ -s, --silent
+ -h, --help
+```
+
+示例
+
+```bash
+# 启动应用,用于生产环境,
+yarn nocobase start
+```
+
+### `install`
+
+安装
+
+```bash
+$ yarn nocobase install -h
+
+Usage: nocobase install [options]
+
+Options:
+ -f, --force
+ -c, --clean
+ -s, --silent
+ -l, --lang [lang]
+ -e, --root-email
+ -p, --root-password
+ -n, --root-nickname [rootNickname]
+ -h, --help
+```
+
+示例
+
+```bash
+# 初始安装
+yarn nocobase install -l zh-CN -e admin@nocobase.com -p admin123
+# 删除 NocoBase 的所有数据表,并重新安装
+yarn nocobase install -f -l zh-CN -e admin@nocobase.com -p admin123
+# 清空数据库,并重新安装
+yarn nocobase install -c -l zh-CN -e admin@nocobase.com -p admin123
+```
+
+
+
+`-f/--force` 和 `-c/--clean` 的区别
+- `-f/--force` 删除 NocoBase 的数据表
+- `-c/--clean` 清空数据库,所有数据表都会被删除
+
+
+
+### `upgrade`
+
+升级
+
+```bash
+yarn nocobase upgrade
+```
+
+### `test`
+
+jest 测试,支持所有 [jest-cli](https://jestjs.io/docs/cli) 的 options,除此之外还扩展了 `-c, --db-clean` 的支持。
+
+```bash
+$ yarn nocobase test -h
+
+Usage: nocobase test [options]
+
+Options:
+ -c, --db-clean 运行所有测试前清空数据库
+ -h, --help
+```
+
+示例
+
+```bash
+# 运行所有测试文件
+yarn nocobase test
+# 运行指定文件夹下所有测试文件
+yarn nocobase test packages/core/server
+# 运行指定文件里的所有测试
+yarn nocobase test packages/core/database/src/__tests__/database.test.ts
+
+# 运行测试前,清空数据库
+yarn nocobase test -c
+yarn nocobase test packages/core/server -c
+```
+
+### `build`
+
+代码部署到生产环境前,需要将源码编译打包,如果代码有修改,也需要重新构建。
+
+```bash
+# 所有包
+yarn nocobase build
+# 指定包
+yarn nocobase build app/server app/client
+```
+
+### `clean`
+
+删除编译之后的文件
+
+```bash
+yarn clean
+# 等同于
+yarn rimraf -rf packages/*/*/{lib,esm,es,dist}
+```
+
+### `doc`
+
+文档开发
+
+```bash
+# 启动文档
+yarn doc --lang=zh-CN # 等同于 yarn doc dev
+# 构建文档,默认输出到 ./docs/dist/ 目录下
+yarn doc build
+# 查看 dist 输出的文档最终效果
+yarn doc serve --lang=zh-CN
+```
+
+### `db:auth`
+
+校验数据库是否连接成功
+
+```bash
+$ yarn nocobase db:auth -h
+
+Usage: nocobase db:auth [options]
+
+Options:
+ -r, --repeat [repeat] 重连次数
+ -h, --help
+```
+
+### `db:sync`
+
+通过 collections 配置生成数据表和字段
+
+```bash
+$ yarn nocobase db:sync -h
+
+Usage: nocobase db:sync [options]
+
+Options:
+ -f, --force
+ -h, --help display help for command
+```
+
+### `umi`
+
+`app/client` 基于 [umi](https://umijs.org/) 构建,可以通过 `nocobase umi` 来执行其他相关命令。
+
+```bash
+# 生成开发环境所需的 .umi 缓存
+yarn nocobase umi generate tmp
+```
+
+### `help`
+
+帮助命令,也可以用 option 参数,`-h` 和 `--help`
+
+```bash
+# 查看所有 cli
+yarn nocobase help
+# 也可以用 -h
+yarn nocobase -h
+# 或者 --help
+yarn nocobase --help
+# 查看 db:sync 命令的 option
+yarn nocobase db:sync -h
+```
diff --git a/docs/zh-CN/development/plugin-development/client/overview.md b/docs/zh-CN/development/plugin-development/client/overview.md
new file mode 100644
index 000000000..4bba659eb
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/overview.md
@@ -0,0 +1 @@
+# Overview
\ No newline at end of file
diff --git "a/docs/zh-CN/development/plugin-development/client/providers/\bapi-client.md" "b/docs/zh-CN/development/plugin-development/client/providers/\bapi-client.md"
new file mode 100644
index 000000000..3dac00645
--- /dev/null
+++ "b/docs/zh-CN/development/plugin-development/client/providers/\bapi-client.md"
@@ -0,0 +1 @@
+# APIClient
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/acl.md b/docs/zh-CN/development/plugin-development/client/providers/acl.md
new file mode 100644
index 000000000..45cdee8d8
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/acl.md
@@ -0,0 +1 @@
+# ACL
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/antd.md b/docs/zh-CN/development/plugin-development/client/providers/antd.md
new file mode 100644
index 000000000..a80a47303
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/antd.md
@@ -0,0 +1 @@
+# Ant Design
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/china-region.md b/docs/zh-CN/development/plugin-development/client/providers/china-region.md
new file mode 100644
index 000000000..3706bbe44
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/china-region.md
@@ -0,0 +1 @@
+# ChianRegion
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/collection-manager.md b/docs/zh-CN/development/plugin-development/client/providers/collection-manager.md
new file mode 100644
index 000000000..da019d550
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/collection-manager.md
@@ -0,0 +1 @@
+# CollectionManager
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/i18n.md b/docs/zh-CN/development/plugin-development/client/providers/i18n.md
new file mode 100644
index 000000000..a4f29d977
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/i18n.md
@@ -0,0 +1 @@
+# I18n
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/route-switch.md b/docs/zh-CN/development/plugin-development/client/providers/route-switch.md
new file mode 100644
index 000000000..3bfc5a330
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/route-switch.md
@@ -0,0 +1 @@
+# RouteSwitch
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/schema-component.md b/docs/zh-CN/development/plugin-development/client/providers/schema-component.md
new file mode 100644
index 000000000..90d3aa4d8
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/schema-component.md
@@ -0,0 +1 @@
+# SchemaComponent
diff --git a/docs/zh-CN/development/plugin-development/client/providers/schema-initializer.md b/docs/zh-CN/development/plugin-development/client/providers/schema-initializer.md
new file mode 100644
index 000000000..bd2e33b59
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/client/providers/schema-initializer.md
@@ -0,0 +1 @@
+# SchemaInitializer
diff --git a/docs/zh-CN/development/plugin-development/index.md b/docs/zh-CN/development/plugin-development/index.md
new file mode 100644
index 000000000..b8be99be8
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/index.md
@@ -0,0 +1 @@
+# 快速入门
diff --git a/docs/zh-CN/development/plugin-development/server/acl.md b/docs/zh-CN/development/plugin-development/server/acl.md
new file mode 100644
index 000000000..8cd8bbcac
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/acl.md
@@ -0,0 +1 @@
+# ACL
diff --git a/docs/zh-CN/development/plugin-development/server/app-manager.md b/docs/zh-CN/development/plugin-development/server/app-manager.md
new file mode 100644
index 000000000..76a11afbe
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/app-manager.md
@@ -0,0 +1 @@
+# AppManager
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/server/cli.md b/docs/zh-CN/development/plugin-development/server/cli.md
new file mode 100644
index 000000000..db3cc6737
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/cli.md
@@ -0,0 +1 @@
+# CLI
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/server/database.md b/docs/zh-CN/development/plugin-development/server/database.md
new file mode 100644
index 000000000..4a79ce0cd
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/database.md
@@ -0,0 +1 @@
+# Database
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/server/events.md b/docs/zh-CN/development/plugin-development/server/events.md
new file mode 100644
index 000000000..b649f948c
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/events.md
@@ -0,0 +1 @@
+# Event
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/server/i18n.md b/docs/zh-CN/development/plugin-development/server/i18n.md
new file mode 100644
index 000000000..05b5b6193
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/i18n.md
@@ -0,0 +1 @@
+# I18n
diff --git a/docs/zh-CN/development/plugin-development/server/middleware.md b/docs/zh-CN/development/plugin-development/server/middleware.md
new file mode 100644
index 000000000..c5033ed0e
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/middleware.md
@@ -0,0 +1 @@
+# Middleware
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/server/overview.md b/docs/zh-CN/development/plugin-development/server/overview.md
new file mode 100644
index 000000000..4bba659eb
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/overview.md
@@ -0,0 +1 @@
+# Overview
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/server/plugin-manager.md b/docs/zh-CN/development/plugin-development/server/plugin-manager.md
new file mode 100644
index 000000000..b98d016d5
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/plugin-manager.md
@@ -0,0 +1 @@
+# PluginManager
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/server/resourcer.md b/docs/zh-CN/development/plugin-development/server/resourcer.md
new file mode 100644
index 000000000..5c0d22865
--- /dev/null
+++ b/docs/zh-CN/development/plugin-development/server/resourcer.md
@@ -0,0 +1 @@
+# Resource & Action
\ No newline at end of file
diff --git a/docs/zh-CN/faq.md b/docs/zh-CN/faq.md
new file mode 100644
index 000000000..80cba6c74
--- /dev/null
+++ b/docs/zh-CN/faq.md
@@ -0,0 +1,2 @@
+# 常见问题
+
diff --git a/docs/zh-CN/getting-started/installation/create-nocobase-app.md b/docs/zh-CN/getting-started/installation/create-nocobase-app.md
new file mode 100644
index 000000000..f0dda1a5e
--- /dev/null
+++ b/docs/zh-CN/getting-started/installation/create-nocobase-app.md
@@ -0,0 +1,93 @@
+# `create-nocobase-app` 安装
+
+## 0. 先决条件
+
+请确保你已经:
+
+- 安装了 Node.js 14+、Yarn 1.22.x
+- 配置并启动了所需数据库 SQLite 3.x、MySQL 8.x、PostgreSQL 10.x 任选其一
+
+如果你没有安装 Node.js 可以从官网下载并安装最新的 LTS 版本。如果你打算长期与 Node.js 打交道,推荐使用 nvm(Win 系统可以使用 nvm-windows )来管理 Node.js 版本。
+
+```bash
+$ node -v
+
+v16.13.2
+```
+
+推荐使用 yarn 包管理器。
+
+```bash
+$ npm install --global yarn
+$ yarn -v
+
+1.22.10
+```
+
+由于国内网络环境的原因,强烈建议你更换国内镜像。
+
+```bash
+$ yarn config set registry https://registry.npmmirror.com/
+$ yarn config set sqlite3_binary_host_mirror https://npmmirror.com/mirrors/sqlite3/
+```
+
+## 1. 创建 NocoBase 项目
+
+```bash
+# SQLite
+yarn create nocobase-app my-nocobase-app -d sqlite
+# MySQL
+yarn create nocobase-app my-nocobase-app -d mysql \
+ -e DB_HOST=localhost \
+ -e DB_PORT=3356 \
+ -e DB_DATABASE=nocobase \
+ -e DB_USER=nocobase \
+ -e DB_PASSWORD=nocobase
+# PostgreSQL
+yarn create nocobase-app my-nocobase-app -d postgres \
+ -e DB_HOST=localhost \
+ -e DB_PORT=5432 \
+ -e DB_DATABASE=nocobase \
+ -e DB_USER=nocobase \
+ -e DB_PASSWORD=nocobase
+```
+
+## 2. 切换目录
+
+```bash
+cd my-nocobase-app
+```
+
+## 3. 安装依赖
+
+📢 由于网络环境、系统配置等因素影响,接下来这一步骤可能需要十几分钟时间。
+
+```bash
+yarn install
+```
+
+## 4. 安装 NocoBase
+
+```bash
+yarn nocobase install --lang=zh-CN
+```
+
+## 5. 启动 NocoBase
+
+开发环境
+
+```bash
+yarn dev
+```
+
+生产环境
+
+```bash
+yarn start
+```
+
+注:生产环境,如果代码有修改,需要执行 `yarn build`,再重新启动 NocoBase。
+
+## 6. 登录 NocoBase
+
+使用浏览器打开 http://localhost:13000/ 初始化账号和密码是 `admin@nocobase.com` 和 `admin123`。
diff --git a/docs/zh-CN/getting-started/installation/docker-compose.md b/docs/zh-CN/getting-started/installation/docker-compose.md
new file mode 100644
index 000000000..da920ca2b
--- /dev/null
+++ b/docs/zh-CN/getting-started/installation/docker-compose.md
@@ -0,0 +1,52 @@
+# Docker 安装 (👍 推荐)
+
+## 0. 先决条件
+
+⚡⚡ 请确保你已经安装了 [Docker](https://docs.docker.com/get-docker/)
+
+## 1. 将 NocoBase 下载到本地
+
+使用 Git 下载(或直接[下载 Zip 包](https://github.com/nocobase/nocobase/archive/refs/heads/main.zip),并解压到 nocobase 目录下)
+
+```bash
+git clone https://github.com/nocobase/nocobase.git nocobase
+```
+
+## 2. 选择数据库(任选其一)
+
+支持 SQLite、MySQL、PostgreSQL 数据库
+
+```bash
+# SQLite
+cd nocobase/docker/app-sqlite
+# MySQL
+cd nocobase/docker/app-mysql
+# PostgreSQL
+cd nocobase/docker/app-postgres
+```
+
+## 3. 安装并启动 NocoBase
+
+安装过程可能需要等待几十秒钟
+
+```bash
+# 在后台运行
+$ docker-compose up -d
+# 查看 app 进程的情况
+$ docker-compose logs app
+
+app-sqlite-app-1 | nginx started
+app-sqlite-app-1 | yarn run v1.22.15
+app-sqlite-app-1 | $ cross-env DOTENV_CONFIG_PATH=.env node -r dotenv/config packages/app/server/lib/index.js install -s
+app-sqlite-app-1 | Done in 2.72s.
+app-sqlite-app-1 | yarn run v1.22.15
+app-sqlite-app-1 | $ pm2-runtime start --node-args="-r dotenv/config" packages/app/server/lib/index.js -- start
+app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: Launching in no daemon mode
+app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] starting in -fork mode-
+app-sqlite-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] online
+app-sqlite-app-1 | 🚀 NocoBase server running at: http://localhost:13000/
+```
+
+## 4. 登录 NocoBase
+
+使用浏览器打开 http://localhost:13000/ 初始化账号和密码是 `admin@nocobase.com` 和 `admin123`。
diff --git a/docs/zh-CN/getting-started/installation/git-clone.md b/docs/zh-CN/getting-started/installation/git-clone.md
new file mode 100644
index 000000000..3b416dc61
--- /dev/null
+++ b/docs/zh-CN/getting-started/installation/git-clone.md
@@ -0,0 +1,66 @@
+# Git 源码安装
+
+## 0. 先决条件
+
+请确保你已经:
+
+- 安装了 Git、Node.js 14+、Yarn 1.22.x
+- 配置并启动了所需数据库 SQLite 3.x、MySQL 8.x、PostgreSQL 10.x 任选其一
+
+## 1. 将 NocoBase 下载到本地
+
+```bash
+git clone https://github.com/nocobase/nocobase.git my-nocobase-app
+```
+
+## 2. 切换目录
+
+```bash
+cd my-nocobase-app
+```
+
+## 3. 安装依赖
+
+📢 由于网络环境、系统配置等因素影响,接下来这一步骤可能需要十几分钟时间。
+
+```bash
+yarn install
+```
+
+## 4. 设置环境变量
+
+NocoBase 所需的环境变量储存在根目录 `.env` 文件里,根据实际情况修改环境变量,如果你不知道怎么改,[点此查看环境变量说明](../development/env.md),也可以保持默认。
+
+```bash
+# 使用 sqlite 数据库
+DB_DIALECT=sqlite
+# sqlite 文件地址
+DB_STORAGE=storage/db/nocobase.sqlite
+```
+
+## 5. 安装 NocoBase
+
+```bash
+yarn nocobase install --lang=zh-CN
+```
+
+## 6. 启动 NocoBase
+
+开发环境
+
+```bash
+yarn dev
+```
+
+生产环境
+
+```bash
+# 编译
+yarn build
+# 启动
+yarn start
+```
+
+## 7. 登录 NocoBase
+
+使用浏览器打开 http://localhost:13000/ 初始化账号和密码是 `admin@nocobase.com` 和 `admin123`。
diff --git a/docs/zh-CN/getting-started/installation/overview.md b/docs/zh-CN/getting-started/installation/overview.md
new file mode 100644
index 000000000..6940b17b5
--- /dev/null
+++ b/docs/zh-CN/getting-started/installation/overview.md
@@ -0,0 +1,23 @@
+# 安装概述
+
+## 安装方式
+
+NocoBase 支持三种安装方式:
+
+- [Docker 安装(推荐)](./docker-compose.md)
+- [create-nocobase-app 安装](./create-nocobase-app.md)
+- [Git 源码安装](./git-clone.md)
+
+## 如何选择
+
+**Docker 安装(推荐)**:
+
+适合无代码场景,不需要写代码。升级时,下载最新镜像并重启即可。
+
+**create-nocobase-app 安装**:
+
+项目的业务代码完全独立,支持低代码开发。
+
+**Git 源码安装**:
+
+如果你想体验最新未发布版本,或者想参与贡献,需要在源码上进行修改、调试,建议选择这种安装方式,对开发技术水平要求较高,如果代码有更新,可以走 git 流程拉取最新代码。
diff --git a/docs/zh-CN/getting-started/upgrading.md b/docs/zh-CN/getting-started/upgrading.md
new file mode 100644
index 000000000..e2dd59aa9
--- /dev/null
+++ b/docs/zh-CN/getting-started/upgrading.md
@@ -0,0 +1,55 @@
+# 升级
+
+升级前请务必将数据库数据进行备份
+
+## Docker
+
+切换到对应的目录
+
+```bash
+# SQLite
+cd nocobase/docker/app-sqlite
+# MySQL
+cd nocobase/docker/app-mysql
+# PostgreSQL
+cd nocobase/docker/app-postgres
+```
+
+使用 `docker-compose` 停止、删除应用,并下载最新镜像
+
+```bash
+# 停止应用
+docker-compose stop app
+# 删除应用
+docker-compose rm app
+# 下载最新镜像并启动
+docker-compose up -d app
+# 查看 app 进程的情况
+docker-compose logs app
+```
+
+## create-nocobase-app
+
+执行 `nocobase upgrade` 升级命令
+
+```bash
+# 切换到对应的目录
+cd my-nocobase-app
+# 执行更新命令
+yarn nocobase upgrade
+# 启动
+yarn start
+```
+
+## Git 源码
+
+```bash
+# 切换到对应的目录
+cd my-nocobase-app
+# pull 最新代码
+git pull
+# 执行更新命令
+yarn nocobase upgrade
+# 启动
+yarn start
+```
diff --git a/docs/zh-CN/index.md b/docs/zh-CN/index.md
new file mode 100644
index 000000000..9fbb1a217
--- /dev/null
+++ b/docs/zh-CN/index.md
@@ -0,0 +1,52 @@
+# 介绍
+
+![](https://www.nocobase.com/images/demo/11.png)
+
+## NocoBase 是什么
+
+NocoBase 是一个极易扩展的开源无代码开发平台。
+无需编程,使用 NocoBase 搭建自己的协作平台、管理系统,只需要几分钟时间。
+
+官网:https://cn.nocobase.com/
+
+在线体验:https://demo-cn.nocobase.com/new
+
+## 为什么选择 NocoBase
+
+- **开源免费**
+ - 采用 Apache-2.0 许可协议,不限制商业使用
+ - 拥有全部代码,私有化部署,保障数据私有和安全
+ - 针对实际需求自由扩展开发
+ - 具备良好的生态支持
+- **无代码能力强**
+ - 数据模型
+ - 使用文本、日期、数字、附件、选项、图标等数十种字段类型,以及一对一、一对多、多对多等各种关联关系,创建独立的数据模型
+ - 区块
+ - 使用表格、表单、看板、日历、详情等区块类型在页面内自由组合,来展示和操作数据
+ - 权限
+ - 基于角色控制用户的系统配置权限、数据操作权限和菜单访问权限
+ - 工作流
+ - 重复性的任务由自动化代替,减少人工操作, 提高效率。重要的事情需经过人工审批。
+ - 菜单
+ - 可以对菜单分组,支持添加页面和链接,支持无限级子菜单
+ - 操作
+ - 支持筛选、导出、添加、删除、修改、查看等操作对数据进行处理,可以扩展更多类型
+- **对开发者友好**
+ - 微内核,灵活易扩展,具备健全的插件体系
+ - 基于 Node.js,使用主流框架和技术,包括 Koa、Sequelize、React、Formily、Ant Design 等
+ - 渐进式开发,上手难度低,对新人友好
+ - 不绑架、不强依赖,可任意组合使用或扩展,可用于现有项目中
+
+## NocoBase 架构
+
+![](https://www.nocobase.com/images/NocoBaseMindMapLite.png)
+
+[点此查看完整图片](https://www.nocobase.com/images/NocoBaseMindMap.png)
+
+## 联系
+
+如果你希望加入我们一起开发 NocoBase,或者需要提供商业服务,欢迎通过邮件联系我们:hello@nocobase.com
+
+或者添加我们的微信:
+
+![](https://www.nocobase.com/images/wechat.png)
diff --git a/docs/zh-CN/release-notes.md b/docs/zh-CN/release-notes.md
new file mode 100644
index 000000000..f30562f67
--- /dev/null
+++ b/docs/zh-CN/release-notes.md
@@ -0,0 +1,72 @@
+# 更新日志
+
+## 准备发布
+
+### 新功能
+
+- 打包工具 `@nocobase/build`
+- cli 工具 `@nocobase/cli`
+- devtools 包 `@nocobase/devtools`
+- JavaScript 版本的 SDK `@nocobase/sdk`
+- 全新的文档(v0.7)
+
+### 问题修复和改进
+- 将 NocoBase 无代码平台插件放到一起 `@nocobase/preset-nocobase`
+- 改进 create 脚手架 `create-nocobase-app`
+- 官网文档主题 `dumi-theme-nocobase`
+
+## 2022/05/14 ~ v0.7.0-alpha.34
+
+- feat: add plugins:getPinned action api
+- Fix(plugin workflow): fix cannot get job result properties (#382)
+- feat: exist on server start throw error (#374)
+- chore: application options (#375)
+- fix: not in operator with null value record (#377)
+
+## 2022/05/13 ~ v0.7.0-alpha.33
+
+- fix: link-to field data scope error (#1337)
+- feat(plugin workflow): revisions (#379)
+- fix(database): fix option-parser include list index (#371)
+- fix(plugin-worklfow): fix duplicated description in fields values (#368)
+- fix(database): fix type and transaction in repository (#366)
+- fix(plugin workflow): fix transaction of execution (#364)
+
+## 2022/05/05 ~ v0.7.0-alpha.30
+
+- fix(client): upgrade formily packages
+- fix(client): setFormValueChanged must be defined
+
+## 2022/05/01 ~ v0.7.0-alpha.27
+
+- fix: use wrapper when greater than one column
+- fix: props for CreateFormBlockInitializers
+- fix: add schema initializer icon
+- fix: plugin workflow (#349)
+- fix: db:sync not working (#348)
+- fix(plugin-workflow): fix trigger bind logic to avoid duplication (#347)
+- Fix(plugin workflow) (#346)
+- fix: action open mode
+- Fix: menu url style (#344)
+- feat: action loading
+- fix: compile the label field
+- fix: invalid drag and drop sort
+
+## 2022/04/25 ~ v0.7.0-alpha.16
+
+- fix: cannot find module mkdirp (#330)
+- Fix(plugin workflow): UX issues (#329)
+- fix(plugin-file-manager): test failed
+- fix(app-server): dist options
+
+## 2022/04/25 ~ v0.7.0-alpha.0
+
+- 内测版
+
+## 2021/10/07 ~ v0.5.0
+
+- 第二个预览版
+
+## 2021/04/07 ~ v0.4.0
+
+- 第一个预览版
diff --git a/docs/zh-CN/roadmap.md b/docs/zh-CN/roadmap.md
new file mode 100644
index 000000000..2e8c7860c
--- /dev/null
+++ b/docs/zh-CN/roadmap.md
@@ -0,0 +1,30 @@
+# 路线图
+
+## 正在迭代
+
+- `core` 角色和权限
+- `core` 系统升级
+- `core` 表关系
+- `plugin` 工作流
+- `doc` 开发文档
+
+## 正在开发
+
+- `core` 自定义操作
+- `plugin` 操作记录
+- `plugin` 连接第三方数据库
+
+## 准备开发
+
+- `ui` 移动端响应
+- `plugin` 导出
+- `core` 插件管理器
+
+## 未来开发
+
+- `plugin` 审批
+- `plugin` 全文搜索
+- `plugin` 分享页面
+- `plugin` 引用和复制关系表的数据
+- `plugin` 公式
+- `plugin` 数据可视化
\ No newline at end of file
diff --git a/docs/zh-CN/thanks.md b/docs/zh-CN/thanks.md
new file mode 100644
index 000000000..f835eba67
--- /dev/null
+++ b/docs/zh-CN/thanks.md
@@ -0,0 +1,12 @@
+# 致谢
+
+NocoBase 使用了优秀的、成熟的开源产品,向他们表示诚挚的谢意:
+
+- [Ant Design](https://ant.design/)
+- [Dnd Kit](https://dndkit.com/)
+- [Formily](https://github.com/alibaba/formily)
+- [I18next](https://www.i18next.com/)
+- [Koa](https://koajs.com/)
+- [React](https://reactjs.org/)
+- [Sequelize](https://sequelize.org/)
+- [UmiJS](https://umijs.org/)
diff --git a/docs/zh-CN/user-manual/advanced-guide/actions.md b/docs/zh-CN/user-manual/advanced-guide/actions.md
new file mode 100644
index 000000000..b403cd20d
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/actions.md
@@ -0,0 +1,3 @@
+# 操作
+
+TO DO
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/blocks.md b/docs/zh-CN/user-manual/advanced-guide/blocks.md
new file mode 100644
index 000000000..716368802
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/blocks.md
@@ -0,0 +1,63 @@
+# 区块
+
+区块是用来展示和操作数据的视图。区块可以放在页面和弹窗里。一个完整的区块由三部分组成:
+
+1. 内容区:区块的主体
+2. 操作区:可以放置各种操作按钮,用于操作区块数据
+3. 配置区:操作区块配置的按钮
+
+![6.block.jpg](./blocks/6.block.jpg)
+
+## 添加区块
+
+进入界面配置模式,在页面和弹窗内点击 Add block 按钮即可添加区块。选项分为 4 步:
+
+1. 选择区块类型:目前可用的区块类型包括表格、表单、详情、日历、看板、Markdown
+2. 选择 Collection:此处会列出所有的 Collection
+3. 选择创建方式:创建空白区块,或者从复制区块模板,或者引用区块模板
+4. 选择模板:若第 3 步选择了从模板创建,则在第 4 步选择模板
+
+![6.block-add.jpg](./blocks/6.block-add.jpg)
+
+## 配置区块
+
+配置区块包括三方面的内容:
+
+- 配置区块内容
+- 配置区块操作
+- 配置区块属性
+
+### 配置区块内容
+
+以表格区块为例,区块内容是指表格中要显示的列。点击 Configure columns 即可配置要显示的列:
+
+![6.block-content.gif](./blocks/6.block-content.gif)
+
+### 配置区块操作
+
+以表格区块为例,有筛选、添加、删除、查看、编辑、自定义等操作可选。点击 Configure actions 按钮可以配置操作。其中,每个操作按钮都可以单独配置属性:
+
+![6.block-content.gif](./blocks/6.block-content%201.gif)
+
+### 配置区块属性
+
+将光标移到区块右上角,会看到区块配置按钮。以表格区块为例,可以配置的属性有:
+
+- Drag & drop sorting
+- Set the data scope
+- Set default sorting rules
+- Records per page
+
+![6.collection-setting.gif](./blocks/6.collection-setting.gif)
+
+## 区块类型
+
+目前 NocoBase 支持以下几种区块:
+
+- 表格
+- 表单
+- 详情
+- 看板
+- 日历
+- 相关数据
+- Markdown
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-add.jpg b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-add.jpg
new file mode 100755
index 000000000..cd609413f
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-add.jpg differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-content 1.gif b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-content 1.gif
new file mode 100755
index 000000000..8f79be9fa
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-content 1.gif differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-content.gif b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-content.gif
new file mode 100755
index 000000000..8f79be9fa
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block-content.gif differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/blocks/6.block.jpg b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block.jpg
new file mode 100755
index 000000000..b609af5a0
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/blocks/6.block.jpg differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/blocks/6.collection-setting.gif b/docs/zh-CN/user-manual/advanced-guide/blocks/6.collection-setting.gif
new file mode 100755
index 000000000..d969e34e8
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/blocks/6.collection-setting.gif differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/collections.md b/docs/zh-CN/user-manual/advanced-guide/collections.md
new file mode 100644
index 000000000..4f07705ce
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/collections.md
@@ -0,0 +1,42 @@
+# 数据表
+
+开发一个系统之前,我们通常要对业务进行抽象,建立数据模型。在 NocoBase 里,数据表的概念与关系型数据库的数据表概念相近。
+
+点击“数据表配置”按钮,进入数据表配置界面。在这里,可以对数据表进行新增、编辑、删除等操作。
+
+![4.collections.gif](./collections/4.collections.gif)
+
+## 字段类型
+
+- 基本类型
+ - 单行文本
+ - 多行文本
+ - 手机号码
+ - 电子邮箱
+ - 数字
+ - 百分比
+ - 密码
+ - 图标
+- 选择类型
+ - 勾选
+ - 下拉菜单(单选)
+ - 下拉菜单(多选)
+ - 单选框
+ - 复选框
+ - 中国行政区
+- 多媒体
+ - 附件
+ - Markdown
+ - 富文本
+- 日期 & 时间
+ - 日期
+ - 时间
+- 关系类型
+ - 关联
+ - 子表格
+- 系统信息
+ - ID
+ - 创建日期
+ - 最后修改日期
+ - 创建人
+ - 最后修改人
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/collections/4.collections.gif b/docs/zh-CN/user-manual/advanced-guide/collections/4.collections.gif
new file mode 100755
index 000000000..dd0f01a4d
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/collections/4.collections.gif differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/file-storages.md b/docs/zh-CN/user-manual/advanced-guide/file-storages.md
new file mode 100644
index 000000000..f26b9d2ef
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/file-storages.md
@@ -0,0 +1,11 @@
+# 文件存储
+
+NocoBase 文件存储目前支持以下三种方式
+
+- Local storage
+- Aliyun OSS
+- Amazon S3
+
+点击 File storage 进入配置界面,添加相应的信息即可。
+
+![8.storage.gif](./file-storages/8.storage.gif)
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/file-storages/8.storage.gif b/docs/zh-CN/user-manual/advanced-guide/file-storages/8.storage.gif
new file mode 100755
index 000000000..c9edfa8f9
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/file-storages/8.storage.gif differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/functional-zoning.md b/docs/zh-CN/user-manual/advanced-guide/functional-zoning.md
new file mode 100644
index 000000000..d9902ee1e
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/functional-zoning.md
@@ -0,0 +1,9 @@
+# 功能分区
+
+NocoBase 默认内置一个布局模板,这个布局模板的界面主要分为三个区域:
+
+1. 配置入口区。具备系统配置权限的用户,可以在这里看到界面配置、数据表配置、角色和权限、区块模板、工作流,以及其他扩展的配置选项。
+2. 菜单区。顶部是一级菜单,左侧是二级及以下层级的菜单。每个菜单项都可以配置为菜单分组、页面、外部链接。
+3. 区块容器。这里是页面的区块容器,在里面可以放置各种各样的区块。
+
+![3.zone.jpg](./functional-zoning/3.zone.jpg)
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/functional-zoning/3.zone.jpg b/docs/zh-CN/user-manual/advanced-guide/functional-zoning/3.zone.jpg
new file mode 100755
index 000000000..9507d2c7e
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/functional-zoning/3.zone.jpg differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/menus.md b/docs/zh-CN/user-manual/advanced-guide/menus.md
new file mode 100644
index 000000000..d41aa14ef
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/menus.md
@@ -0,0 +1,32 @@
+# 菜单
+
+NocoBase 的默认菜单位置在顶部和左侧。顶部是一级菜单,左侧是二级及以下层级的菜单。
+
+菜单项支持三种类型:
+
+- 菜单分组
+- 页面
+- 外部链接
+
+进入界面配置模式之后,可以添加和编辑菜单,也可以对菜单项进行排序。
+
+## 添加
+
+![5.menu-add.jpg](./menus/5.menu-add.jpg)
+
+点击 Add menu item,选择添加的类型。支持无限级子菜单。
+
+## 配置和排序
+
+将光标移到菜单项上,右上角会出现排序和配置按钮。按住排序按钮,可以拖拽排序。
+
+对菜单项可操作的配置:
+
+- Edit
+- Move to
+- Insert before
+- Insert after
+- Insert Inner
+- Delete
+
+![5.menu-edit.jpg](./menus/5.menu-edit.jpg)
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/menus/5.menu-add.jpg b/docs/zh-CN/user-manual/advanced-guide/menus/5.menu-add.jpg
new file mode 100755
index 000000000..da89a6f93
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/menus/5.menu-add.jpg differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/menus/5.menu-edit.jpg b/docs/zh-CN/user-manual/advanced-guide/menus/5.menu-edit.jpg
new file mode 100755
index 000000000..0252465f7
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/menus/5.menu-edit.jpg differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/plugins.md b/docs/zh-CN/user-manual/advanced-guide/plugins.md
new file mode 100644
index 000000000..f007e86c9
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/plugins.md
@@ -0,0 +1 @@
+# 插件
diff --git a/docs/zh-CN/user-manual/advanced-guide/plugins/Workflow 7229c53cffc8429dbf7acb58cac90a76.md b/docs/zh-CN/user-manual/advanced-guide/plugins/Workflow 7229c53cffc8429dbf7acb58cac90a76.md
new file mode 100755
index 000000000..d9afb34e2
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/plugins/Workflow 7229c53cffc8429dbf7acb58cac90a76.md
@@ -0,0 +1,3 @@
+# Workflow
+
+TO DO
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/roles-permissions.md b/docs/zh-CN/user-manual/advanced-guide/roles-permissions.md
new file mode 100644
index 000000000..c64e82982
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/roles-permissions.md
@@ -0,0 +1,3 @@
+# 角色和权限
+
+TO DO
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/system-settings.md b/docs/zh-CN/user-manual/advanced-guide/system-settings.md
new file mode 100644
index 000000000..a4b550cab
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/system-settings.md
@@ -0,0 +1,10 @@
+# 系统配置
+
+点击 System settings 进入系统配置,可以配置的属性包括:
+
+- System title
+- Logo
+- Language
+- Allow sign up
+
+![9.system.gif](./system-settings/9.system.gif)
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/advanced-guide/system-settings/9.system.gif b/docs/zh-CN/user-manual/advanced-guide/system-settings/9.system.gif
new file mode 100755
index 000000000..e1d26b471
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/system-settings/9.system.gif differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/tabs.md b/docs/zh-CN/user-manual/advanced-guide/tabs.md
new file mode 100644
index 000000000..57da5f6be
--- /dev/null
+++ b/docs/zh-CN/user-manual/advanced-guide/tabs.md
@@ -0,0 +1,9 @@
+# 标签页
+
+在单条数据的页面或弹窗里,可以添加多个标签页,向每个标签页里添加不同的区块,从而显示不同的内容和操作。比如,在一个顾客信息的弹窗里,添加 3 个标签页,分别用来显示顾客的个人信息、订单记录、顾客评价:
+
+![7.tabs.gif](./tabs/7.tabs.gif)
+
+或者在一条待发货的订单记录里,在第 1 个标签页里放置操作发货的表单区块,实现快捷发货;第 2 个标签页放置关联数据区块,用来显示当前订单的订单商品;第 3 个标签页放置订单详情区块:
+
+![7.tabs-2.gif](./tabs/7.tabs-2.gif)
diff --git a/docs/zh-CN/user-manual/advanced-guide/tabs/7.tabs-2.gif b/docs/zh-CN/user-manual/advanced-guide/tabs/7.tabs-2.gif
new file mode 100755
index 000000000..3699ad9e7
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/tabs/7.tabs-2.gif differ
diff --git a/docs/zh-CN/user-manual/advanced-guide/tabs/7.tabs.gif b/docs/zh-CN/user-manual/advanced-guide/tabs/7.tabs.gif
new file mode 100755
index 000000000..df7c895aa
Binary files /dev/null and b/docs/zh-CN/user-manual/advanced-guide/tabs/7.tabs.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started.md b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started.md
new file mode 100644
index 000000000..ca91c75ce
--- /dev/null
+++ b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started.md
@@ -0,0 +1,91 @@
+# 5 分钟上手
+
+让我们花 5 分钟时间用 NocoBase 搭建一个订单管理系统。
+
+## 1. 创建数据表和字段
+
+在这个订单管理系统中,我们需要掌握`Customers`、`Products`、`Orders`的信息,他们彼此之间互相关联。经过分析,我们需要建立 4 个数据表,它们的字段分别为:
+
+- Customers
+ - 姓名
+ - 生日
+ - 性别
+ - 电话
+ - 订单(购买过的所有订单,数据来自`Orders`,每条顾客数据包含多条订单数据)
+- Products
+ - 商品名称
+ - 描述
+ - 图片
+ - 价格
+ - 订单明细(在哪些订单中购买了该商品,数据来自`Order Details`,每条商品数据属于多条订单明细数据)
+- Orders
+ - 订单编号
+ - 总价
+ - 备注
+ - 地址
+ - 顾客(该订单所属的顾客,数据来自`Customers`,每条订单数据属于一条顾客数据)
+ - 订单明细(该订单中的商品,数据来自`Order Details`,每条订单数据包含多条订单明细数据)
+- Order Details
+ - 订单(该明细所属的订单,数据来自`Orders`,每条订单明细数据属于一条订单数据)
+ - 商品(该明细所包含的商品,数据来自`Products`,每条订单明细数据包含一条商品数据)
+ - 数量
+
+其中,有下划线的字段是关系字段,关联到其他数据表。
+
+接下来,点击“数据表配置”按钮,进入数据表配置界面,创建第一个 Collection `Customers`。
+
+![1.customers.gif](./5-minutes-to-get-started/1.customers.gif)
+
+然后点击“字段配置”,为`Customers` 添加 name 字段,它是单行文本类型。
+
+![2.field.gif](./5-minutes-to-get-started/2.field.gif)
+
+用同样的方法,为`Customers` 添加 Birthday、Gender、Phone,它们分别是日期类型、单项选择类型、手机号码类型。
+
+![1.fields.jpg](./5-minutes-to-get-started/1.fields.jpg)
+
+用同样的方法,创建 Collection `Products`、`Orders`、`Order Details` 以及它们的字段。
+
+![1.collections.jpg](./5-minutes-to-get-started/1.collections.jpg)
+
+
+
+其中,对于关系字段,我们要选择 Link to 类型,从而建立数据表之间的关联。在这个例子中,我们将 `Products` 与 `Orders` 关联,并使用 `Order Details` 作为中间表。
+
+![1.relation.jpg](./5-minutes-to-get-started/1.relation.jpg)
+
+将数据表和字段创建完成后,我们开始制作界面。
+
+## 2. 配置菜单和页面
+
+我们需要顾客、订单、商品三个页面展示和管理我们的数据。
+
+点击界面配置按钮,进入界面配置模式。在界面配置模式下,我们可以添加菜单项,添加页面,在页面内布置区块。
+
+![1.editor.gif](./5-minutes-to-get-started/1.editor.gif)
+
+点击添加菜单项,添加菜单分组 “Customers” 和 “Orders & Products” ,然后添加子菜单页面 “All Orders” 和 “Products”。
+
+![1.menu.gif](./5-minutes-to-get-started/1.menu.gif)
+
+添加完菜单和页面之后,我们可以在页面内添加和配置区块了。
+
+## 3. 添加和配置区块
+
+NocoBase 目前支持表格、看板、日历、表单、详情等类型的区块,它们可以将数据表中的数据展示出来,并可以对数据进行操作。显然,顾客、订单、商品 都适合用表格的方式展示和操作。
+
+我们在“所有订单”页面,添加一个表格区块,数据源选择 Collection `Orders` ,并为这个表格区块配置需要显示的列。
+
+![1.block.gif](./5-minutes-to-get-started/1.block.gif)
+
+给这个表格区块配置操作,包括筛选、添加、删除、查看、编辑。
+
+![1.action.gif](./5-minutes-to-get-started/1.action.gif)
+
+为新增、编辑、查看等操作配置表单和详情区块。
+
+![1.action-block.gif](./5-minutes-to-get-started/1.action-block.gif)
+
+然后,用同样的方法,在 Products 和 Customers 页面布置表格区块。完成后,退出界面配置模式,进入使用模式,一个简单的订单管理系统就完成了。
+
+![1.finished.gif](./5-minutes-to-get-started/1.finished.gif)
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.action-block.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.action-block.gif
new file mode 100755
index 000000000..db4d312de
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.action-block.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.action.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.action.gif
new file mode 100755
index 000000000..f8a8f2ba6
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.action.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.block.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.block.gif
new file mode 100755
index 000000000..b2cbbcb79
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.block.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.collections.jpg b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.collections.jpg
new file mode 100755
index 000000000..a03de2c37
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.collections.jpg differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.customers.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.customers.gif
new file mode 100755
index 000000000..eafca0b67
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.customers.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.editor.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.editor.gif
new file mode 100755
index 000000000..d5e7a84df
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.editor.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.fields.jpg b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.fields.jpg
new file mode 100755
index 000000000..79195e552
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.fields.jpg differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.finished.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.finished.gif
new file mode 100755
index 000000000..be301d4ea
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.finished.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.menu.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.menu.gif
new file mode 100755
index 000000000..d1f43c62a
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.menu.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.relation.jpg b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.relation.jpg
new file mode 100755
index 000000000..8f5bce152
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/1.relation.jpg differ
diff --git a/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/2.field.gif b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/2.field.gif
new file mode 100755
index 000000000..c544c710a
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/5-minutes-to-get-started/2.field.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/important-features.md b/docs/zh-CN/user-manual/introduction/important-features.md
new file mode 100644
index 000000000..77a203858
--- /dev/null
+++ b/docs/zh-CN/user-manual/introduction/important-features.md
@@ -0,0 +1,19 @@
+# NocoBase 特色
+
+## 1. “数据结构”与“使用界面”分离
+
+多数以表单、表格或者流程驱动的无代码产品都是在使用界面上直接创建数据结构,比如 Airtable 在表格里新增一列就是新增一个字段。这样的好处是使用简单,不足是功能和灵活性受限,难以满足较复杂场景的需求。
+
+NocoBase 采用数据结构与使用界面分离的设计思路,可以为数据表创建任意数量、任意形态的区块(数据视图),每个区块里可以定义不同的样式、文案、操作。这样既兼顾了无代码的简单操作,又具备了原生开发的灵活性。
+
+![2.collection-block.png](./important-features/2.collection-block.png)
+
+## 2. “系统配置”与“系统使用”分离
+
+NocoBase 用来开发相对复杂的业务系统。在这些场景中,我们希望系统开发者与系统使用者是不同的角色。使用者看到的是一个成熟的、经过精心设计的系统,就像原生开发出来的产品一样,而不是僵化的、可以自由拖拽的、随时修改的系统;而开发者则可以采用所见即所得的方式快速开发系统。
+
+![2.user-root.gif](./important-features/2.user-root.gif)
+
+## 3. 功能即插件
+
+NocoBase 采用插件化架构,所有新功能都可以通过开发和安装插件来实现。未来我们将搭建插件市场,扩展功能就像在手机上安装 APP 一样简单。
\ No newline at end of file
diff --git a/docs/zh-CN/user-manual/introduction/important-features/2.collection-block.png b/docs/zh-CN/user-manual/introduction/important-features/2.collection-block.png
new file mode 100755
index 000000000..7389064cb
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/important-features/2.collection-block.png differ
diff --git a/docs/zh-CN/user-manual/introduction/important-features/2.user-root.gif b/docs/zh-CN/user-manual/introduction/important-features/2.user-root.gif
new file mode 100755
index 000000000..92d668c14
Binary files /dev/null and b/docs/zh-CN/user-manual/introduction/important-features/2.user-root.gif differ
diff --git a/docs/zh-CN/user-manual/introduction/why-nocobase.md b/docs/zh-CN/user-manual/introduction/why-nocobase.md
new file mode 100644
index 000000000..d0dc1ae96
--- /dev/null
+++ b/docs/zh-CN/user-manual/introduction/why-nocobase.md
@@ -0,0 +1,10 @@
+# 适用场景
+
+如果你同时有以下需求,NocoBase 就是为你设计的:
+
+- 开发组织内部管理系统
+- 在很短时间内通过无代码的方式完成 90% 的系统开发
+- 自由扩展开发,满足剩余 10% 的个性化需求部分
+- 系统功能需要频繁变动
+- 私有部署,掌控全部代码和数据
+- 可免费使用,也可以付费获得更多技术支持
diff --git a/docs/zh-CN/who.md b/docs/zh-CN/who.md
new file mode 100644
index 000000000..97617d54a
--- /dev/null
+++ b/docs/zh-CN/who.md
@@ -0,0 +1,10 @@
+# 适用场景
+
+如果你有以下需求,NocoBase 就是为你设计的:
+
+- 开发组织内部管理系统
+- 通过无代码开发,满足大部分业务需求
+- 通过扩展开发,满足个性化业务需求
+- 系统功能需要频繁变动
+- 私有部署,掌控全部代码和数据
+- 可免费使用,也可以付费获得更多技术支持
diff --git a/docs/zh-CN/why.md b/docs/zh-CN/why.md
new file mode 100644
index 000000000..5c659013e
--- /dev/null
+++ b/docs/zh-CN/why.md
@@ -0,0 +1,21 @@
+# 与众不同之处
+
+## 1. “数据结构”与“使用界面”分离
+
+多数以表单、表格或者流程驱动的无代码产品都是在使用界面上直接创建数据结构,比如 Airtable 在表格里新增一列就是新增一个字段。这样的好处是使用简单,不足是功能和灵活性受限,难以满足较复杂场景的需求。
+
+NocoBase 采用数据结构与使用界面分离的设计思路,可以为数据表创建任意数量、任意形态的区块(数据视图),每个区块里可以定义不同的样式、文案、操作。这样既兼顾了无代码的简单操作,又具备了原生开发的灵活性。
+
+![2.collection-block.png](./user-manual/introduction/important-features/2.collection-block.png)
+
+## 2. “系统配置”与“系统使用”分离
+
+NocoBase 用来开发相对复杂的业务系统。在这些场景中,我们希望系统开发者与系统使用者是不同的角色。使用者看到的是一个成熟的、经过精心设计的系统,就像原生开发出来的产品一样,而不是僵化的、可以自由拖拽的、随时修改的系统;而开发者则可以采用所见即所得的方式快速开发系统。
+
+![2.user-root.gif](./user-manual/introduction/important-features/2.user-root.gif)
+
+## 3. 功能即插件
+
+NocoBase 采用插件化架构,所有新功能都可以通过开发和安装插件来实现。未来我们将搭建插件市场,扩展功能就像在手机上安装 APP 一样简单。
+
+![](https://www.nocobase.com/images/NocoBaseMindMapLite.png)
diff --git a/jest.cli.js b/jest.cli.js
deleted file mode 100644
index 8be1963dd..000000000
--- a/jest.cli.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const dotenv = require('dotenv');
-const { existsSync } = require('fs');
-const { resolve } = require('path')
-const yargs = require('yargs');
-
-const envFile = existsSync(resolve(__dirname, '.env.test')) ? '.env.test' : '.env';
-
-dotenv.config({
- path: resolve(__dirname, envFile),
-});
-
-if (yargs.argv.dbDialect) {
- process.env.DB_DIALECT = yargs.argv.dbDialect;
-}
-
-if (yargs.argv.dbPort) {
- process.env.DB_PORT = yargs.argv.dbPort;
-}
-
-console.log('DB_DIALECT:', process.env.DB_DIALECT);
-console.log('DB_PORT:', process.env.DB_PORT);
-
-require('jest-cli/bin/jest');
diff --git a/jest.config.js b/jest.config.js
index 2c327d6a9..40acf3bf3 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,7 +1,8 @@
const { pathsToModuleNameMapper } = require('ts-jest/utils');
-const { compilerOptions } = require('./tsconfig.jest.json');
+const { compilerOptions } = require('./tsconfig.json');
module.exports = {
+ rootDir: process.cwd(),
collectCoverage: false,
verbose: true,
testEnvironment: 'jsdom',
@@ -18,7 +19,7 @@ module.exports = {
diagnostics: false,
},
},
- modulePathIgnorePatterns: ['/esm/', '/lib/'],
+ modulePathIgnorePatterns: ['/esm/', '/es/', '/dist/', '/lib/'],
coveragePathIgnorePatterns: [
'/node_modules/',
'/__tests__/',
diff --git a/lerna.json b/lerna.json
index 7306cf96d..7054f6354 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "0.7.0-alpha.34",
+ "version": "independent",
"npmClient": "yarn",
"useWorkspaces": true,
"npmClientArgs": [
diff --git a/package.json b/package.json
index 7c0fe7ab1..970bb5de0 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,8 @@
{
- "name": "root",
+ "name": "nocobase",
"private": true,
"workspaces": [
- "packages/app/*",
- "packages/core/*",
- "packages/plugins/*"
+ "packages/*/*"
],
"license": "Apache-2.0",
"licenses": [
@@ -14,18 +12,15 @@
}
],
"scripts": {
- "start": "concurrently --kill-others \"yarn start-server -s\" \"yarn start-client\"",
- "start-pm2": "pm2-runtime start --node-args=\"-r dotenv/config\" packages/app/server/lib/index.js -- start",
- "start-docs": "dumi dev",
- "bootstrap": "lerna bootstrap",
- "clean": "rimraf -rf packages/{app,core,plugins}/*/{lib,esm,dist} && lerna clean",
- "nocobase": "cross-env DOTENV_CONFIG_PATH=.env ts-node-dev -r dotenv/config -r tsconfig-paths/register ./packages/app/server/src/index.ts",
- "start-client": "cd packages/app/client && yarn start",
- "start-server": "yarn nocobase start",
- "build": "lerna run build",
- "build-docs": "dumi build",
- "test": "node ./jest.cli.js -i",
+ "nocobase": "nocobase",
+ "dev": "nocobase dev",
+ "start": "nocobase start",
+ "build": "nocobase build",
+ "test": "nocobase test",
+ "doc": "nocobase doc",
+ "postinstall": "nocobase postinstall",
"lint": "eslint .",
+ "clean": "nocobase clean",
"version:alpha": "lerna version prerelease --preid alpha --force-publish=* --no-git-tag-version -m \"chore(versions): publish packages %s\"",
"release:force": "lerna publish from-package --yes",
"release": "lerna publish"
@@ -43,56 +38,9 @@
"@commitlint/cli": "^16.1.0",
"@commitlint/config-conventional": "^16.0.0",
"@commitlint/prompt-cli": "^16.1.0",
- "@testing-library/react": "^12.1.2",
- "@types/jest": "^26.0.0",
- "@types/koa": "^2.13.4",
- "@types/koa-bodyparser": "^4.3.4",
- "@types/lodash": "^4.14.177",
- "@types/node": "^12.6.8",
- "@types/react": "^17.0.0",
- "@types/react-dom": "^17.0.0",
- "@typescript-eslint/eslint-plugin": "^4.9.1",
- "@typescript-eslint/parser": "^4.8.2",
- "classnames": "^2.3.1",
- "concurrently": "^7.0.0",
- "cross-env": "^7.0.3",
- "dotenv": "^10.0.0",
- "dumi": "^1.1.33",
- "eslint": "^7.14.0",
- "eslint-config-prettier": "^7.0.0",
- "eslint-plugin-import": "^2.13.0",
- "eslint-plugin-markdown": "^2.0.1",
- "eslint-plugin-node": "^11.1.0",
- "eslint-plugin-prettier": "^3.1.0",
- "eslint-plugin-promise": "^4.0.0",
- "eslint-plugin-react": "^7.14.2",
- "eslint-plugin-react-hooks": "^4.2.0",
- "eslint-plugin-vue": "^7.0.1",
"ghooks": "^2.0.4",
- "glob": "^7.1.3",
- "jest": "^26.0.0",
- "jest-codemods": "^0.19.1",
- "jest-dom": "^3.1.2",
- "jest-localstorage-mock": "^2.3.0",
- "jest-styled-components": "6.3.3",
- "jest-watch-lerna-packages": "^1.1.0",
- "koa": "^2.13.4",
- "koa-bodyparser": "^4.3.0",
- "lerna": "^4.0.0",
- "pm2": "^5.2.0",
"prettier": "^2.2.1",
"pretty-format": "^24.0.0",
- "pretty-quick": "^3.1.0",
- "react": "^17.0.1",
- "react-dom": "^17.0.1",
- "rimraf": "^3.0.0",
- "sqlite3": "^5.0.2",
- "supertest": "^6.1.6",
- "ts-jest": "^26.0.0",
- "ts-loader": "^7.0.4",
- "ts-node": "^9.1.1",
- "ts-node-dev": "^1.1.8",
- "tsconfig-paths": "^3.12.0",
- "typescript": "^4.1.5"
+ "pretty-quick": "^3.1.0"
}
}
diff --git a/packages/app/client/.umirc.ts b/packages/app/client/.umirc.ts
index 5c58693ad..5e7c80700 100644
--- a/packages/app/client/.umirc.ts
+++ b/packages/app/client/.umirc.ts
@@ -1,20 +1,14 @@
-import { getUmiConfig } from '@nocobase/utils/umiConfig';
-import dotenv from 'dotenv';
-import { resolve } from 'path';
+import { getUmiConfig, resolveNocobasePackagesAlias } from '@nocobase/devtools/umiConfig';
import { defineConfig } from 'umi';
const umiConfig = getUmiConfig();
-dotenv.config({
- path: resolve(__dirname, '../../../.env'),
-});
-
process.env.MFSU_AD = 'none';
export default defineConfig({
hash: true,
define: {
- 'process.env.NOCOBASE_ENV': process.env.NOCOBASE_ENV,
+ 'process.env.APP_ENV': process.env.APP_ENV,
...umiConfig.define,
},
// only proxy when using `umi dev`
@@ -28,11 +22,6 @@ export default defineConfig({
routes: [{ path: '/', exact: false, component: '@/pages/index' }],
// fastRefresh: {},
chainWebpack(config) {
- const clientSrc = resolve(__dirname, '../../core/client/src');
- const utilsSrc = resolve(__dirname, '../../core/utils/src');
- config.module.rules.get('ts-in-node_modules').include.add(clientSrc);
- config.resolve.alias.set('@nocobase/client', clientSrc);
- config.module.rules.get('ts-in-node_modules').include.add(utilsSrc);
- config.resolve.alias.set('@nocobase/utils', utilsSrc);
+ resolveNocobasePackagesAlias(config);
},
});
diff --git a/packages/app/client/package.json b/packages/app/client/package.json
index 309b8c63d..1ccddf92c 100644
--- a/packages/app/client/package.json
+++ b/packages/app/client/package.json
@@ -1,23 +1,9 @@
{
"name": "@nocobase/app-client",
- "version": "0.7.0-alpha.34",
+ "version": "0.7.0-alpha.55",
"license": "MIT",
- "scripts": {
- "start": "umi dev",
- "build": "umi build",
- "postinstall": "node ./umi.cli.js generate tmp",
- "test": "umi-test",
- "test:coverage": "umi-test --coverage"
- },
"devDependencies": {
- "@nocobase/client": "0.7.0-alpha.34",
- "@types/react": "^17.0.0",
- "@types/react-dom": "^17.0.0",
- "@umijs/test": "^3.5.20",
- "antd": "~4.19.5",
- "react": "17.x",
- "react-dom": "17.x",
- "umi": "^3.5.20"
+ "@nocobase/client": "0.7.0-alpha.55"
},
"repository": {
"type": "git",
diff --git a/packages/app/client/src/pages/apiClient.ts b/packages/app/client/src/pages/apiClient.ts
index 63cba55cf..082319619 100644
--- a/packages/app/client/src/pages/apiClient.ts
+++ b/packages/app/client/src/pages/apiClient.ts
@@ -1,7 +1,7 @@
import { APIClient } from '@nocobase/client';
const apiClient = new APIClient({
- baseURL: process.env.SERVER_BASE_URL,
+ baseURL: process.env.API_BASE_URL,
});
export default apiClient;
diff --git a/packages/app/client/umi.cli.js b/packages/app/client/umi.cli.js
deleted file mode 100644
index ba80fce41..000000000
--- a/packages/app/client/umi.cli.js
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env node
-try {
- require('v8-compile-cache');
- require('umi/lib/cli');
-} catch (error) {
-
-}
diff --git a/packages/app/server/.npmignore b/packages/app/server/.npmignore
index 8019620d5..83426817e 100644
--- a/packages/app/server/.npmignore
+++ b/packages/app/server/.npmignore
@@ -2,7 +2,3 @@ node_modules
*.log
docs
__tests__
-jest.config.js
-tsconfig.json
-tsconfig.build.json
-.fatherrc.ts
diff --git a/packages/app/server/package.json b/packages/app/server/package.json
index cd660b4f0..0e8c1c38a 100644
--- a/packages/app/server/package.json
+++ b/packages/app/server/package.json
@@ -1,29 +1,12 @@
{
"name": "@nocobase/app-server",
- "version": "0.7.0-alpha.34",
+ "version": "0.7.0-alpha.55",
"description": "",
"license": "MIT",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
- "scripts": {
- "build": "rimraf -rf lib esm dist && npm run build:cjs && npm run build:esm",
- "build:cjs": "tsc --project tsconfig.build.json",
- "build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir esm"
- },
"dependencies": {
- "@nocobase/database": "0.7.0-alpha.34",
- "@nocobase/plugin-acl": "0.7.0-alpha.34",
- "@nocobase/plugin-china-region": "0.7.0-alpha.34",
- "@nocobase/plugin-client": "0.7.0-alpha.34",
- "@nocobase/plugin-collection-manager": "0.7.0-alpha.34",
- "@nocobase/plugin-error-handler": "0.7.0-alpha.34",
- "@nocobase/plugin-file-manager": "0.7.0-alpha.34",
- "@nocobase/plugin-system-settings": "0.7.0-alpha.34",
- "@nocobase/plugin-ui-routes-storage": "0.7.0-alpha.34",
- "@nocobase/plugin-ui-schema-storage": "0.7.0-alpha.34",
- "@nocobase/plugin-users": "0.7.0-alpha.34",
- "@nocobase/plugin-workflow": "0.7.0-alpha.34",
- "@nocobase/server": "0.7.0-alpha.34"
+ "@nocobase/preset-nocobase": "0.7.0-alpha.55"
},
"repository": {
"type": "git",
diff --git a/packages/app/server/src/config/database.ts b/packages/app/server/src/config/database.ts
index cc6f3bc65..25c7beb7e 100644
--- a/packages/app/server/src/config/database.ts
+++ b/packages/app/server/src/config/database.ts
@@ -1,27 +1,12 @@
import { IDatabaseOptions } from '@nocobase/database';
-import { resolve } from 'path';
-const dialect = process.env.DB_DIALECT as any;
-
-let databaseConfig: IDatabaseOptions = {
- dialect,
- logging: process.env.DB_LOG_SQL === 'on' ? console.log : false,
-};
-
-if (dialect === 'sqlite') {
- databaseConfig = {
- ...databaseConfig,
- storage: resolve(process.cwd(), process.env.DB_STORAGE || 'db.sqlite'),
- };
-} else {
- databaseConfig = {
- ...databaseConfig,
- username: process.env.DB_USER,
- password: process.env.DB_PASSWORD,
- database: process.env.DB_DATABASE,
- host: process.env.DB_HOST,
- port: process.env.DB_PORT as any,
- };
-}
-
-export default databaseConfig;
+export default {
+ logging: process.env.DB_LOGGING === 'on' ? console.log : false,
+ dialect: process.env.DB_DIALECT as any,
+ storage: process.env.DB_STORAGE,
+ username: process.env.DB_USER,
+ password: process.env.DB_PASSWORD,
+ database: process.env.DB_DATABASE,
+ host: process.env.DB_HOST,
+ port: process.env.DB_PORT as any,
+} as IDatabaseOptions;
diff --git a/packages/app/server/src/config/index.ts b/packages/app/server/src/config/index.ts
new file mode 100644
index 000000000..05aa3c881
--- /dev/null
+++ b/packages/app/server/src/config/index.ts
@@ -0,0 +1,9 @@
+import database from './database';
+import plugins from './plugins';
+import resourcer from './resourcer';
+
+export default {
+ database,
+ resourcer,
+ plugins,
+};
diff --git a/packages/app/server/src/config/plugins.ts b/packages/app/server/src/config/plugins.ts
index dd32ae34d..597f808f0 100644
--- a/packages/app/server/src/config/plugins.ts
+++ b/packages/app/server/src/config/plugins.ts
@@ -1,5 +1,4 @@
import { PluginsConfigurations } from '@nocobase/server';
-import { resolve } from 'path';
export default [
'@nocobase/plugin-error-handler',
@@ -8,21 +7,9 @@ export default [
'@nocobase/plugin-ui-routes-storage',
'@nocobase/plugin-file-manager',
'@nocobase/plugin-system-settings',
- [
- '@nocobase/plugin-users',
- {
- jwt: {
- secret: process.env.JWT_SECRET,
- },
- },
- ],
+ '@nocobase/plugin-users',
'@nocobase/plugin-acl',
'@nocobase/plugin-china-region',
'@nocobase/plugin-workflow',
- [
- '@nocobase/plugin-client',
- {
- dist: resolve(process.cwd(), 'packages/app/client/dist'),
- },
- ],
+ '@nocobase/plugin-client',
] as PluginsConfigurations;
diff --git a/packages/app/server/src/config/resourcer.ts b/packages/app/server/src/config/resourcer.ts
index e3dd1eb92..77cbf8ebc 100644
--- a/packages/app/server/src/config/resourcer.ts
+++ b/packages/app/server/src/config/resourcer.ts
@@ -1,3 +1,3 @@
export default {
- prefix: process.env.SERVER_BASE_PATH,
+ prefix: process.env.API_BASE_PATH,
};
diff --git a/packages/app/server/src/index.ts b/packages/app/server/src/index.ts
index aae0494b5..eae2f074d 100644
--- a/packages/app/server/src/index.ts
+++ b/packages/app/server/src/index.ts
@@ -1,8 +1,10 @@
-import { Application, readConfig } from '@nocobase/server';
-import * as path from 'path';
+import { Application } from '@nocobase/server';
+import config from './config';
-(async () => {
- const config = await readConfig(path.join(__dirname, './config'));
- const app = new Application(config);
- await app.parse();
-})();
+const app = new Application(config);
+
+if (require.main === module) {
+ app.parse();
+}
+
+export default app;
diff --git a/packages/app/server/tsconfig.build.json b/packages/app/server/tsconfig.build.json
deleted file mode 100644
index 9bdd87769..000000000
--- a/packages/app/server/tsconfig.build.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../../tsconfig.build.json",
- "compilerOptions": {
- "outDir": "./lib",
- "declaration": true
- },
- "include": ["./src/**/*.ts", "./src/**/*.tsx"],
- "exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
-}
\ No newline at end of file
diff --git a/packages/app/server/tsconfig.json b/packages/app/server/tsconfig.json
deleted file mode 100644
index bf4bd3fa9..000000000
--- a/packages/app/server/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "../../../tsconfig.json",
- "include": ["./src/**/*.ts", "./src/**/*.tsx"],
- "exclude": ["./esm/*", "./lib/*"]
-}
\ No newline at end of file
diff --git a/packages/core/acl/package.json b/packages/core/acl/package.json
index d11a4cdbf..48ed3f161 100644
--- a/packages/core/acl/package.json
+++ b/packages/core/acl/package.json
@@ -1,6 +1,6 @@
{
"name": "@nocobase/acl",
- "version": "0.7.0-alpha.34",
+ "version": "0.7.0-alpha.55",
"description": "",
"license": "Apache-2.0",
"licenses": [
@@ -11,13 +11,8 @@
],
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
- "scripts": {
- "build": "rimraf -rf lib esm dist && npm run build:cjs && npm run build:esm",
- "build:cjs": "tsc --project tsconfig.build.json",
- "build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir esm"
- },
"dependencies": {
- "@nocobase/resourcer": "0.7.0-alpha.34",
+ "@nocobase/resourcer": "0.7.0-alpha.55",
"json-templates": "^4.2.0"
},
"repository": {
diff --git a/packages/core/acl/tsconfig.build.json b/packages/core/acl/tsconfig.build.json
deleted file mode 100644
index 9bdd87769..000000000
--- a/packages/core/acl/tsconfig.build.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../../tsconfig.build.json",
- "compilerOptions": {
- "outDir": "./lib",
- "declaration": true
- },
- "include": ["./src/**/*.ts", "./src/**/*.tsx"],
- "exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
-}
\ No newline at end of file
diff --git a/packages/core/acl/tsconfig.json b/packages/core/acl/tsconfig.json
deleted file mode 100644
index bf4bd3fa9..000000000
--- a/packages/core/acl/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "../../../tsconfig.json",
- "include": ["./src/**/*.ts", "./src/**/*.tsx"],
- "exclude": ["./esm/*", "./lib/*"]
-}
\ No newline at end of file
diff --git a/packages/core/actions/package.json b/packages/core/actions/package.json
index 31956d213..3b9d81241 100644
--- a/packages/core/actions/package.json
+++ b/packages/core/actions/package.json
@@ -1,6 +1,6 @@
{
"name": "@nocobase/actions",
- "version": "0.7.0-alpha.34",
+ "version": "0.7.0-alpha.55",
"description": "",
"license": "Apache-2.0",
"licenses": [
@@ -11,14 +11,9 @@
],
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
- "scripts": {
- "build": "rimraf -rf lib esm dist && npm run build:cjs && npm run build:esm",
- "build:cjs": "tsc --project tsconfig.build.json",
- "build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir esm"
- },
"dependencies": {
- "@nocobase/database": "0.7.0-alpha.34",
- "@nocobase/resourcer": "0.7.0-alpha.34"
+ "@nocobase/database": "0.7.0-alpha.55",
+ "@nocobase/resourcer": "0.7.0-alpha.55"
},
"repository": {
"type": "git",
diff --git a/packages/core/actions/src/__tests__/index.ts b/packages/core/actions/src/__tests__/index.ts
index 51609810a..bfad5a9c8 100644
--- a/packages/core/actions/src/__tests__/index.ts
+++ b/packages/core/actions/src/__tests__/index.ts
@@ -1,10 +1,10 @@
-import qs from 'qs';
-import Koa from 'koa';
+import Database, { CollectionOptions, DatabaseOptions } from '@nocobase/database';
+import { Handlers, ResourceOptions, Resourcer } from '@nocobase/resourcer';
import merge from 'deepmerge';
+import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
+import qs from 'qs';
import supertest, { SuperAgentTest } from 'supertest';
-import { Resourcer, Handlers, ResourceOptions } from '@nocobase/resourcer';
-import Database, { DatabaseOptions, CollectionOptions } from '@nocobase/database';
import table2resource from '../../../server/src/middlewares/table2resource';
export function generatePrefixByPath() {
@@ -28,7 +28,7 @@ export function getConfig(config = {}, options?: any): DatabaseOptions {
port: process.env.DB_PORT,
dialect: process.env.DB_DIALECT,
storage: process.env.DB_STORAGE,
- logging: process.env.DB_LOG_SQL === 'on',
+ logging: process.env.DB_LOGGING === 'on',
sync: {
force: true,
},
diff --git a/packages/core/actions/tsconfig.build.json b/packages/core/actions/tsconfig.build.json
deleted file mode 100644
index 9bdd87769..000000000
--- a/packages/core/actions/tsconfig.build.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../../tsconfig.build.json",
- "compilerOptions": {
- "outDir": "./lib",
- "declaration": true
- },
- "include": ["./src/**/*.ts", "./src/**/*.tsx"],
- "exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
-}
\ No newline at end of file
diff --git a/packages/core/actions/tsconfig.json b/packages/core/actions/tsconfig.json
deleted file mode 100644
index bf4bd3fa9..000000000
--- a/packages/core/actions/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "../../../tsconfig.json",
- "include": ["./src/**/*.ts", "./src/**/*.tsx"],
- "exclude": ["./esm/*", "./lib/*"]
-}
\ No newline at end of file
diff --git a/packages/core/build/.local b/packages/core/build/.local
new file mode 100755
index 000000000..9cbae257c
--- /dev/null
+++ b/packages/core/build/.local
@@ -0,0 +1 @@
+Used in bin/father.js to determine if it is in the local debug state.
diff --git a/packages/core/build/.npmignore b/packages/core/build/.npmignore
new file mode 100755
index 000000000..75230a7a6
--- /dev/null
+++ b/packages/core/build/.npmignore
@@ -0,0 +1,4 @@
+/src/fixtures
+/src/**/*.test.ts
+/lib/**/*.test.js
+/.local
diff --git a/docs/index.md b/packages/core/build/README.md
old mode 100644
new mode 100755
similarity index 100%
rename from docs/index.md
rename to packages/core/build/README.md
diff --git a/packages/core/build/bin/nocobase-build.js b/packages/core/build/bin/nocobase-build.js
new file mode 100755
index 000000000..1f45a0188
--- /dev/null
+++ b/packages/core/build/bin/nocobase-build.js
@@ -0,0 +1,71 @@
+#!/usr/bin/env node
+
+const { existsSync } = require('fs');
+const { join } = require('path');
+const yParser = require('yargs-parser');
+const chalk = require('chalk');
+const signale = require('signale');
+
+// print version and @local
+const args = yParser(process.argv.slice(2), {
+ alias: {
+ package: 'p',
+ },
+});
+
+if (args.v || args.version) {
+ console.log(require('../package').version);
+ if (existsSync(join(__dirname, '../.local'))) {
+ console.log(chalk.cyan('@local'));
+ }
+ process.exit(0);
+}
+
+// Notify update when process exits
+const updater = require('update-notifier');
+const pkg = require('../package.json');
+updater({ pkg }).notify({ defer: true });
+
+function stripEmptyKeys(obj) {
+ Object.keys(obj).forEach((key) => {
+ if (!obj[key] || (Array.isArray(obj[key]) && !obj[key].length)) {
+ delete obj[key];
+ }
+ });
+ return obj;
+}
+
+function build() {
+ // Parse buildArgs from cli
+ const buildArgs = stripEmptyKeys({
+ esm: args.esm && { type: args.esm === true ? 'rollup' : args.esm },
+ cjs: args.cjs && { type: args.cjs === true ? 'rollup' : args.cjs },
+ umd: args.umd && { name: args.umd === true ? undefined : args.umd },
+ file: args.file,
+ target: args.target,
+ entry: args._,
+ config: args.config,
+ });
+
+ if (buildArgs.file && buildArgs.entry && buildArgs.entry.length > 1) {
+ signale.error(
+ new Error(`Cannot specify file when have multiple entries (${buildArgs.entry.join(', ')})`)
+ );
+ process.exit(1);
+ }
+
+ require('../lib/build')
+ .default({
+ cwd: args.root || process.cwd(),
+ watch: args.w || args.watch,
+ clean: args.clean,
+ buildArgs,
+ packages: args._ || [],
+ })
+ .catch((e) => {
+ signale.error(e);
+ process.exit(1);
+ });
+}
+
+build();
diff --git a/packages/core/build/package.json b/packages/core/build/package.json
new file mode 100755
index 000000000..43f96c6a5
--- /dev/null
+++ b/packages/core/build/package.json
@@ -0,0 +1,77 @@
+{
+ "name": "@nocobase/build",
+ "version": "0.7.0-alpha.55",
+ "description": "Library build tool based on rollup.",
+ "main": "lib/index.js",
+ "bin": {
+ "nocobase-build": "./bin/nocobase-build.js"
+ },
+ "typings": "./index.d.ts",
+ "dependencies": {
+ "@babel/core": "7.12.3",
+ "@babel/plugin-proposal-class-properties": "7.12.1",
+ "@babel/plugin-proposal-decorators": "7.12.1",
+ "@babel/plugin-proposal-do-expressions": "7.12.1",
+ "@babel/plugin-proposal-export-default-from": "7.12.1",
+ "@babel/plugin-proposal-export-namespace-from": "7.12.1",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "7.12.1",
+ "@babel/plugin-proposal-optional-chaining": "7.12.1",
+ "@babel/plugin-syntax-dynamic-import": "7.8.3",
+ "@babel/plugin-transform-modules-commonjs": "7.12.1",
+ "@babel/plugin-transform-runtime": "7.12.1",
+ "@babel/preset-env": "7.12.1",
+ "@babel/preset-react": "7.12.1",
+ "@babel/preset-typescript": "7.12.1",
+ "@babel/register": "7.12.1",
+ "@lerna/filter-packages": "4.0.0",
+ "@lerna/project": "4.0.0",
+ "@lerna/query-graph": "4.0.0",
+ "@rollup/plugin-babel": "5.3.1",
+ "@rollup/plugin-commonjs": "16.0.0",
+ "@rollup/plugin-inject": "4.0.2",
+ "@rollup/plugin-json": "4.1.0",
+ "@rollup/plugin-node-resolve": "10.0.0",
+ "@rollup/plugin-replace": "2.3.4",
+ "@rollup/plugin-url": "5.0.1",
+ "@svgr/rollup": "5.5.0",
+ "ajv": "6.12.6",
+ "autoprefixer": "9.6.0",
+ "babel-plugin-istanbul": "^5.2.0",
+ "babel-plugin-react-require": "3.1.1",
+ "chalk": "2.4.2",
+ "chokidar": "^3.0.2",
+ "es5-imcompatible-versions": "^0.1.37",
+ "glob": "^7.1.4",
+ "gulp-if": "2.0.2",
+ "gulp-less": "^4.0.1",
+ "gulp-plumber": "^1.2.1",
+ "gulp-typescript": "5.0.1",
+ "less": "3.9.0",
+ "less-plugin-npm-import": "2.1.0",
+ "lodash": "4.17.21",
+ "pkg-up": "3.1.0",
+ "rimraf": "2.6.3",
+ "rollup": "2.33.3",
+ "rollup-plugin-postcss": "3.1.8",
+ "rollup-plugin-terser": "7.0.2",
+ "rollup-plugin-typescript2": "0.29.0",
+ "semver": "6.1.1",
+ "signale": "1.4.0",
+ "slash2": "2.0.0",
+ "temp-dir": "2.0.0",
+ "through2": "3.0.1",
+ "ts-loader": "^8.0.7",
+ "typescript": "^4.0.5",
+ "update-notifier": "3.0.0",
+ "vinyl-fs": "3.0.3",
+ "yargs-parser": "13.1.2"
+ },
+ "license": "MIT",
+ "scripts": {
+ "build": "umi-tools build"
+ },
+ "devDependencies": {
+ "@types/gulp-plumber": "^0.0.32",
+ "umi-tools": "^0.4.0"
+ }
+}
diff --git a/packages/core/build/src/babel.ts b/packages/core/build/src/babel.ts
new file mode 100755
index 000000000..5a16537c7
--- /dev/null
+++ b/packages/core/build/src/babel.ts
@@ -0,0 +1,257 @@
+import { join, extname, relative } from "path";
+import { existsSync, readFileSync, statSync } from "fs";
+import vfs from "vinyl-fs";
+import signale from "signale";
+import lodash from "lodash";
+import rimraf from "rimraf";
+import through from "through2";
+import slash from "slash2";
+import * as chokidar from "chokidar";
+import * as babel from "@babel/core";
+import gulpTs from "gulp-typescript";
+import gulpLess from "gulp-less";
+import gulpPlumber from "gulp-plumber";
+import gulpIf from "gulp-if";
+import chalk from "chalk";
+import getBabelConfig from "./getBabelConfig";
+import { Dispose, IBundleOptions } from "./types";
+import * as ts from "typescript";
+
+interface IBabelOpts {
+ cwd: string;
+ rootPath?: string;
+ type: "esm" | "cjs";
+ target?: "browser" | "node";
+ log?: (string) => void;
+ watch?: boolean;
+ dispose?: Dispose[];
+ importLibToEs?: boolean;
+ bundleOpts: IBundleOptions;
+}
+
+interface ITransformOpts {
+ file: {
+ contents: string;
+ path: string;
+ };
+ type: "esm" | "cjs";
+}
+
+export default async function (opts: IBabelOpts) {
+ const {
+ cwd,
+ rootPath,
+ type,
+ watch,
+ dispose,
+ importLibToEs,
+ log,
+ bundleOpts: {
+ target = "browser",
+ runtimeHelpers,
+ extraBabelPresets = [],
+ extraBabelPlugins = [],
+ browserFiles = [],
+ nodeFiles = [],
+ nodeVersion,
+ disableTypeCheck,
+ cjs,
+ lessInBabelMode,
+ },
+ } = opts;
+ const srcPath = join(cwd, "src");
+ const targetDir = type === "esm" ? "es" : "lib";
+ const targetPath = join(cwd, targetDir);
+
+ log(chalk.gray(`Clean ${targetDir} directory`));
+ rimraf.sync(targetPath);
+
+ function transform(opts: ITransformOpts) {
+ const { file, type } = opts;
+ const { opts: babelOpts, isBrowser } = getBabelConfig({
+ target,
+ type,
+ typescript: true,
+ runtimeHelpers,
+ filePath: slash(relative(cwd, file.path)),
+ browserFiles,
+ nodeFiles,
+ nodeVersion,
+ lazy: cjs && cjs.lazy,
+ lessInBabelMode,
+ });
+ if (importLibToEs && type === "esm") {
+ babelOpts.plugins.push(require.resolve("../lib/importLibToEs"));
+ }
+ babelOpts.presets.push(...extraBabelPresets);
+ babelOpts.plugins.push(...extraBabelPlugins);
+
+ const relFile = slash(file.path).replace(`${cwd}/`, "");
+ log(
+ `Transform to ${type} for ${chalk[isBrowser ? "yellow" : "blue"](
+ relFile
+ )}`
+ );
+
+ return babel.transform(file.contents, {
+ ...babelOpts,
+ filename: file.path,
+ // 不读取外部的babel.config.js配置文件,全采用babelOpts中的babel配置来构建
+ configFile: false,
+ }).code;
+ }
+
+ /**
+ * tsconfig.json is not valid json file
+ * https://github.com/Microsoft/TypeScript/issues/20384
+ */
+ function parseTsconfig(path: string) {
+ const readFile = (path: string) => readFileSync(path, "utf-8");
+ const result = ts.readConfigFile(path, readFile);
+ if (result.error) {
+ return;
+ }
+ const pkgTsConfig = result.config;
+ if (pkgTsConfig.extends) {
+ const rootTsConfigPath = slash(relative(cwd, pkgTsConfig.extends));
+ const rootTsConfig = parseTsconfig(rootTsConfigPath);
+ if (rootTsConfig) {
+ const mergedConfig = {
+ ...rootTsConfig,
+ ...pkgTsConfig,
+ compilerOptions: {
+ ...rootTsConfig.compilerOptions,
+ ...pkgTsConfig.compilerOptions,
+ },
+ };
+ return mergedConfig;
+ }
+ }
+ return pkgTsConfig;
+ }
+
+ function getTsconfigCompilerOptions(path: string) {
+ const config = parseTsconfig(path);
+ return config ? config.compilerOptions : undefined;
+ }
+
+ function getTSConfig() {
+ const tsconfigPath = join(cwd, "tsconfig.json");
+ const templateTsconfigPath = join(__dirname, "../template/tsconfig.json");
+
+ if (existsSync(tsconfigPath)) {
+ return getTsconfigCompilerOptions(tsconfigPath) || {};
+ }
+ if (rootPath && existsSync(join(rootPath, "tsconfig.json"))) {
+ return getTsconfigCompilerOptions(join(rootPath, "tsconfig.json")) || {};
+ }
+ return getTsconfigCompilerOptions(templateTsconfigPath) || {};
+ }
+
+ function createStream(src) {
+ const tsConfig = getTSConfig();
+ const babelTransformRegexp = disableTypeCheck ? /\.(t|j)sx?$/ : /\.jsx?$/;
+
+ function isTsFile(path) {
+ return /\.tsx?$/.test(path) && !path.endsWith(".d.ts");
+ }
+
+ function isTransform(path) {
+ return babelTransformRegexp.test(path) && !path.endsWith(".d.ts");
+ }
+
+ return vfs
+ .src(src, {
+ allowEmpty: true,
+ base: srcPath,
+ })
+ .pipe(watch ? gulpPlumber() : through.obj())
+ .pipe(
+ gulpIf((f) => !disableTypeCheck && isTsFile(f.path), gulpTs(tsConfig))
+ )
+ .pipe(
+ gulpIf(
+ (f) => lessInBabelMode && /\.less$/.test(f.path),
+ gulpLess(lessInBabelMode || {})
+ )
+ )
+ .pipe(
+ gulpIf(
+ (f) => isTransform(f.path),
+ through.obj((file, env, cb) => {
+ try {
+ file.contents = Buffer.from(
+ transform({
+ file,
+ type,
+ })
+ );
+ // .jsx -> .js
+ file.path = file.path.replace(extname(file.path), ".js");
+ cb(null, file);
+ } catch (e) {
+ signale.error(`Compiled faild: ${file.path}`);
+ console.log(e);
+ cb(null);
+ }
+ })
+ )
+ )
+ .pipe(vfs.dest(targetPath));
+ }
+
+ return new Promise((resolve) => {
+ const patterns = [
+ join(srcPath, "**/*"),
+ `!${join(srcPath, "**/fixtures{,/**}")}`,
+ `!${join(srcPath, "**/demos{,/**}")}`,
+ `!${join(srcPath, "**/__test__{,/**}")}`,
+ `!${join(srcPath, "**/__tests__{,/**}")}`,
+ `!${join(srcPath, "**/*.mdx")}`,
+ `!${join(srcPath, "**/*.md")}`,
+ `!${join(srcPath, "**/*.+(test|e2e|spec).+(js|jsx|ts|tsx)")}`,
+ `!${join(srcPath, "**/tsconfig{,.*}.json")}`,
+ `!${join(srcPath, ".umi{,-production,-test}{,/**}")}`,
+ ];
+ createStream(patterns).on("end", () => {
+ if (watch) {
+ log(
+ chalk.magenta(
+ `Start watching ${slash(srcPath).replace(
+ `${cwd}/`,
+ ""
+ )} directory...`
+ )
+ );
+ const watcher = chokidar.watch(patterns, {
+ ignoreInitial: true,
+ });
+
+ const files = [];
+ function compileFiles() {
+ while (files.length) {
+ createStream(files.pop());
+ }
+ }
+
+ const debouncedCompileFiles = lodash.debounce(compileFiles, 1000);
+ watcher.on("all", (event, fullPath) => {
+ const relPath = fullPath.replace(srcPath, "");
+ log(
+ `[${event}] ${slash(join(srcPath, relPath)).replace(`${cwd}/`, "")}`
+ );
+ if (!existsSync(fullPath)) return;
+ if (statSync(fullPath).isFile()) {
+ if (!files.includes(fullPath)) files.push(fullPath);
+ debouncedCompileFiles();
+ }
+ });
+ process.once("SIGINT", () => {
+ watcher.close();
+ });
+ dispose?.push(() => watcher.close());
+ }
+ resolve();
+ });
+ });
+}
diff --git a/packages/core/build/src/build.test.ts b/packages/core/build/src/build.test.ts
new file mode 100755
index 000000000..254b28abf
--- /dev/null
+++ b/packages/core/build/src/build.test.ts
@@ -0,0 +1,52 @@
+import { join, basename, sep } from 'path';
+import { getPackagesSync } from '@lerna/project';
+import { existsSync, readdirSync, renameSync, statSync } from 'fs';
+import mkdirp from 'mkdirp';
+import rimraf from 'rimraf';
+import build from './build';
+
+function moveEsLibToDist(cwd) {
+ ['es', 'lib'].forEach(dir => {
+ const absDirPath = join(cwd, dir);
+ const absDistPath = join(cwd, 'dist');
+ if (existsSync(absDirPath)) {
+ mkdirp.sync(absDistPath);
+ renameSync(absDirPath, join(absDistPath, dir));
+ }
+ });
+}
+
+describe('father build', () => {
+ const rootConfigMapping = {
+ 'lerna-root-config-override': { cjs: 'rollup', esm: false },
+ };
+
+ require('test-build-result')({
+ root: join(__dirname, './fixtures/build'),
+ build({ cwd }) {
+ process.chdir(cwd);
+ rimraf.sync(join(cwd, 'dist'));
+ return build({ cwd, rootConfig: rootConfigMapping[basename(cwd)] }).then(() => {
+ // babel
+ moveEsLibToDist(cwd);
+
+ // lerna
+ if (existsSync(join(cwd, 'lerna.json'))) {
+ mkdirp.sync(join(cwd, 'dist'));
+ const pkgs = getPackagesSync(cwd)
+ for (let pkg of pkgs) {
+
+ const pkgPath = pkg.contents;
+
+ if (!statSync(pkgPath).isDirectory()) continue;
+ moveEsLibToDist(pkgPath);
+ renameSync(
+ join(pkgPath, 'dist'),
+ join(cwd, 'dist', pkgPath.split(sep).pop())
+ );
+ }
+ }
+ });
+ },
+ });
+});
diff --git a/packages/core/build/src/build.ts b/packages/core/build/src/build.ts
new file mode 100755
index 000000000..49b396758
--- /dev/null
+++ b/packages/core/build/src/build.ts
@@ -0,0 +1,260 @@
+import * as assert from 'assert';
+import chalk from 'chalk';
+import { existsSync, readFileSync } from 'fs';
+import { merge } from 'lodash';
+import { isAbsolute, join, sep } from 'path';
+import rimraf from 'rimraf';
+import signale from 'signale';
+import babel from './babel';
+import getUserConfig, { CONFIG_FILES } from './getUserConfig';
+import randomColor from './randomColor';
+import registerBabel from './registerBabel';
+import rollup from './rollup';
+import { Dispose, IBundleOptions, IBundleTypeOutput, ICjs, IEsm, IOpts } from './types';
+import { getExistFile, getLernaPackages } from './utils';
+
+export function getBundleOpts(opts: IOpts): IBundleOptions[] {
+ const { cwd, buildArgs = {}, rootConfig = {} } = opts;
+ const entry = getExistFile({
+ cwd,
+ files: ['src/index.tsx', 'src/index.ts', 'src/index.jsx', 'src/index.js'],
+ returnRelative: true,
+ });
+ const userConfig = getUserConfig({ cwd, customPath: buildArgs.config });
+ const userConfigs = Array.isArray(userConfig) ? userConfig : [userConfig];
+ return (userConfigs as any).map((userConfig) => {
+ const bundleOpts = merge(
+ {
+ entry,
+ },
+ rootConfig,
+ userConfig,
+ buildArgs
+ );
+
+ // Support config esm: 'rollup' and cjs: 'rollup'
+ if (typeof bundleOpts.esm === 'string') {
+ bundleOpts.esm = { type: bundleOpts.esm };
+ }
+ if (typeof bundleOpts.cjs === 'string') {
+ bundleOpts.cjs = { type: bundleOpts.cjs };
+ }
+
+ return bundleOpts;
+ });
+}
+
+function validateBundleOpts(bundleOpts: IBundleOptions, { cwd, rootPath }) {
+ if (bundleOpts.runtimeHelpers) {
+ const pkgPath = join(cwd, 'package.json');
+ assert.ok(existsSync(pkgPath), `@babel/runtime dependency is required to use runtimeHelpers`);
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
+ assert.ok(
+ (pkg.dependencies || {})['@babel/runtime'],
+ `@babel/runtime dependency is required to use runtimeHelpers`
+ );
+ }
+ if (
+ bundleOpts.cjs &&
+ (bundleOpts.cjs as ICjs).lazy &&
+ (bundleOpts.cjs as ICjs).type === 'rollup'
+ ) {
+ throw new Error(
+ `
+cjs.lazy don't support rollup.
+ `.trim()
+ );
+ }
+ if (!bundleOpts.esm && !bundleOpts.cjs && !bundleOpts.umd) {
+ throw new Error(
+ `
+None format of ${chalk.cyan(
+ 'cjs | esm | umd'
+ )} is configured, checkout https://github.com/umijs/father for usage details.
+`.trim()
+ );
+ }
+ if (bundleOpts.entry) {
+ const tsConfigPath = join(cwd, 'tsconfig.json');
+ const tsConfig =
+ existsSync(tsConfigPath) || (rootPath && existsSync(join(rootPath, 'tsconfig.json')));
+ if (
+ !tsConfig &&
+ ((Array.isArray(bundleOpts.entry) && bundleOpts.entry.some(isTypescriptFile)) ||
+ (!Array.isArray(bundleOpts.entry) && isTypescriptFile(bundleOpts.entry)))
+ ) {
+ signale.info(
+ `Project using ${chalk.cyan(
+ 'typescript'
+ )} but tsconfig.json not exists. Use default config.`
+ );
+ }
+ }
+}
+
+function isTypescriptFile(filePath) {
+ return filePath.endsWith('.ts') || filePath.endsWith('.tsx');
+}
+
+interface IExtraBuildOpts {
+ pkg?: string | { name?: string };
+}
+
+export async function build(opts: IOpts, extraOpts: IExtraBuildOpts = {}) {
+ const { cwd, rootPath, watch, buildArgs = {}, clean = true } = opts;
+ const { pkg } = extraOpts;
+
+ const dispose: Dispose[] = [];
+
+ const customConfigPath =
+ buildArgs.config &&
+ (isAbsolute(buildArgs.config) ? buildArgs.config : join(process.cwd(), buildArgs.config));
+
+ // register babel for config files
+ registerBabel({
+ cwd,
+ only: customConfigPath ? CONFIG_FILES.concat(customConfigPath) : CONFIG_FILES,
+ });
+
+ const pkgName = (typeof pkg === 'string' ? pkg : pkg?.name) || 'unknown';
+
+ function log(msg) {
+ console.log(`${pkg ? `${randomColor(`${pkgName}`)}: ` : ''}${msg}`);
+ }
+
+ // Get user config
+ const bundleOptsArray = getBundleOpts(opts);
+
+ for (const bundleOpts of bundleOptsArray) {
+ validateBundleOpts(bundleOpts, { cwd, rootPath });
+
+ // Clean dist
+ if (clean) {
+ log(chalk.gray(`Clean dist directory`));
+ rimraf.sync(join(cwd, 'dist'));
+ }
+
+
+ // Build umd
+ if (bundleOpts.umd) {
+ log(`Build umd`);
+ await rollup({
+ cwd,
+ rootPath,
+ log,
+ type: 'umd',
+ entry: bundleOpts.entry,
+ watch,
+ dispose,
+ bundleOpts,
+ });
+ }
+
+ // Build cjs
+ if (bundleOpts.cjs) {
+ const cjs = bundleOpts.cjs as IBundleTypeOutput;
+ log(`Build cjs with ${cjs.type}`);
+ if (cjs.type === 'babel') {
+ await babel({ cwd, rootPath, watch, dispose, type: 'cjs', log, bundleOpts });
+ } else {
+ await rollup({
+ cwd,
+ rootPath,
+ log,
+ type: 'cjs',
+ entry: bundleOpts.entry,
+ watch,
+ dispose,
+ bundleOpts,
+ });
+ }
+ }
+
+ // Build esm
+ if (bundleOpts.esm) {
+ const esm = bundleOpts.esm as IEsm;
+ log(`Build esm with ${esm.type}`);
+ const importLibToEs = esm && esm.importLibToEs;
+ if (esm && esm.type === 'babel') {
+ await babel({ cwd, rootPath, watch, dispose, type: 'esm', importLibToEs, log, bundleOpts });
+ } else {
+ await rollup({
+ cwd,
+ rootPath,
+ log,
+ type: 'esm',
+ entry: bundleOpts.entry,
+ importLibToEs,
+ watch,
+ dispose,
+ bundleOpts,
+ });
+ }
+ }
+ }
+
+ return dispose;
+}
+
+function getPkgRelativePath(cwd, pkg) {
+ const basePath = cwd.split(sep).join('/') + '/packages/';
+ const dir = pkg.contents.split(sep).join('/');
+ return dir.substring(basePath.length);
+}
+
+export async function buildForLerna(opts: IOpts) {
+ const { cwd, rootConfig = {}, buildArgs = {}, packages = [] } = opts;
+
+ // register babel for config files
+ registerBabel({
+ cwd,
+ only: CONFIG_FILES,
+ });
+
+ const userConfig = merge(getUserConfig({ cwd }), rootConfig, buildArgs);
+
+ let pkgs = await getLernaPackages(cwd, userConfig.pkgFilter);
+ // support define pkgs in lerna
+ if (userConfig.pkgs) {
+ pkgs = pkgs.filter(pkg => userConfig.pkgs.includes(getPkgRelativePath(cwd, pkg)));
+ }
+ const dispose: Dispose[] = [];
+ for (const pkg of pkgs) {
+ const pkgName = getPkgRelativePath(cwd, pkg);
+ if (userConfig.excludePkgs && userConfig.excludePkgs.includes(pkgName)) {
+ continue;
+ }
+ if (packages.length && !packages.includes(pkgName)) continue;
+ // build error when .DS_Store includes in packages root
+ const pkgPath = pkg.contents;
+ assert.ok(
+ existsSync(join(pkgPath, 'package.json')),
+ `package.json not found in packages/${pkg}`
+ );
+ process.chdir(pkgPath);
+ dispose.push(
+ ...(await build(
+ {
+ // eslint-disable-line
+ ...opts,
+ buildArgs: opts.buildArgs,
+ rootConfig: userConfig,
+ cwd: pkgPath,
+ rootPath: cwd,
+ },
+ {
+ pkg,
+ }
+ ))
+ );
+ }
+ return dispose;
+}
+
+export default async function (opts: IOpts) {
+ const useLerna = existsSync(join(opts.cwd, 'lerna.json'));
+ const isLerna = useLerna && process.env.LERNA !== 'none';
+
+ const dispose = isLerna ? await buildForLerna(opts) : await build(opts);
+ return () => dispose.forEach((e) => e());
+}
diff --git a/packages/core/build/src/es5ImcompatibleVersions.ts b/packages/core/build/src/es5ImcompatibleVersions.ts
new file mode 100755
index 000000000..8f72f36b4
--- /dev/null
+++ b/packages/core/build/src/es5ImcompatibleVersions.ts
@@ -0,0 +1,33 @@
+// 参考:
+// https://github.com/umijs/umi/blob/2.x/packages/af-webpack/src/getWebpackConfig/es5ImcompatibleVersions.js
+import { dirname } from 'path';
+import pkgUp from 'pkg-up';
+import { satisfies } from 'semver';
+
+const pkgPathCache = {};
+const pkgCache = {};
+const {
+ config: { 'es5-imcompatible-versions': config },
+} = require('es5-imcompatible-versions/package.json');
+
+export function getPkgPath(filePath: string) {
+ const dir = dirname(filePath);
+ if (dir in pkgPathCache) return pkgPathCache[dir];
+ pkgPathCache[dir] = pkgUp.sync({ cwd: filePath });
+ return pkgPathCache[dir];
+}
+
+export function shouldTransform(pkgPath: string) {
+ if (pkgPath in pkgCache) return pkgCache[pkgPath];
+ const { name, version } = require(pkgPath);
+ pkgCache[pkgPath] = isMatch(name, version);
+ return pkgCache[pkgPath];
+}
+
+function isMatch(name, version) {
+ if (config[name]) {
+ return Object.keys(config[name]).some((sv) => satisfies(version, sv));
+ } else {
+ return false;
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/babel-browser-files/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-browser-files/.fatherrc.js
new file mode 100755
index 000000000..3cd11ad83
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-browser-files/.fatherrc.js
@@ -0,0 +1,8 @@
+
+export default {
+ esm: 'babel',
+ target: 'node',
+ browserFiles: [
+ 'src/browser.js',
+ ],
+}
diff --git a/packages/core/build/src/fixtures/build/babel-browser-files/expected/es/browser.js b/packages/core/build/src/fixtures/build/babel-browser-files/expected/es/browser.js
new file mode 100755
index 000000000..22dc0e15f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-browser-files/expected/es/browser.js
@@ -0,0 +1 @@
+var b = 'foo';
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-browser-files/expected/es/node.js b/packages/core/build/src/fixtures/build/babel-browser-files/expected/es/node.js
new file mode 100755
index 000000000..ed389c023
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-browser-files/expected/es/node.js
@@ -0,0 +1 @@
+const a = 'foo';
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-browser-files/src/browser.js b/packages/core/build/src/fixtures/build/babel-browser-files/src/browser.js
new file mode 100755
index 000000000..a3677a7e4
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-browser-files/src/browser.js
@@ -0,0 +1,2 @@
+
+const b = 'foo';
diff --git a/packages/core/build/src/fixtures/build/babel-browser-files/src/node.js b/packages/core/build/src/fixtures/build/babel-browser-files/src/node.js
new file mode 100755
index 000000000..528eb6b5a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-browser-files/src/node.js
@@ -0,0 +1,2 @@
+
+const a = 'foo';
diff --git a/packages/core/build/src/fixtures/build/babel-cjs-lazy/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-cjs-lazy/.fatherrc.js
new file mode 100755
index 000000000..37192c105
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-cjs-lazy/.fatherrc.js
@@ -0,0 +1,8 @@
+
+export default {
+ target: 'node',
+ cjs: { type: 'babel', lazy: true },
+ browserFiles: [
+ 'src/foo.js',
+ ],
+};
diff --git a/packages/core/build/src/fixtures/build/babel-cjs-lazy/src/foo.js b/packages/core/build/src/fixtures/build/babel-cjs-lazy/src/foo.js
new file mode 100755
index 000000000..fafe4ba5f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-cjs-lazy/src/foo.js
@@ -0,0 +1,3 @@
+import bar from 'bar';
+
+bar();
diff --git a/packages/core/build/src/fixtures/build/babel-cjs-lazy/src/index.js b/packages/core/build/src/fixtures/build/babel-cjs-lazy/src/index.js
new file mode 100755
index 000000000..fafe4ba5f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-cjs-lazy/src/index.js
@@ -0,0 +1,3 @@
+import bar from 'bar';
+
+bar();
diff --git a/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/.fatherrc.js
new file mode 100755
index 000000000..b90b773fa
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/.fatherrc.js
@@ -0,0 +1,10 @@
+
+export default {
+ esm: { type: 'babel' },
+ extraBabelPresets: [
+ require.resolve('./preset'),
+ ],
+ extraBabelPlugins: [
+ require.resolve('./p2'),
+ ],
+};
diff --git a/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/expected/es/index.js
new file mode 100755
index 000000000..dd712d79e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/expected/es/index.js
@@ -0,0 +1,2 @@
+console.log("p1", "p2", 1);
+alert(2);
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/p1.js b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/p1.js
new file mode 100755
index 000000000..a3a3e24e1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/p1.js
@@ -0,0 +1,20 @@
+
+module.exports = function ({ types: t }) {
+ function isConsoleLog(node) {
+ const { callee, callee: { object, property } } = node;
+ return t.isMemberExpression(callee)
+ && t.isIdentifier(object) && object.name === 'console'
+ && t.isIdentifier(property) && property.name === 'log';
+ }
+
+ return {
+ visitor: {
+ CallExpression(path, state) {
+ const { node, node: { callee, callee: { object, property } } } = path;
+ if (isConsoleLog(node)) {
+ node.arguments.unshift(t.stringLiteral('p1'));
+ }
+ },
+ },
+ };
+}
diff --git a/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/p2.js b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/p2.js
new file mode 100755
index 000000000..297ac66d1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/p2.js
@@ -0,0 +1,20 @@
+
+module.exports = function ({ types: t }) {
+ function isConsoleLog(node) {
+ const { callee, callee: { object, property } } = node;
+ return t.isMemberExpression(callee)
+ && t.isIdentifier(object) && object.name === 'console'
+ && t.isIdentifier(property) && property.name === 'log';
+ }
+
+ return {
+ visitor: {
+ CallExpression(path, state) {
+ const { node, node: { callee, callee: { object, property } } } = path;
+ if (isConsoleLog(node)) {
+ node.arguments.unshift(t.stringLiteral('p2'));
+ }
+ },
+ },
+ };
+}
diff --git a/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/preset.js b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/preset.js
new file mode 100755
index 000000000..07ccbb29c
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/preset.js
@@ -0,0 +1,8 @@
+
+module.exports = function () {
+ return {
+ plugins: [
+ require.resolve('./p1'),
+ ],
+ };
+}
diff --git a/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/src/index.js b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/src/index.js
new file mode 100755
index 000000000..923799068
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-extra-babel-presets-and-plugins/src/index.js
@@ -0,0 +1,3 @@
+
+console.log(1);
+alert(2);
diff --git a/packages/core/build/src/fixtures/build/babel-importLibToEs/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-importLibToEs/.fatherrc.js
new file mode 100755
index 000000000..f1ef9292b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-importLibToEs/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel', importLibToEs: true },
+};
diff --git a/packages/core/build/src/fixtures/build/babel-importLibToEs/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-importLibToEs/expected/es/index.js
new file mode 100755
index 000000000..d10ef2731
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-importLibToEs/expected/es/index.js
@@ -0,0 +1,2 @@
+import foo from "foo/es/foo";
+console.log(foo());
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-importLibToEs/src/index.js b/packages/core/build/src/fixtures/build/babel-importLibToEs/src/index.js
new file mode 100755
index 000000000..a8105c428
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-importLibToEs/src/index.js
@@ -0,0 +1,3 @@
+import foo from 'foo/lib/foo';
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/.fatherrc.js
new file mode 100755
index 000000000..ead5605aa
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel' },
+ lessInBabelMode: false,
+};
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/foo.js b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/foo.js
new file mode 100755
index 000000000..85ffde227
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/foo.js
@@ -0,0 +1,6 @@
+
+import "./index.less";
+import "./foo.module.less";
+export default function () {
+ return 'foo';
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/foo.module.less b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/foo.module.less
new file mode 100755
index 000000000..213d0676a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/foo.module.less
@@ -0,0 +1,3 @@
+.foo {
+ color: green;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/index.less b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/index.less
new file mode 100755
index 000000000..f151aa5e7
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/expected/es/index.less
@@ -0,0 +1,6 @@
+
+@link-color: green;
+
+.foo {
+ color: @link-color;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/foo.js b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/foo.js
new file mode 100755
index 000000000..e1cab23ea
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/foo.js
@@ -0,0 +1,6 @@
+import "./index.less";
+import "./foo.module.less";
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/foo.module.less b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/foo.module.less
new file mode 100755
index 000000000..213d0676a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/foo.module.less
@@ -0,0 +1,3 @@
+.foo {
+ color: green;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/index.less b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/index.less
new file mode 100755
index 000000000..f151aa5e7
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css-forbid/src/index.less
@@ -0,0 +1,6 @@
+
+@link-color: green;
+
+.foo {
+ color: @link-color;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-less-to-css/.fatherrc.js
new file mode 100755
index 000000000..c2ed104b4
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel' },
+ lessInBabelMode: true,
+};
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/foo.js b/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/foo.js
new file mode 100755
index 000000000..a70263317
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/foo.js
@@ -0,0 +1,6 @@
+
+import "./index.css";
+import "./foo.module.css";
+export default function () {
+ return 'foo';
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/foo.module.css b/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/foo.module.css
new file mode 100755
index 000000000..213d0676a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/foo.module.css
@@ -0,0 +1,3 @@
+.foo {
+ color: green;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/index.css b/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/index.css
new file mode 100755
index 000000000..213d0676a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css/expected/es/index.css
@@ -0,0 +1,3 @@
+.foo {
+ color: green;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css/src/foo.js b/packages/core/build/src/fixtures/build/babel-less-to-css/src/foo.js
new file mode 100755
index 000000000..e1cab23ea
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css/src/foo.js
@@ -0,0 +1,6 @@
+import "./index.less";
+import "./foo.module.less";
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css/src/foo.module.less b/packages/core/build/src/fixtures/build/babel-less-to-css/src/foo.module.less
new file mode 100755
index 000000000..213d0676a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css/src/foo.module.less
@@ -0,0 +1,3 @@
+.foo {
+ color: green;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-less-to-css/src/index.less b/packages/core/build/src/fixtures/build/babel-less-to-css/src/index.less
new file mode 100755
index 000000000..f151aa5e7
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-less-to-css/src/index.less
@@ -0,0 +1,6 @@
+
+@link-color: green;
+
+.foo {
+ color: @link-color;
+}
diff --git a/packages/core/build/src/fixtures/build/babel-node-files/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-node-files/.fatherrc.js
new file mode 100755
index 000000000..ea494d59f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-files/.fatherrc.js
@@ -0,0 +1,8 @@
+
+export default {
+ esm: 'babel',
+ target: 'browser',
+ nodeFiles: [
+ 'src/node.js',
+ ],
+}
diff --git a/packages/core/build/src/fixtures/build/babel-node-files/expected/es/browser.js b/packages/core/build/src/fixtures/build/babel-node-files/expected/es/browser.js
new file mode 100755
index 000000000..22dc0e15f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-files/expected/es/browser.js
@@ -0,0 +1 @@
+var b = 'foo';
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-node-files/expected/es/node.js b/packages/core/build/src/fixtures/build/babel-node-files/expected/es/node.js
new file mode 100755
index 000000000..ed389c023
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-files/expected/es/node.js
@@ -0,0 +1 @@
+const a = 'foo';
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-node-files/src/browser.js b/packages/core/build/src/fixtures/build/babel-node-files/src/browser.js
new file mode 100755
index 000000000..a3677a7e4
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-files/src/browser.js
@@ -0,0 +1,2 @@
+
+const b = 'foo';
diff --git a/packages/core/build/src/fixtures/build/babel-node-files/src/node.js b/packages/core/build/src/fixtures/build/babel-node-files/src/node.js
new file mode 100755
index 000000000..528eb6b5a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-files/src/node.js
@@ -0,0 +1,2 @@
+
+const a = 'foo';
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/.fatherrc.js
new file mode 100755
index 000000000..d59f32117
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ esm: 'babel',
+ target: 'node',
+}
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/B.d.ts b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/B.d.ts
new file mode 100755
index 000000000..2ef04fb23
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/B.d.ts
@@ -0,0 +1 @@
+declare const b = "foo";
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/B.js b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/B.js
new file mode 100755
index 000000000..22dc0e15f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/B.js
@@ -0,0 +1 @@
+var b = 'foo';
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/C.js b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/C.js
new file mode 100755
index 000000000..22dc0e15f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/C.js
@@ -0,0 +1 @@
+var b = 'foo';
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/node.js b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/node.js
new file mode 100755
index 000000000..ed389c023
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/expected/es/node.js
@@ -0,0 +1 @@
+const a = 'foo';
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/B.tsx b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/B.tsx
new file mode 100755
index 000000000..a3677a7e4
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/B.tsx
@@ -0,0 +1,2 @@
+
+const b = 'foo';
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/C.jsx b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/C.jsx
new file mode 100755
index 000000000..a3677a7e4
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/C.jsx
@@ -0,0 +1,2 @@
+
+const b = 'foo';
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/node.js b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/node.js
new file mode 100755
index 000000000..528eb6b5a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/src/node.js
@@ -0,0 +1,2 @@
+
+const a = 'foo';
diff --git a/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/tsconfig.json b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/tsconfig.json
new file mode 100755
index 000000000..6db6275c3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-node-tsx-jsx/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "target": "esnext",
+ "moduleResolution": "node",
+ "jsx": "preserve",
+ "esModuleInterop": true,
+ "declaration": true
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/babel-normal/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-normal/.fatherrc.js
new file mode 100755
index 000000000..19390b36b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel' },
+};
diff --git a/packages/core/build/src/fixtures/build/babel-normal/expected/es/foo.js b/packages/core/build/src/fixtures/build/babel-normal/expected/es/foo.js
new file mode 100755
index 000000000..29a891a23
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/expected/es/foo.js
@@ -0,0 +1,3 @@
+export default function () {
+ return 'foo';
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-normal/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-normal/expected/es/index.js
new file mode 100755
index 000000000..8b2cbd724
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/expected/es/index.js
@@ -0,0 +1,3 @@
+import 'bar';
+import foo from './foo';
+console.log(foo());
\ No newline at end of file
diff --git a/packages/core/create-nocobase-app/src/resources/files/packages/app/server/.gitkeep b/packages/core/build/src/fixtures/build/babel-normal/expected/es/types.d.ts
old mode 100644
new mode 100755
similarity index 100%
rename from packages/core/create-nocobase-app/src/resources/files/packages/app/server/.gitkeep
rename to packages/core/build/src/fixtures/build/babel-normal/expected/es/types.d.ts
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/__test__/__snapshots__/index.test.js.snap b/packages/core/build/src/fixtures/build/babel-normal/src/__test__/__snapshots__/index.test.js.snap
new file mode 100755
index 000000000..7c645e42f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/__test__/__snapshots__/index.test.js.snap
@@ -0,0 +1 @@
+export default {};
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/__test__/index.test.js b/packages/core/build/src/fixtures/build/babel-normal/src/__test__/index.test.js
new file mode 100755
index 000000000..ff8b4c563
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/__test__/index.test.js
@@ -0,0 +1 @@
+export default {};
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/bar.md b/packages/core/build/src/fixtures/build/babel-normal/src/bar.md
new file mode 100755
index 000000000..d93e603dc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/bar.md
@@ -0,0 +1 @@
+# bar
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/bar.mdx b/packages/core/build/src/fixtures/build/babel-normal/src/bar.mdx
new file mode 100755
index 000000000..d93e603dc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/bar.mdx
@@ -0,0 +1 @@
+# bar
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/demos/foo.js b/packages/core/build/src/fixtures/build/babel-normal/src/demos/foo.js
new file mode 100755
index 000000000..eb59b1b29
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/demos/foo.js
@@ -0,0 +1,3 @@
+export default function() {
+ return "foo";
+}
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/fixtures/example/package.json b/packages/core/build/src/fixtures/build/babel-normal/src/fixtures/example/package.json
new file mode 100755
index 000000000..9e26dfeeb
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/fixtures/example/package.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/core/create-nocobase-app/src/resources/files/packages/plugins/.gitkeep b/packages/core/build/src/fixtures/build/babel-normal/src/foo.e2e.ts
old mode 100644
new mode 100755
similarity index 100%
rename from packages/core/create-nocobase-app/src/resources/files/packages/plugins/.gitkeep
rename to packages/core/build/src/fixtures/build/babel-normal/src/foo.e2e.ts
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/foo.js b/packages/core/build/src/fixtures/build/babel-normal/src/foo.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/foo.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/create-nocobase-app/src/resources/files/storage/.gitignore b/packages/core/build/src/fixtures/build/babel-normal/src/foo.spec.ts
old mode 100644
new mode 100755
similarity index 100%
rename from packages/core/create-nocobase-app/src/resources/files/storage/.gitignore
rename to packages/core/build/src/fixtures/build/babel-normal/src/foo.spec.ts
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.js b/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.js
new file mode 100755
index 000000000..e69de29bb
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.jsx b/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.jsx
new file mode 100755
index 000000000..e69de29bb
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.ts b/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.ts
new file mode 100755
index 000000000..e69de29bb
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.tsx b/packages/core/build/src/fixtures/build/babel-normal/src/foo.test.tsx
new file mode 100755
index 000000000..e69de29bb
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/index.js b/packages/core/build/src/fixtures/build/babel-normal/src/index.js
new file mode 100755
index 000000000..9d80d06dc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-normal/src/index.js
@@ -0,0 +1,4 @@
+import 'bar';
+import foo from './foo';
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/babel-normal/src/types.d.ts b/packages/core/build/src/fixtures/build/babel-normal/src/types.d.ts
new file mode 100755
index 000000000..e69de29bb
diff --git a/packages/core/build/src/fixtures/build/babel-runtimeHelpers/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/.fatherrc.js
new file mode 100755
index 000000000..6d1ce8487
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ runtimeHelpers: true,
+ esm: { type: 'babel' },
+ cjs: { type: 'babel' },
+}
diff --git a/packages/core/build/src/fixtures/build/babel-runtimeHelpers/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/expected/es/index.js
new file mode 100755
index 000000000..9a5518f11
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/expected/es/index.js
@@ -0,0 +1,21 @@
+import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
+import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
+import _createClass from "@babel/runtime/helpers/esm/createClass";
+
+var A = /*#__PURE__*/function () {
+ function A() {
+ _classCallCheck(this, A);
+ }
+
+ _createClass(A, [{
+ key: "foo",
+ value: function foo() {}
+ }]);
+
+ return A;
+}();
+
+new A().foo();
+var a = {};
+
+var b = _objectSpread({}, a);
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-runtimeHelpers/package.json b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/package.json
new file mode 100755
index 000000000..9c4a09846
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "@babel/runtime": "7.10.4"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/babel-runtimeHelpers/src/index.js b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/src/index.js
new file mode 100755
index 000000000..5f0d5578c
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-runtimeHelpers/src/index.js
@@ -0,0 +1,9 @@
+
+class A {
+ foo() {}
+}
+
+(new A()).foo();
+
+const a = {};
+const b = {...a};
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-syntax/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-syntax/.fatherrc.js
new file mode 100755
index 000000000..8b9450222
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-syntax/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+};
diff --git a/packages/core/build/src/fixtures/build/babel-syntax/expected/index.esm.js b/packages/core/build/src/fixtures/build/babel-syntax/expected/index.esm.js
new file mode 100755
index 000000000..c74948696
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-syntax/expected/index.esm.js
@@ -0,0 +1,84 @@
+import React from 'react';
+
+function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+}
+
+function _objectWithoutPropertiesLoose(source, excluded) {
+ if (source == null) return {};
+ var target = {};
+ var sourceKeys = Object.keys(source);
+ var key, i;
+
+ for (i = 0; i < sourceKeys.length; i++) {
+ key = sourceKeys[i];
+ if (excluded.indexOf(key) >= 0) continue;
+ target[key] = source[key];
+ }
+
+ return target;
+}
+
+function _objectWithoutProperties(source, excluded) {
+ if (source == null) return {};
+
+ var target = _objectWithoutPropertiesLoose(source, excluded);
+
+ var key, i;
+
+ if (Object.getOwnPropertySymbols) {
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
+
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
+ key = sourceSymbolKeys[i];
+ if (excluded.indexOf(key) >= 0) continue;
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
+ target[key] = source[key];
+ }
+ }
+
+ return target;
+}
+
+function a () {
+ alert('a');
+}
+
+function b1() {
+ alert('b1');
+}
+function b2() {
+ alert('b2');
+}
+
+var b = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ b1: b1,
+ b2: b2
+});
+
+var _class;
+// babel-plugin-react-require
+var Foo = function Foo() {
+ return /*#__PURE__*/React.createElement("div", null);
+}; // Don't support multiple chunks for now
+// @babel/plugin-syntax-dynamic-import
+// import('./a');
+// object-rest-spread
+
+var _bar = bar,
+ foo = _bar.foo,
+ z = _objectWithoutProperties(_bar, ["foo"]);
+
+console.log(z); // @babel/plugin-proposal-decorators + class
+
+var A = foo(_class = function A() {
+ _classCallCheck(this, A);
+}) || _class; // export default from
+
+var a$1 = x > 10 ? 'big' : 'small';
+console.log(a$1); // export namespace from
+
+export { A, Foo, a, b };
diff --git a/packages/core/build/src/fixtures/build/babel-syntax/package.json b/packages/core/build/src/fixtures/build/babel-syntax/package.json
new file mode 100755
index 000000000..1368588bd
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-syntax/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "react": "^16.8.4"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/babel-syntax/src/a.js b/packages/core/build/src/fixtures/build/babel-syntax/src/a.js
new file mode 100755
index 000000000..4e005dbee
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-syntax/src/a.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ alert('a');
+}
diff --git a/packages/core/build/src/fixtures/build/babel-syntax/src/b.js b/packages/core/build/src/fixtures/build/babel-syntax/src/b.js
new file mode 100755
index 000000000..c03767c13
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-syntax/src/b.js
@@ -0,0 +1,8 @@
+
+export function b1() {
+ alert('b1');
+}
+
+export function b2() {
+ alert('b2');
+}
diff --git a/packages/core/build/src/fixtures/build/babel-syntax/src/index.js b/packages/core/build/src/fixtures/build/babel-syntax/src/index.js
new file mode 100755
index 000000000..aec1e847b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-syntax/src/index.js
@@ -0,0 +1,32 @@
+
+// babel-plugin-react-require
+export const Foo = () => ;
+
+// Don't support multiple chunks for now
+// @babel/plugin-syntax-dynamic-import
+// import('./a');
+
+// object-rest-spread
+const { foo, ...z } = bar;
+console.log(z);
+
+// @babel/plugin-proposal-decorators + class
+@foo
+export class A {}
+
+// export default from
+export a from './a';
+
+// do expression
+let a = do {
+ if(x > 10) {
+ 'big';
+ } else {
+ 'small';
+ }
+};
+console.log(a);
+
+// export namespace from
+export * as b from './b';
+
diff --git a/packages/core/build/src/fixtures/build/babel-ts-3.7-features/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/.fatherrc.js
new file mode 100755
index 000000000..0637dcfc5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/.fatherrc.js
@@ -0,0 +1,4 @@
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel' },
+};
diff --git a/packages/core/build/src/fixtures/build/babel-ts-3.7-features/expected/es/index.d.ts b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/expected/es/index.d.ts
new file mode 100755
index 000000000..daaf9ca46
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/expected/es/index.d.ts
@@ -0,0 +1,2 @@
+export declare const optionalChaining: string;
+export declare const nullishCoalescing: string | boolean;
diff --git a/packages/core/build/src/fixtures/build/babel-ts-3.7-features/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/expected/es/index.js
new file mode 100755
index 000000000..640b9525a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/expected/es/index.js
@@ -0,0 +1,6 @@
+var _foo$test;
+
+var foo = {};
+export var optionalChaining = foo === null || foo === void 0 ? void 0 : (_foo$test = foo.test) === null || _foo$test === void 0 ? void 0 : _foo$test.abc;
+var bar = false;
+export var nullishCoalescing = bar !== null && bar !== void 0 ? bar : 'default';
diff --git a/packages/core/build/src/fixtures/build/babel-ts-3.7-features/src/index.ts b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/src/index.ts
new file mode 100755
index 000000000..5ed0adeb7
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-ts-3.7-features/src/index.ts
@@ -0,0 +1,11 @@
+type Foo = {
+ test?: {
+ abc?: string;
+ }
+}
+const foo: Foo = {};
+
+export const optionalChaining = foo?.test?.abc;
+
+const bar = false;
+export const nullishCoalescing = bar ?? 'default';
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/.fatherrc.js
new file mode 100755
index 000000000..166359112
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel' },
+ disableTypeCheck: true,
+};
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/expected/es/index.js
new file mode 100755
index 000000000..da1c4ebf5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/expected/es/index.js
@@ -0,0 +1,3 @@
+export default function foo(opts) {
+ return opts.foo ? 'foo' : 'bar';
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/src/index.ts b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/src/index.ts
new file mode 100755
index 000000000..3a0363ce2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/src/index.ts
@@ -0,0 +1,7 @@
+interface IOpts {
+ foo: boolean;
+}
+
+export default function foo(opts: IOpts): string {
+ return opts.foo ? 'foo' : 'bar';
+}
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/tsconfig.json b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/tsconfig.json
new file mode 100755
index 000000000..d322bf935
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-disable-typecheck/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "target": "esnext",
+ "moduleResolution": "node",
+ "jsx": "preserve",
+ "esModuleInterop": true
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-template/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-typescript-template/.fatherrc.js
new file mode 100755
index 000000000..19390b36b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-template/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel' },
+};
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-template/expected/es/index.d.ts b/packages/core/build/src/fixtures/build/babel-typescript-template/expected/es/index.d.ts
new file mode 100755
index 000000000..9f688a7e2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-template/expected/es/index.d.ts
@@ -0,0 +1,5 @@
+interface IOpts {
+ foo: boolean;
+}
+export default function foo(opts: IOpts): string;
+export {};
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-template/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-typescript-template/expected/es/index.js
new file mode 100755
index 000000000..da1c4ebf5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-template/expected/es/index.js
@@ -0,0 +1,3 @@
+export default function foo(opts) {
+ return opts.foo ? 'foo' : 'bar';
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-typescript-template/src/index.ts b/packages/core/build/src/fixtures/build/babel-typescript-template/src/index.ts
new file mode 100755
index 000000000..3a0363ce2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript-template/src/index.ts
@@ -0,0 +1,7 @@
+interface IOpts {
+ foo: boolean;
+}
+
+export default function foo(opts: IOpts): string {
+ return opts.foo ? 'foo' : 'bar';
+}
diff --git a/packages/core/build/src/fixtures/build/babel-typescript/.fatherrc.js b/packages/core/build/src/fixtures/build/babel-typescript/.fatherrc.js
new file mode 100755
index 000000000..19390b36b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ cjs: { type: 'babel' },
+ esm: { type: 'babel' },
+};
diff --git a/packages/core/build/src/fixtures/build/babel-typescript/expected/es/index.d.ts b/packages/core/build/src/fixtures/build/babel-typescript/expected/es/index.d.ts
new file mode 100755
index 000000000..9f688a7e2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript/expected/es/index.d.ts
@@ -0,0 +1,5 @@
+interface IOpts {
+ foo: boolean;
+}
+export default function foo(opts: IOpts): string;
+export {};
diff --git a/packages/core/build/src/fixtures/build/babel-typescript/expected/es/index.js b/packages/core/build/src/fixtures/build/babel-typescript/expected/es/index.js
new file mode 100755
index 000000000..da1c4ebf5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript/expected/es/index.js
@@ -0,0 +1,3 @@
+export default function foo(opts) {
+ return opts.foo ? 'foo' : 'bar';
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/babel-typescript/src/index.ts b/packages/core/build/src/fixtures/build/babel-typescript/src/index.ts
new file mode 100755
index 000000000..3a0363ce2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript/src/index.ts
@@ -0,0 +1,7 @@
+interface IOpts {
+ foo: boolean;
+}
+
+export default function foo(opts: IOpts): string {
+ return opts.foo ? 'foo' : 'bar';
+}
diff --git a/packages/core/build/src/fixtures/build/babel-typescript/tsconfig.json b/packages/core/build/src/fixtures/build/babel-typescript/tsconfig.json
new file mode 100755
index 000000000..fd3ce93b7
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/babel-typescript/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ // tsconfig is not valid josn file
+ "target": "esnext",
+ "moduleResolution": "node",
+ "jsx": "preserve",
+ "esModuleInterop": true,
+ "declaration": true
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/config-array/.fatherrc.js b/packages/core/build/src/fixtures/build/config-array/.fatherrc.js
new file mode 100755
index 000000000..695d856f1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/config-array/.fatherrc.js
@@ -0,0 +1,13 @@
+
+export default [
+ {
+ cjs: 'babel',
+ },
+ {
+ entry: 'ui/index.js',
+ umd: {
+ name: 'foo',
+ minFile: false,
+ },
+ },
+];
diff --git a/packages/core/build/src/fixtures/build/config-array/expected/index.umd.js b/packages/core/build/src/fixtures/build/config-array/expected/index.umd.js
new file mode 100755
index 000000000..f610a7710
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/config-array/expected/index.umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.foo = factory());
+}(this, (function () { 'use strict';
+
+ var index = (function () {
+ return 1;
+ });
+
+ return index;
+
+})));
diff --git a/packages/core/build/src/fixtures/build/config-array/src/index.js b/packages/core/build/src/fixtures/build/config-array/src/index.js
new file mode 100755
index 000000000..be26f6dda
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/config-array/src/index.js
@@ -0,0 +1,2 @@
+
+export default () => 1;
diff --git a/packages/core/build/src/fixtures/build/config-array/ui/index.js b/packages/core/build/src/fixtures/build/config-array/ui/index.js
new file mode 100755
index 000000000..807a7975a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/config-array/ui/index.js
@@ -0,0 +1 @@
+export default () => 1;
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-pkgs/.fatherrc.js
new file mode 100755
index 000000000..391752f4d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/.fatherrc.js
@@ -0,0 +1,8 @@
+
+export default {
+ esm: { type: 'rollup' },
+ pkgs: [
+ 'foo',
+ 'bar'
+ ]
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/core/bar/package.json b/packages/core/build/src/fixtures/build/lerna-pkgs/core/bar/package.json
new file mode 100755
index 000000000..694594cfe
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/core/bar/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "bar"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/core/bar/src/index.js b/packages/core/build/src/fixtures/build/lerna-pkgs/core/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/core/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/core/foo/package.json b/packages/core/build/src/fixtures/build/lerna-pkgs/core/foo/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/core/foo/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/core/foo/src/index.js b/packages/core/build/src/fixtures/build/lerna-pkgs/core/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/core/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/expected/bar/index.esm.js b/packages/core/build/src/fixtures/build/lerna-pkgs/expected/bar/index.esm.js
new file mode 100755
index 000000000..8cc7aa3e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/expected/bar/index.esm.js
@@ -0,0 +1 @@
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/expected/foo/index.esm.js b/packages/core/build/src/fixtures/build/lerna-pkgs/expected/foo/index.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/expected/foo/index.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-pkgs/lerna.json b/packages/core/build/src/fixtures/build/lerna-pkgs/lerna.json
new file mode 100755
index 000000000..e85dc989a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-pkgs/lerna.json
@@ -0,0 +1,5 @@
+{
+ "packages": [
+ "core/*"
+ ]
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-root-config-override/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/expected/bar/index.js b/packages/core/build/src/fixtures/build/lerna-root-config-override/expected/bar/index.js
new file mode 100755
index 000000000..2b1938520
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/expected/bar/index.js
@@ -0,0 +1,3 @@
+'use strict';
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/expected/foo/index.js b/packages/core/build/src/fixtures/build/lerna-root-config-override/expected/foo/index.js
new file mode 100755
index 000000000..aece69e8b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/expected/foo/index.js
@@ -0,0 +1,3 @@
+'use strict';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/lerna.json b/packages/core/build/src/fixtures/build/lerna-root-config-override/lerna.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/lerna.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/bar/package.json b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/bar/package.json
new file mode 100755
index 000000000..694594cfe
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/bar/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "bar"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/bar/src/index.js b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/foo/package.json b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/foo/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/foo/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/foo/src/index.js b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config-override/packages/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-root-config/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/expected/bar/index.esm.js b/packages/core/build/src/fixtures/build/lerna-root-config/expected/bar/index.esm.js
new file mode 100755
index 000000000..8cc7aa3e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/expected/bar/index.esm.js
@@ -0,0 +1 @@
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/expected/foo/index.esm.js b/packages/core/build/src/fixtures/build/lerna-root-config/expected/foo/index.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/expected/foo/index.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/lerna.json b/packages/core/build/src/fixtures/build/lerna-root-config/lerna.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/lerna.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/packages/bar/package.json b/packages/core/build/src/fixtures/build/lerna-root-config/packages/bar/package.json
new file mode 100755
index 000000000..694594cfe
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/packages/bar/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "bar"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/packages/bar/src/index.js b/packages/core/build/src/fixtures/build/lerna-root-config/packages/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/packages/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/packages/foo/package.json b/packages/core/build/src/fixtures/build/lerna-root-config/packages/foo/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/packages/foo/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-config/packages/foo/src/index.js b/packages/core/build/src/fixtures/build/lerna-root-config/packages/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-config/packages/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-root-scope/.fatherrc.js
new file mode 100755
index 000000000..5c4c510bf
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/.fatherrc.js
@@ -0,0 +1,3 @@
+export default {
+ esm: { type: 'babel' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/expected/bar/index.esm.js b/packages/core/build/src/fixtures/build/lerna-root-scope/expected/bar/index.esm.js
new file mode 100755
index 000000000..8cc7aa3e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/expected/bar/index.esm.js
@@ -0,0 +1 @@
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/expected/foo/index.esm.js b/packages/core/build/src/fixtures/build/lerna-root-scope/expected/foo/index.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/expected/foo/index.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/lerna.json b/packages/core/build/src/fixtures/build/lerna-root-scope/lerna.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/lerna.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/.fatherrc.js
new file mode 100755
index 000000000..030fee174
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/.fatherrc.js
@@ -0,0 +1,3 @@
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/package.json b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/package.json
new file mode 100755
index 000000000..694594cfe
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "bar"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/src/index.js b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/.fatherrc.js
new file mode 100755
index 000000000..030fee174
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/.fatherrc.js
@@ -0,0 +1,3 @@
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/package.json b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/src/index.js b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-scope/packages/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/.fatherrc.js
new file mode 100755
index 000000000..2875def12
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'babel' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/expected/bar/es/index.js b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/expected/bar/es/index.js
new file mode 100755
index 000000000..11f6ee783
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/expected/bar/es/index.js
@@ -0,0 +1,3 @@
+export default (function () {
+ console.log('bar');
+});
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/expected/foo/es/index.js b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/expected/foo/es/index.js
new file mode 100755
index 000000000..1f28f54e8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/expected/foo/es/index.js
@@ -0,0 +1,3 @@
+export default (function () {
+ console.log('foo');
+});
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/lerna.json b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/lerna.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/lerna.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/bar/package.json b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/bar/package.json
new file mode 100755
index 000000000..694594cfe
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/bar/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "bar"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/bar/src/index.ts b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/bar/src/index.ts
new file mode 100755
index 000000000..f053c5b21
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/bar/src/index.ts
@@ -0,0 +1,4 @@
+
+export default () => {
+ console.log('bar');
+};
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/foo/package.json b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/foo/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/foo/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/foo/src/index.ts b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/foo/src/index.ts
new file mode 100755
index 000000000..32ecfb320
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/packages/foo/src/index.ts
@@ -0,0 +1,4 @@
+
+export default () => {
+ console.log('foo');
+};
diff --git a/packages/core/build/src/fixtures/build/lerna-root-tsconfig/tsconfig.json b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/tsconfig.json
new file mode 100755
index 000000000..38fe9e814
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-root-tsconfig/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "declaration": false,
+ "target": "esnext",
+ "module": "esnext",
+ "moduleResolution": "node",
+ "jsx": "react",
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true
+ },
+ "exclude": ["node_modules", "es", "lib", "dist"]
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/expected/bar/index.esm.js b/packages/core/build/src/fixtures/build/lerna-scope-packages/expected/bar/index.esm.js
new file mode 100755
index 000000000..8cc7aa3e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/expected/bar/index.esm.js
@@ -0,0 +1 @@
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/expected/foo/index.esm.js b/packages/core/build/src/fixtures/build/lerna-scope-packages/expected/foo/index.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/expected/foo/index.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/lerna.json b/packages/core/build/src/fixtures/build/lerna-scope-packages/lerna.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/lerna.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/package.json b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/package.json
new file mode 100755
index 000000000..d970115c2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "@hoo/bar"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/src/index.js b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/@hoo/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/package.json b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/src/index.js b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna-scope-packages/packages/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna/expected/bar/index.esm.js b/packages/core/build/src/fixtures/build/lerna/expected/bar/index.esm.js
new file mode 100755
index 000000000..8cc7aa3e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/expected/bar/index.esm.js
@@ -0,0 +1 @@
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna/expected/foo/index.esm.js b/packages/core/build/src/fixtures/build/lerna/expected/foo/index.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/expected/foo/index.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/lerna/lerna.json b/packages/core/build/src/fixtures/build/lerna/lerna.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/lerna.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/fixtures/build/lerna/packages/bar/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna/packages/bar/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/packages/bar/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna/packages/bar/package.json b/packages/core/build/src/fixtures/build/lerna/packages/bar/package.json
new file mode 100755
index 000000000..694594cfe
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/packages/bar/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "bar"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna/packages/bar/src/index.js b/packages/core/build/src/fixtures/build/lerna/packages/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/packages/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/lerna/packages/foo/.fatherrc.js b/packages/core/build/src/fixtures/build/lerna/packages/foo/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/packages/foo/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/lerna/packages/foo/package.json b/packages/core/build/src/fixtures/build/lerna/packages/foo/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/packages/foo/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/lerna/packages/foo/src/index.js b/packages/core/build/src/fixtures/build/lerna/packages/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/lerna/packages/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/.fatherrc.js b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/.fatherrc.js
new file mode 100755
index 000000000..6e6bd69f5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ umd: {
+ minFile: false,
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/expected/index.umd.js b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/expected/index.umd.js
new file mode 100755
index 000000000..3819aa8e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/expected/index.umd.js
@@ -0,0 +1,43 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.foo = factory());
+}(this, (function () { 'use strict';
+
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
+
+ function createCommonjsModule(fn, basedir, module) {
+ return module = {
+ path: basedir,
+ exports: {},
+ require: function (path, base) {
+ return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
+ }
+ }, fn(module, module.exports), module.exports;
+ }
+
+ function commonjsRequire () {
+ throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
+ }
+
+ var lib = createCommonjsModule(function (module) {
+ (function (root, factory) {
+ if ( module.exports) {
+ module.exports = factory();
+ } else {
+ root.timing2 = factory();
+ }
+ }(typeof self !== 'undefined' ? self : commonjsGlobal, function () {
+ return {
+ timing2: 'timing2',
+ };
+ }));
+ });
+
+ function index () {
+ console.log(lib);
+ }
+
+ return index;
+
+})));
diff --git a/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/package.json b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/package.json
new file mode 100755
index 000000000..bde99de92
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "foo"
+}
diff --git a/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/packages/fooo/package.json b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/packages/fooo/package.json
new file mode 100755
index 000000000..de662967e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/packages/fooo/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "fooo",
+ "dependencies": {
+ "timing2": "^0.3.3"
+ },
+ "scripts": {
+ "build": "father build --umd"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/packages/fooo/src/index.js b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/packages/fooo/src/index.js
new file mode 100755
index 000000000..ce3b69ab5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/packages/fooo/src/index.js
@@ -0,0 +1,5 @@
+import timing2 from 'timing2';
+
+export default function() {
+ console.log(timing2);
+};
diff --git a/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/src/index.js b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/src/index.js
new file mode 100755
index 000000000..917890035
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/require-node_modules-in-sub-directory/src/index.js
@@ -0,0 +1 @@
+export { default } from '../packages/fooo/src/index';
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/.fatherrc.js
new file mode 100755
index 000000000..6e6bd69f5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ umd: {
+ minFile: false,
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/expected/index.umd.js
new file mode 100755
index 000000000..1a43aefbc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/expected/index.umd.js
@@ -0,0 +1,34 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ function createCommonjsModule(fn, basedir, module) {
+ return module = {
+ path: basedir,
+ exports: {},
+ require: function (path, base) {
+ return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
+ }
+ }, fn(module, module.exports), module.exports;
+ }
+
+ function commonjsRequire () {
+ throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
+ }
+
+ var foo_1 = createCommonjsModule(function (module, exports) {
+ var foo = exports;
+
+ foo.a = function () {
+ return 'a';
+ };
+ foo.b = function () {
+ return 'b';
+ };
+ });
+
+ console.log(foo_1.a());
+ console.log(foo_1.b());
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/package.json b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/package.json
new file mode 100755
index 000000000..040bc3a1e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "foo": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/src/index.js b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/src/index.js
new file mode 100755
index 000000000..8fa897e84
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps-auto-named-exports/src/index.js
@@ -0,0 +1,4 @@
+import { a, b } from 'foo';
+
+console.log(a());
+console.log(b());
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/.fatherrc.js
new file mode 100755
index 000000000..6e6bd69f5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ umd: {
+ minFile: false,
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/expected/index.umd.js
new file mode 100755
index 000000000..2c1ff18ce
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/expected/index.umd.js
@@ -0,0 +1,18 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ var foo = {
+ a: function () {
+ return 'a';
+ },
+ b: function () {
+ return 'b';
+ },
+ };
+
+ console.log(foo.a());
+ console.log(foo.b());
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps/package.json b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/package.json
new file mode 100755
index 000000000..040bc3a1e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "foo": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-commonjs-deps/src/index.js b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/src/index.js
new file mode 100755
index 000000000..8fa897e84
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-commonjs-deps/src/index.js
@@ -0,0 +1,4 @@
+import { a, b } from 'foo';
+
+console.log(a());
+console.log(b());
diff --git a/packages/core/build/src/fixtures/build/rollup-config-alias/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-config-alias/.fatherrc.js
new file mode 100755
index 000000000..85815c788
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-config-alias/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: 'rollup',
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-config-alias/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-config-alias/expected/index.esm.js
new file mode 100755
index 000000000..586fcf9a5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-config-alias/expected/index.esm.js
@@ -0,0 +1,6 @@
+var foo = 'a';
+function index () {
+ console.log(foo);
+}
+
+export default index;
diff --git a/packages/core/build/src/fixtures/build/rollup-config-alias/src/index.js b/packages/core/build/src/fixtures/build/rollup-config-alias/src/index.js
new file mode 100755
index 000000000..80c65e1f0
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-config-alias/src/index.js
@@ -0,0 +1,6 @@
+
+const foo = 'a';
+
+export default function () {
+ console.log(foo);
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/.fatherrc.js
new file mode 100755
index 000000000..5f43af600
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/.fatherrc.js
@@ -0,0 +1,10 @@
+
+export default {
+ esm: { type: 'rollup' },
+ autoprefixer: {
+ overrideBrowserslist: [
+ 'ie>8',
+ 'Safari >= 6',
+ ],
+ },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/expected/index.esm.js
new file mode 100755
index 000000000..7724570da
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/expected/index.esm.js
@@ -0,0 +1,31 @@
+function styleInject(css, ref) {
+ if ( ref === void 0 ) ref = {};
+ var insertAt = ref.insertAt;
+
+ if (!css || typeof document === 'undefined') { return; }
+
+ var head = document.head || document.getElementsByTagName('head')[0];
+ var style = document.createElement('style');
+ style.type = 'text/css';
+
+ if (insertAt === 'top') {
+ if (head.firstChild) {
+ head.insertBefore(style, head.firstChild);
+ } else {
+ head.appendChild(style);
+ }
+ } else {
+ head.appendChild(style);
+ }
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+}
+
+var css_248z = "\n.a {\n display: -webkit-box;\n display: -webkit-flex;\n display: -ms-flexbox;\n display: flex;\n}\n";
+styleInject(css_248z);
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/src/foo.css b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/src/foo.css
new file mode 100755
index 000000000..b4d332f68
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/src/foo.css
@@ -0,0 +1,4 @@
+
+.a {
+ display: flex;
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/src/index.js b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/src/index.js
new file mode 100755
index 000000000..9a761d97a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-autoprefixer/src/index.js
@@ -0,0 +1,3 @@
+import './foo.css';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-css-extract/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-css-extract/.fatherrc.js
new file mode 100755
index 000000000..c01e2a255
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-extract/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ extractCSS: true,
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css-extract/expected/index.esm.css b/packages/core/build/src/fixtures/build/rollup-css-extract/expected/index.esm.css
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-extract/expected/index.esm.css
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-css-extract/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-css-extract/expected/index.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-extract/expected/index.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-css-extract/src/foo.css b/packages/core/build/src/fixtures/build/rollup-css-extract/src/foo.css
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-extract/src/foo.css
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-css-extract/src/index.js b/packages/core/build/src/fixtures/build/rollup-css-extract/src/index.js
new file mode 100755
index 000000000..9a761d97a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-extract/src/index.js
@@ -0,0 +1,3 @@
+import './foo.css';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-css-inject/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-css-inject/.fatherrc.js
new file mode 100755
index 000000000..c39568546
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-inject/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ injectCSS: false,
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css-inject/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-css-inject/expected/index.esm.js
new file mode 100755
index 000000000..d5522693b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-inject/expected/index.esm.js
@@ -0,0 +1,3 @@
+var css_248z = "\n.a { color: green; }\n";
+
+console.log(css_248z);
diff --git a/packages/core/build/src/fixtures/build/rollup-css-inject/src/foo.css b/packages/core/build/src/fixtures/build/rollup-css-inject/src/foo.css
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-inject/src/foo.css
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-css-inject/src/index.js b/packages/core/build/src/fixtures/build/rollup-css-inject/src/index.js
new file mode 100755
index 000000000..b2bb60ab0
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-inject/src/index.js
@@ -0,0 +1,3 @@
+import style from './foo.css';
+
+console.log(style);
diff --git a/packages/core/build/src/fixtures/build/rollup-css-modules/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-css-modules/.fatherrc.js
new file mode 100755
index 000000000..d75347b75
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-modules/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ esm: { type: 'rollup' },
+ cssModules: true,
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css-modules/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-css-modules/expected/index.esm.js
new file mode 100755
index 000000000..7e6569e18
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-modules/expected/index.esm.js
@@ -0,0 +1,32 @@
+function styleInject(css, ref) {
+ if ( ref === void 0 ) ref = {};
+ var insertAt = ref.insertAt;
+
+ if (!css || typeof document === 'undefined') { return; }
+
+ var head = document.head || document.getElementsByTagName('head')[0];
+ var style = document.createElement('style');
+ style.type = 'text/css';
+
+ if (insertAt === 'top') {
+ if (head.firstChild) {
+ head.insertBefore(style, head.firstChild);
+ } else {
+ head.appendChild(style);
+ }
+ } else {
+ head.appendChild(style);
+ }
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+}
+
+var css_248z = "\n.foo_a__3z5g- { color: green; }\n";
+var styles = {"a":"foo_a__3z5g-"};
+styleInject(css_248z);
+
+console.log('foo', styles.a);
diff --git a/packages/core/build/src/fixtures/build/rollup-css-modules/src/foo.css b/packages/core/build/src/fixtures/build/rollup-css-modules/src/foo.css
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-modules/src/foo.css
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-css-modules/src/index.js b/packages/core/build/src/fixtures/build/rollup-css-modules/src/index.js
new file mode 100755
index 000000000..0ebd23438
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css-modules/src/index.js
@@ -0,0 +1,3 @@
+import styles from './foo.css';
+
+console.log('foo', styles.a);
diff --git a/packages/core/build/src/fixtures/build/rollup-css/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-css/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-css/expected/index.esm.js
new file mode 100755
index 000000000..f7e62e7a8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css/expected/index.esm.js
@@ -0,0 +1,31 @@
+function styleInject(css, ref) {
+ if ( ref === void 0 ) ref = {};
+ var insertAt = ref.insertAt;
+
+ if (!css || typeof document === 'undefined') { return; }
+
+ var head = document.head || document.getElementsByTagName('head')[0];
+ var style = document.createElement('style');
+ style.type = 'text/css';
+
+ if (insertAt === 'top') {
+ if (head.firstChild) {
+ head.insertBefore(style, head.firstChild);
+ } else {
+ head.appendChild(style);
+ }
+ } else {
+ head.appendChild(style);
+ }
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+}
+
+var css_248z = "\n.a {\n color: green;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n}\n";
+styleInject(css_248z);
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-css/src/foo.css b/packages/core/build/src/fixtures/build/rollup-css/src/foo.css
new file mode 100755
index 000000000..ca6e9cd5d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css/src/foo.css
@@ -0,0 +1,7 @@
+
+.a {
+ color: green;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-css/src/index.js b/packages/core/build/src/fixtures/build/rollup-css/src/index.js
new file mode 100755
index 000000000..9a761d97a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-css/src/index.js
@@ -0,0 +1,3 @@
+import './foo.css';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-dynamic-import/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-dynamic-import/.fatherrc.js
new file mode 100755
index 000000000..8b9450222
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-dynamic-import/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-dynamic-import/expected/bar-fc754098.js b/packages/core/build/src/fixtures/build/rollup-dynamic-import/expected/bar-fc754098.js
new file mode 100755
index 000000000..d35211662
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-dynamic-import/expected/bar-fc754098.js
@@ -0,0 +1,5 @@
+var bar = function bar() {
+ return 'bar';
+};
+
+export { bar };
diff --git a/packages/core/build/src/fixtures/build/rollup-dynamic-import/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-dynamic-import/expected/index.esm.js
new file mode 100755
index 000000000..c18af1dcb
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-dynamic-import/expected/index.esm.js
@@ -0,0 +1,2 @@
+var bar = import('./bar-fc754098.js');
+console.log(bar());
diff --git a/packages/core/build/src/fixtures/build/rollup-dynamic-import/src/bar.js b/packages/core/build/src/fixtures/build/rollup-dynamic-import/src/bar.js
new file mode 100755
index 000000000..be06675d9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-dynamic-import/src/bar.js
@@ -0,0 +1 @@
+export const bar = () => 'bar'
diff --git a/packages/core/build/src/fixtures/build/rollup-dynamic-import/src/index.js b/packages/core/build/src/fixtures/build/rollup-dynamic-import/src/index.js
new file mode 100755
index 000000000..70ba96a42
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-dynamic-import/src/index.js
@@ -0,0 +1,3 @@
+const bar = import('./bar')
+
+console.log(bar())
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-file/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-esm-file/.fatherrc.js
new file mode 100755
index 000000000..ae65f17f5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-file/.fatherrc.js
@@ -0,0 +1,7 @@
+
+export default {
+ esm: {
+ type: 'rollup',
+ file: 'demo.esm'
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-file/expected/demo.esm.js b/packages/core/build/src/fixtures/build/rollup-esm-file/expected/demo.esm.js
new file mode 100755
index 000000000..a2248efc6
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-file/expected/demo.esm.js
@@ -0,0 +1 @@
+console.log('test');
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-file/package.json b/packages/core/build/src/fixtures/build/rollup-esm-file/package.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-file/package.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-file/src/index.js b/packages/core/build/src/fixtures/build/rollup-esm-file/src/index.js
new file mode 100755
index 000000000..a2248efc6
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-file/src/index.js
@@ -0,0 +1 @@
+console.log('test');
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-minify/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-esm-minify/.fatherrc.js
new file mode 100755
index 000000000..25ded9459
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-minify/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup', minify: true },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-minify/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-esm-minify/expected/index.esm.js
new file mode 100755
index 000000000..f05f55286
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-minify/expected/index.esm.js
@@ -0,0 +1 @@
+function o(){console.log("foo")}export default o;
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-minify/package.json b/packages/core/build/src/fixtures/build/rollup-esm-minify/package.json
new file mode 100755
index 000000000..81bb2b631
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-minify/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "bar": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-minify/src/foo.js b/packages/core/build/src/fixtures/build/rollup-esm-minify/src/foo.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-minify/src/foo.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-minify/src/index.js b/packages/core/build/src/fixtures/build/rollup-esm-minify/src/index.js
new file mode 100755
index 000000000..079e99f5a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-minify/src/index.js
@@ -0,0 +1,5 @@
+import foo from './foo';
+
+export default function () {
+ console.log(foo());
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-mjs/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-esm-mjs/.fatherrc.js
new file mode 100755
index 000000000..ed89f5d34
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-mjs/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup', mjs: true },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-mjs/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-esm-mjs/expected/index.esm.js
new file mode 100755
index 000000000..6890cce5b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-mjs/expected/index.esm.js
@@ -0,0 +1,6 @@
+import 'bar';
+
+function index () {
+}
+
+export default index;
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-mjs/expected/index.mjs b/packages/core/build/src/fixtures/build/rollup-esm-mjs/expected/index.mjs
new file mode 100755
index 000000000..8f73bfe1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-mjs/expected/index.mjs
@@ -0,0 +1 @@
+function o(){}console.log("bar");export default o;
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-mjs/package.json b/packages/core/build/src/fixtures/build/rollup-esm-mjs/package.json
new file mode 100755
index 000000000..81bb2b631
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-mjs/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "bar": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-mjs/src/foo.js b/packages/core/build/src/fixtures/build/rollup-esm-mjs/src/foo.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-mjs/src/foo.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-esm-mjs/src/index.js b/packages/core/build/src/fixtures/build/rollup-esm-mjs/src/index.js
new file mode 100755
index 000000000..01d696690
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-esm-mjs/src/index.js
@@ -0,0 +1,6 @@
+import 'bar';
+import foo from './foo';
+
+export default function () {
+ foo();
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-externalsExclude/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-externalsExclude/.fatherrc.js
new file mode 100755
index 000000000..8ab27f0f1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-externalsExclude/.fatherrc.js
@@ -0,0 +1,11 @@
+
+export default {
+ esm: { type: 'rollup' },
+ cjs: { type: 'rollup' },
+ extraExternals: [
+ 'foo',
+ ],
+ externalsExclude: [
+ 'foo/bar',
+ ],
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-externalsExclude/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-externalsExclude/expected/index.esm.js
new file mode 100755
index 000000000..60d2ac221
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-externalsExclude/expected/index.esm.js
@@ -0,0 +1,5 @@
+import 'foo';
+
+(() => {
+ console.log('bar');
+})();
diff --git a/packages/core/build/src/fixtures/build/rollup-externalsExclude/expected/index.js b/packages/core/build/src/fixtures/build/rollup-externalsExclude/expected/index.js
new file mode 100755
index 000000000..98f72615c
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-externalsExclude/expected/index.js
@@ -0,0 +1,7 @@
+'use strict';
+
+require('foo');
+
+(() => {
+ console.log('bar');
+})();
diff --git a/packages/core/build/src/fixtures/build/rollup-externalsExclude/package.json b/packages/core/build/src/fixtures/build/rollup-externalsExclude/package.json
new file mode 100755
index 000000000..6a3252ea8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-externalsExclude/package.json
@@ -0,0 +1,3 @@
+{
+ "version": "0.1.0"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-externalsExclude/src/index.js b/packages/core/build/src/fixtures/build/rollup-externalsExclude/src/index.js
new file mode 100755
index 000000000..40d29331c
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-externalsExclude/src/index.js
@@ -0,0 +1,2 @@
+import 'foo';
+import 'foo/bar';
diff --git a/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/.fatherrc.js
new file mode 100755
index 000000000..0dfd93f4b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/.fatherrc.js
@@ -0,0 +1,10 @@
+
+export default {
+ esm: { type: 'rollup' },
+ extraBabelPresets: [
+ require.resolve('./preset'),
+ ],
+ extraBabelPlugins: [
+ require.resolve('./p2'),
+ ],
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/expected/index.esm.js
new file mode 100755
index 000000000..0b60c0ede
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/expected/index.esm.js
@@ -0,0 +1,2 @@
+console.log("p1", "p2", 1);
+alert(2);
diff --git a/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/p1.js b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/p1.js
new file mode 100755
index 000000000..a3a3e24e1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/p1.js
@@ -0,0 +1,20 @@
+
+module.exports = function ({ types: t }) {
+ function isConsoleLog(node) {
+ const { callee, callee: { object, property } } = node;
+ return t.isMemberExpression(callee)
+ && t.isIdentifier(object) && object.name === 'console'
+ && t.isIdentifier(property) && property.name === 'log';
+ }
+
+ return {
+ visitor: {
+ CallExpression(path, state) {
+ const { node, node: { callee, callee: { object, property } } } = path;
+ if (isConsoleLog(node)) {
+ node.arguments.unshift(t.stringLiteral('p1'));
+ }
+ },
+ },
+ };
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/p2.js b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/p2.js
new file mode 100755
index 000000000..297ac66d1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/p2.js
@@ -0,0 +1,20 @@
+
+module.exports = function ({ types: t }) {
+ function isConsoleLog(node) {
+ const { callee, callee: { object, property } } = node;
+ return t.isMemberExpression(callee)
+ && t.isIdentifier(object) && object.name === 'console'
+ && t.isIdentifier(property) && property.name === 'log';
+ }
+
+ return {
+ visitor: {
+ CallExpression(path, state) {
+ const { node, node: { callee, callee: { object, property } } } = path;
+ if (isConsoleLog(node)) {
+ node.arguments.unshift(t.stringLiteral('p2'));
+ }
+ },
+ },
+ };
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/preset.js b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/preset.js
new file mode 100755
index 000000000..07ccbb29c
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/preset.js
@@ -0,0 +1,8 @@
+
+module.exports = function () {
+ return {
+ plugins: [
+ require.resolve('./p1'),
+ ],
+ };
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/src/index.js b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/src/index.js
new file mode 100755
index 000000000..923799068
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extra-babel-presets-and-plugins/src/index.js
@@ -0,0 +1,3 @@
+
+console.log(1);
+alert(2);
diff --git a/packages/core/build/src/fixtures/build/rollup-extraExternals/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-extraExternals/.fatherrc.js
new file mode 100755
index 000000000..409af0a2c
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraExternals/.fatherrc.js
@@ -0,0 +1,9 @@
+
+export default {
+ esm: { type: 'rollup' },
+ extraExternals: [
+ '@ali/foo',
+ '@tmp',
+ 'foo',
+ ]
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-extraExternals/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-extraExternals/expected/index.esm.js
new file mode 100755
index 000000000..1a8c84dab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraExternals/expected/index.esm.js
@@ -0,0 +1,5 @@
+import 'foo';
+import '@ali/foo';
+import '@ali/foo/bar';
+import '@tmp/foo';
+import '@tmp/foo/bar';
diff --git a/packages/core/build/src/fixtures/build/rollup-extraExternals/package.json b/packages/core/build/src/fixtures/build/rollup-extraExternals/package.json
new file mode 100755
index 000000000..6a3252ea8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraExternals/package.json
@@ -0,0 +1,3 @@
+{
+ "version": "0.1.0"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-extraExternals/src/index.js b/packages/core/build/src/fixtures/build/rollup-extraExternals/src/index.js
new file mode 100755
index 000000000..3e307458f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraExternals/src/index.js
@@ -0,0 +1,6 @@
+
+import 'foo';
+import '@ali/foo';
+import '@ali/foo/bar';
+import '@tmp/foo';
+import '@tmp/foo/bar';
diff --git a/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/.fatherrc.js
new file mode 100755
index 000000000..f3438f39b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/.fatherrc.js
@@ -0,0 +1,10 @@
+import replace from 'rollup-plugin-replace';
+
+export default {
+ esm: { type: 'rollup' },
+ extraRollupPlugins: [
+ replace({
+ VERSION: JSON.stringify('1.0.0'),
+ }),
+ ],
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/expected/index.esm.js
new file mode 100755
index 000000000..22c71e692
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/expected/index.esm.js
@@ -0,0 +1 @@
+console.log("1.0.0");
diff --git a/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/package.json b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/package.json
new file mode 100755
index 000000000..6a3252ea8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/package.json
@@ -0,0 +1,3 @@
+{
+ "version": "0.1.0"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/src/index.js b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/src/index.js
new file mode 100755
index 000000000..2c9bf5559
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-extraRollupPlugins/src/index.js
@@ -0,0 +1,2 @@
+
+console.log(VERSION);
diff --git a/packages/core/build/src/fixtures/build/rollup-import-directory/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-import-directory/.fatherrc.js
new file mode 100755
index 000000000..8b9450222
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-import-directory/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-import-directory/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-import-directory/expected/index.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-import-directory/expected/index.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-import-directory/src/foo/index.js b/packages/core/build/src/fixtures/build/rollup-import-directory/src/foo/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-import-directory/src/foo/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-import-directory/src/index.js b/packages/core/build/src/fixtures/build/rollup-import-directory/src/index.js
new file mode 100755
index 000000000..ead12a719
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-import-directory/src/index.js
@@ -0,0 +1 @@
+import './foo';
diff --git a/packages/core/build/src/fixtures/build/rollup-importLibToEs/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-importLibToEs/.fatherrc.js
new file mode 100755
index 000000000..2881eb584
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-importLibToEs/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ cjs: { type: 'rollup' },
+ esm: { type: 'rollup', importLibToEs: true },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-importLibToEs/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-importLibToEs/expected/index.esm.js
new file mode 100755
index 000000000..ae0559b15
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-importLibToEs/expected/index.esm.js
@@ -0,0 +1,5 @@
+function foo () {
+ return 'es/foo';
+}
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/rollup-importLibToEs/expected/index.js b/packages/core/build/src/fixtures/build/rollup-importLibToEs/expected/index.js
new file mode 100755
index 000000000..c4e33e771
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-importLibToEs/expected/index.js
@@ -0,0 +1,7 @@
+'use strict';
+
+function foo () {
+ return 'lib/foo';
+}
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/rollup-importLibToEs/src/index.js b/packages/core/build/src/fixtures/build/rollup-importLibToEs/src/index.js
new file mode 100755
index 000000000..a8105c428
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-importLibToEs/src/index.js
@@ -0,0 +1,3 @@
+import foo from 'foo/lib/foo';
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/rollup-inject/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-inject/.fatherrc.js
new file mode 100755
index 000000000..cc0759d33
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-inject/.fatherrc.js
@@ -0,0 +1,7 @@
+
+export default {
+ esm: { type: 'rollup' },
+ inject: {
+ 'window.foo': 'foo',
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-inject/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-inject/expected/index.esm.js
new file mode 100755
index 000000000..2f87bded3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-inject/expected/index.esm.js
@@ -0,0 +1,3 @@
+import $inject_window_foo from 'foo';
+
+console.log($inject_window_foo);
diff --git a/packages/core/build/src/fixtures/build/rollup-inject/package.json b/packages/core/build/src/fixtures/build/rollup-inject/package.json
new file mode 100755
index 000000000..040bc3a1e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-inject/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "foo": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-inject/src/index.js b/packages/core/build/src/fixtures/build/rollup-inject/src/index.js
new file mode 100755
index 000000000..4f632e0de
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-inject/src/index.js
@@ -0,0 +1 @@
+console.log(window.foo);
diff --git a/packages/core/build/src/fixtures/build/rollup-json/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-json/.fatherrc.js
new file mode 100755
index 000000000..8b9450222
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-json/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-json/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-json/expected/index.esm.js
new file mode 100755
index 000000000..6ee3aced8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-json/expected/index.esm.js
@@ -0,0 +1,6 @@
+var foo = "bar";
+var pkg = {
+ foo: foo
+};
+
+console.log(pkg);
diff --git a/packages/core/build/src/fixtures/build/rollup-json/src/index.js b/packages/core/build/src/fixtures/build/rollup-json/src/index.js
new file mode 100755
index 000000000..3ce7d4a36
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-json/src/index.js
@@ -0,0 +1,3 @@
+import pkg from './pkg.json';
+
+console.log(pkg);
diff --git a/packages/core/build/src/fixtures/build/rollup-json/src/pkg.json b/packages/core/build/src/fixtures/build/rollup-json/src/pkg.json
new file mode 100755
index 000000000..c8c4105eb
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-json/src/pkg.json
@@ -0,0 +1,3 @@
+{
+ "foo": "bar"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-less-modules/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-less-modules/.fatherrc.js
new file mode 100755
index 000000000..d75347b75
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-modules/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ esm: { type: 'rollup' },
+ cssModules: true,
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-less-modules/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-less-modules/expected/index.esm.js
new file mode 100755
index 000000000..964691ea9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-modules/expected/index.esm.js
@@ -0,0 +1,32 @@
+function styleInject(css, ref) {
+ if ( ref === void 0 ) ref = {};
+ var insertAt = ref.insertAt;
+
+ if (!css || typeof document === 'undefined') { return; }
+
+ var head = document.head || document.getElementsByTagName('head')[0];
+ var style = document.createElement('style');
+ style.type = 'text/css';
+
+ if (insertAt === 'top') {
+ if (head.firstChild) {
+ head.insertBefore(style, head.firstChild);
+ } else {
+ head.appendChild(style);
+ }
+ } else {
+ head.appendChild(style);
+ }
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+}
+
+var css_248z = ".foo_a__1JvkR {\n color: green;\n}\n";
+var styles = {"a":"foo_a__1JvkR"};
+styleInject(css_248z);
+
+console.log('foo', styles.a);
diff --git a/packages/core/build/src/fixtures/build/rollup-less-modules/src/foo.less b/packages/core/build/src/fixtures/build/rollup-less-modules/src/foo.less
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-modules/src/foo.less
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-less-modules/src/index.js b/packages/core/build/src/fixtures/build/rollup-less-modules/src/index.js
new file mode 100755
index 000000000..9c442740f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-modules/src/index.js
@@ -0,0 +1,3 @@
+import styles from './foo.less';
+
+console.log('foo', styles.a);
diff --git a/packages/core/build/src/fixtures/build/rollup-less-node-modules/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-less-node-modules/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-node-modules/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-less-node-modules/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-less-node-modules/expected/index.esm.js
new file mode 100755
index 000000000..bea7558e7
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-node-modules/expected/index.esm.js
@@ -0,0 +1,31 @@
+function styleInject(css, ref) {
+ if ( ref === void 0 ) ref = {};
+ var insertAt = ref.insertAt;
+
+ if (!css || typeof document === 'undefined') { return; }
+
+ var head = document.head || document.getElementsByTagName('head')[0];
+ var style = document.createElement('style');
+ style.type = 'text/css';
+
+ if (insertAt === 'top') {
+ if (head.firstChild) {
+ head.insertBefore(style, head.firstChild);
+ } else {
+ head.appendChild(style);
+ }
+ } else {
+ head.appendChild(style);
+ }
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+}
+
+var css_248z = ".bar {\n color: red;\n}\n.a {\n color: green;\n}\n";
+styleInject(css_248z);
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-less-node-modules/src/foo.less b/packages/core/build/src/fixtures/build/rollup-less-node-modules/src/foo.less
new file mode 100755
index 000000000..f49f40a45
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-node-modules/src/foo.less
@@ -0,0 +1,3 @@
+@import '~foo/bar.less';
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-less-node-modules/src/index.js b/packages/core/build/src/fixtures/build/rollup-less-node-modules/src/index.js
new file mode 100755
index 000000000..eb9155cfc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less-node-modules/src/index.js
@@ -0,0 +1,3 @@
+import './foo.less';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-less/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-less/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-less/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-less/expected/index.esm.js
new file mode 100755
index 000000000..47e82c7fc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less/expected/index.esm.js
@@ -0,0 +1,31 @@
+function styleInject(css, ref) {
+ if ( ref === void 0 ) ref = {};
+ var insertAt = ref.insertAt;
+
+ if (!css || typeof document === 'undefined') { return; }
+
+ var head = document.head || document.getElementsByTagName('head')[0];
+ var style = document.createElement('style');
+ style.type = 'text/css';
+
+ if (insertAt === 'top') {
+ if (head.firstChild) {
+ head.insertBefore(style, head.firstChild);
+ } else {
+ head.appendChild(style);
+ }
+ } else {
+ head.appendChild(style);
+ }
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+}
+
+var css_248z = ".a {\n color: green;\n}\n";
+styleInject(css_248z);
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-less/src/foo.less b/packages/core/build/src/fixtures/build/rollup-less/src/foo.less
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less/src/foo.less
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-less/src/index.js b/packages/core/build/src/fixtures/build/rollup-less/src/index.js
new file mode 100755
index 000000000..eb9155cfc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-less/src/index.js
@@ -0,0 +1,3 @@
+import './foo.less';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-multiple-entry/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-multiple-entry/.fatherrc.js
new file mode 100755
index 000000000..c49c9b152
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-multiple-entry/.fatherrc.js
@@ -0,0 +1,8 @@
+
+export default {
+ entry: [
+ './src/foo.js',
+ './src/bar.js',
+ ],
+ esm: { type: 'rollup' },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-multiple-entry/expected/bar.esm.js b/packages/core/build/src/fixtures/build/rollup-multiple-entry/expected/bar.esm.js
new file mode 100755
index 000000000..8cc7aa3e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-multiple-entry/expected/bar.esm.js
@@ -0,0 +1 @@
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/rollup-multiple-entry/expected/foo.esm.js b/packages/core/build/src/fixtures/build/rollup-multiple-entry/expected/foo.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-multiple-entry/expected/foo.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-multiple-entry/src/bar.js b/packages/core/build/src/fixtures/build/rollup-multiple-entry/src/bar.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-multiple-entry/src/bar.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/rollup-multiple-entry/src/foo.js b/packages/core/build/src/fixtures/build/rollup-multiple-entry/src/foo.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-multiple-entry/src/foo.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-node-resolve/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-node-resolve/.fatherrc.js
new file mode 100755
index 000000000..5d6b9128e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-node-resolve/.fatherrc.js
@@ -0,0 +1,9 @@
+
+export default {
+ umd: {
+ minFile: false,
+ },
+ nodeResolveOpts: {
+ browser: true,
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-node-resolve/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-node-resolve/expected/index.umd.js
new file mode 100755
index 000000000..5e9006d51
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-node-resolve/expected/index.umd.js
@@ -0,0 +1,10 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ var browser = 'hello browser';
+
+ console.log(browser);
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-node-resolve/package.json b/packages/core/build/src/fixtures/build/rollup-node-resolve/package.json
new file mode 100755
index 000000000..040bc3a1e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-node-resolve/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "foo": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-node-resolve/src/index.js b/packages/core/build/src/fixtures/build/rollup-node-resolve/src/index.js
new file mode 100755
index 000000000..909687930
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-node-resolve/src/index.js
@@ -0,0 +1,3 @@
+import hello from 'foo';
+
+console.log(hello);
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-normal/.fatherrc.js
new file mode 100755
index 000000000..2ae3de8e2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ cjs: { type: 'rollup' },
+ esm: { type: 'rollup' },
+ umd: {},
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.esm.js
new file mode 100755
index 000000000..ea63e10f2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.esm.js
@@ -0,0 +1,7 @@
+import 'bar';
+
+function foo () {
+ return 'foo';
+}
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/expected/index.js b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.js
new file mode 100755
index 000000000..c50247820
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.js
@@ -0,0 +1,9 @@
+'use strict';
+
+require('bar');
+
+function foo () {
+ return 'foo';
+}
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.umd.js
new file mode 100755
index 000000000..ca82ca23f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.umd.js
@@ -0,0 +1,12 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(['bar'], factory) :
+ factory();
+}((function () { 'use strict';
+
+ function foo () {
+ return 'foo';
+ }
+
+ console.log(foo());
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/expected/index.umd.min.js b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.umd.min.js
new file mode 100755
index 000000000..c654cc12f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/expected/index.umd.min.js
@@ -0,0 +1 @@
+!function(n){"function"==typeof define&&define.amd?define(["bar"],n):n()}((function(){"use strict";console.log("foo")}));
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/package.json b/packages/core/build/src/fixtures/build/rollup-normal/package.json
new file mode 100755
index 000000000..5ca44beaa
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/package.json
@@ -0,0 +1,5 @@
+{
+ "peerDependencies": {
+ "bar": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/src/foo.js b/packages/core/build/src/fixtures/build/rollup-normal/src/foo.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/src/foo.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-normal/src/index.js b/packages/core/build/src/fixtures/build/rollup-normal/src/index.js
new file mode 100755
index 000000000..9d80d06dc
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-normal/src/index.js
@@ -0,0 +1,4 @@
+import 'bar';
+import foo from './foo';
+
+console.log(foo());
diff --git a/packages/core/build/src/fixtures/build/rollup-output-dir/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-output-dir/.fatherrc.js
new file mode 100755
index 000000000..463d29534
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-output-dir/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ entry: ['src/a.js', 'src/b.js'],
+ esm: { type: 'rollup', dir: 'dist/out' },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-output-dir/expected/out/a.esm.js b/packages/core/build/src/fixtures/build/rollup-output-dir/expected/out/a.esm.js
new file mode 100755
index 000000000..8609d0755
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-output-dir/expected/out/a.esm.js
@@ -0,0 +1 @@
+console.log('a');
diff --git a/packages/core/build/src/fixtures/build/rollup-output-dir/expected/out/b.esm.js b/packages/core/build/src/fixtures/build/rollup-output-dir/expected/out/b.esm.js
new file mode 100755
index 000000000..eeb313a03
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-output-dir/expected/out/b.esm.js
@@ -0,0 +1 @@
+console.log('b');
diff --git a/packages/core/build/src/fixtures/build/rollup-output-dir/src/a.js b/packages/core/build/src/fixtures/build/rollup-output-dir/src/a.js
new file mode 100755
index 000000000..ad0e1a70a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-output-dir/src/a.js
@@ -0,0 +1 @@
+console.log('a');
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/rollup-output-dir/src/b.js b/packages/core/build/src/fixtures/build/rollup-output-dir/src/b.js
new file mode 100755
index 000000000..3cd704307
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-output-dir/src/b.js
@@ -0,0 +1 @@
+console.log('b')
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/.fatherrc.js
new file mode 100755
index 000000000..1bc453016
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/.fatherrc.js
@@ -0,0 +1,29 @@
+
+export default {
+ entry: [
+ 'src/index.js',
+ 'src/foo.js',
+ 'src/bar.js',
+ ],
+ umd: {
+ },
+ cjs: { type: 'rollup' },
+ esm: { type: 'rollup' },
+ file: 'dva',
+ overridesByEntry: {
+ 'src/foo.js': {
+ file: 'dva.foo',
+ cjs: { type: 'rollup', file: 'dva.foo.cjs' },
+ esm: { type: 'rollup', file: 'dva.foo.esm' },
+ },
+ 'src/bar.js': {
+ cjs: false,
+ esm: false,
+ umd: { file: 'dva.bar' },
+ },
+ 'src/index.js': {
+ cjs: false,
+ esm: false,
+ },
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.bar.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.bar.js
new file mode 100755
index 000000000..70ba81f61
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.bar.js
@@ -0,0 +1,8 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ console.log('bar');
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.bar.min.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.bar.min.js
new file mode 100755
index 000000000..7f57ce5a8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.bar.min.js
@@ -0,0 +1 @@
+!function(n){"function"==typeof define&&define.amd?define(n):n()}((function(){"use strict";console.log("bar")}));
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.esm.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.esm.js
new file mode 100755
index 000000000..8cc7aa3e9
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.esm.js
@@ -0,0 +1 @@
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.cjs.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.cjs.js
new file mode 100755
index 000000000..aece69e8b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.cjs.js
@@ -0,0 +1,3 @@
+'use strict';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.esm.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.esm.js
new file mode 100755
index 000000000..81afa3157
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.esm.js
@@ -0,0 +1 @@
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.umd.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.umd.js
new file mode 100755
index 000000000..62e3a909f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.umd.js
@@ -0,0 +1,8 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ console.log('foo');
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.umd.min.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.umd.min.js
new file mode 100755
index 000000000..e383c2dd0
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.foo.umd.min.js
@@ -0,0 +1 @@
+!function(n){"function"==typeof define&&define.amd?define(n):n()}((function(){"use strict";console.log("foo")}));
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.js
new file mode 100755
index 000000000..2b1938520
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.js
@@ -0,0 +1,3 @@
+'use strict';
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.umd.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.umd.js
new file mode 100755
index 000000000..fd2bf1e89
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.umd.js
@@ -0,0 +1,8 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ console.log('index');
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.umd.min.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.umd.min.js
new file mode 100755
index 000000000..a15d21f33
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/expected/dva.umd.min.js
@@ -0,0 +1 @@
+!function(n){"function"==typeof define&&define.amd?define(n):n()}((function(){"use strict";console.log("index")}));
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/bar.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/bar.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/bar.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/foo.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/foo.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/foo.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/index.js b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/index.js
new file mode 100755
index 000000000..112a16294
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-outputFilename-with-overrides/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('index');
diff --git a/packages/core/build/src/fixtures/build/rollup-replace/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-replace/.fatherrc.js
new file mode 100755
index 000000000..5be9fca42
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-replace/.fatherrc.js
@@ -0,0 +1,7 @@
+
+export default {
+ esm: { type: 'rollup' },
+ replace: {
+ VERSION: JSON.stringify(require('./package').version),
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-replace/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-replace/expected/index.esm.js
new file mode 100755
index 000000000..3bbfad94d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-replace/expected/index.esm.js
@@ -0,0 +1 @@
+console.log("0.1.0");
diff --git a/packages/core/build/src/fixtures/build/rollup-replace/package.json b/packages/core/build/src/fixtures/build/rollup-replace/package.json
new file mode 100755
index 000000000..6a3252ea8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-replace/package.json
@@ -0,0 +1,3 @@
+{
+ "version": "0.1.0"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-replace/src/index.js b/packages/core/build/src/fixtures/build/rollup-replace/src/index.js
new file mode 100755
index 000000000..2c9bf5559
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-replace/src/index.js
@@ -0,0 +1,2 @@
+
+console.log(VERSION);
diff --git a/packages/core/build/src/fixtures/build/rollup-resolve-jsx/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/.fatherrc.js
new file mode 100755
index 000000000..8b9450222
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-resolve-jsx/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/expected/index.esm.js
new file mode 100755
index 000000000..949fb857b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/expected/index.esm.js
@@ -0,0 +1,11 @@
+import React from 'react';
+
+var Foo = (function () {
+ return /*#__PURE__*/React.createElement("h1", null, "Foo");
+});
+
+var index = (function () {
+ return /*#__PURE__*/React.createElement(Foo, null);
+});
+
+export default index;
diff --git a/packages/core/build/src/fixtures/build/rollup-resolve-jsx/package.json b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/package.json
new file mode 100755
index 000000000..55ef290f1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "react": "16"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-resolve-jsx/src/Foo.jsx b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/src/Foo.jsx
new file mode 100755
index 000000000..b518bbcb2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/src/Foo.jsx
@@ -0,0 +1,2 @@
+
+export default () => Foo
;
diff --git a/packages/core/build/src/fixtures/build/rollup-resolve-jsx/src/index.js b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/src/index.js
new file mode 100755
index 000000000..f61210cf6
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-resolve-jsx/src/index.js
@@ -0,0 +1,3 @@
+import Foo from './Foo';
+
+export default () => ;
diff --git a/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/.fatherrc.js
new file mode 100755
index 000000000..b3cf64724
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ runtimeHelpers: true,
+ esm: { type: 'rollup' },
+ cjs: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/expected/index.esm.js
new file mode 100755
index 000000000..1814cb26f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/expected/index.esm.js
@@ -0,0 +1,17 @@
+import _classCallCheck from '@babel/runtime/helpers/esm/classCallCheck';
+import _createClass from '@babel/runtime/helpers/esm/createClass';
+
+var A = /*#__PURE__*/function () {
+ function A() {
+ _classCallCheck(this, A);
+ }
+
+ _createClass(A, [{
+ key: "foo",
+ value: function foo() {}
+ }]);
+
+ return A;
+}();
+
+new A().foo();
diff --git a/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/expected/index.js b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/expected/index.js
new file mode 100755
index 000000000..73d0a72df
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/expected/index.js
@@ -0,0 +1,38 @@
+'use strict';
+
+function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+}
+
+function _defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+}
+
+function _createClass(Constructor, protoProps, staticProps) {
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) _defineProperties(Constructor, staticProps);
+ return Constructor;
+}
+
+var A = /*#__PURE__*/function () {
+ function A() {
+ _classCallCheck(this, A);
+ }
+
+ _createClass(A, [{
+ key: "foo",
+ value: function foo() {}
+ }]);
+
+ return A;
+}();
+
+new A().foo();
diff --git a/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/package.json b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/package.json
new file mode 100755
index 000000000..689bf9cfb
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "@babel/runtime": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/src/index.js b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/src/index.js
new file mode 100755
index 000000000..0cff149b2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-runtimeHelpers/src/index.js
@@ -0,0 +1,6 @@
+
+class A {
+ foo() {}
+}
+
+(new A()).foo();
diff --git a/packages/core/build/src/fixtures/build/rollup-sass/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-sass/.fatherrc.js
new file mode 100755
index 000000000..2f10183a3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-sass/.fatherrc.js
@@ -0,0 +1,4 @@
+
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-sass/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-sass/expected/index.esm.js
new file mode 100755
index 000000000..12763bf9a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-sass/expected/index.esm.js
@@ -0,0 +1,31 @@
+function styleInject(css, ref) {
+ if ( ref === void 0 ) ref = {};
+ var insertAt = ref.insertAt;
+
+ if (!css || typeof document === 'undefined') { return; }
+
+ var head = document.head || document.getElementsByTagName('head')[0];
+ var style = document.createElement('style');
+ style.type = 'text/css';
+
+ if (insertAt === 'top') {
+ if (head.firstChild) {
+ head.insertBefore(style, head.firstChild);
+ } else {
+ head.appendChild(style);
+ }
+ } else {
+ head.appendChild(style);
+ }
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+}
+
+var css_248z = ".a {\n color: green; }\n";
+styleInject(css_248z);
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-sass/src/foo.scss b/packages/core/build/src/fixtures/build/rollup-sass/src/foo.scss
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-sass/src/foo.scss
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-sass/src/index.js b/packages/core/build/src/fixtures/build/rollup-sass/src/index.js
new file mode 100755
index 000000000..28c5d8eb5
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-sass/src/index.js
@@ -0,0 +1,3 @@
+import './foo.scss';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-svgr/.umirc.library.js b/packages/core/build/src/fixtures/build/rollup-svgr/.umirc.library.js
new file mode 100755
index 000000000..030fee174
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-svgr/.umirc.library.js
@@ -0,0 +1,3 @@
+export default {
+ esm: { type: 'rollup' },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-svgr/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-svgr/expected/index.esm.js
new file mode 100755
index 000000000..51370ec9f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-svgr/expected/index.esm.js
@@ -0,0 +1,21 @@
+import React, { createElement } from 'react';
+
+var _defs, _path;
+
+function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
+
+function SvgMenu(props) {
+ return /*#__PURE__*/createElement("svg", _extends({
+ className: "menu_svg__icon",
+ viewBox: "0 0 1024 1024",
+ xmlns: "http://www.w3.org/2000/svg",
+ width: 200,
+ height: 200
+ }, props), _defs || (_defs = /*#__PURE__*/createElement("defs", null, /*#__PURE__*/createElement("style", null))), _path || (_path = /*#__PURE__*/createElement("path", {
+ d: "M656 512h160c8.8 0 16-7.2 16-16v-96c0-8.8-7.2-16-16-16H656c-8.8 0-16 7.2-16 16v22H346V320h86c8.8 0 16-7.2 16-16v-96c0-8.8-7.2-16-16-16H208c-8.8 0-16 7.2-16 16v96c0 8.8 7.2 16 16 16h86v378c0 17.7 14.3 32 32 32h314v22c0 8.8 7.2 16 16 16h160c8.8 0 16-7.2 16-16v-96c0-8.8-7.2-16-16-16H656c-8.8 0-16 7.2-16 16v22H346V474h294v22c0 8.8 7.2 16 16 16z"
+ })));
+}
+
+var svgUrl = "data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20standalone%3D%22no%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20t%3D%221558949630117%22%20class%3D%22icon%22%20style%3D%22%22%20viewBox%3D%220%200%201024%201024%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20%20%20%20%20p-id%3D%2233994%22%20%20%20%20%20width%3D%22200%22%20height%3D%22200%22%3E%20%20%3Cdefs%3E%20%20%20%20%3Cstyle%20type%3D%22text%2Fcss%22%3E%3C%2Fstyle%3E%20%20%3C%2Fdefs%3E%20%20%3Cpath%20%20%20%20d%3D%22M656%20512h160c8.8%200%2016-7.2%2016-16v-96c0-8.8-7.2-16-16-16H656c-8.8%200-16%207.2-16%2016v22H346V320h86c8.8%200%2016-7.2%2016-16v-96c0-8.8-7.2-16-16-16H208c-8.8%200-16%207.2-16%2016v96c0%208.8%207.2%2016%2016%2016h86v378c0%2017.7%2014.3%2032%2032%2032h314v22c0%208.8%207.2%2016%2016%2016h160c8.8%200%2016-7.2%2016-16v-96c0-8.8-7.2-16-16-16H656c-8.8%200-16%207.2-16%2016v22H346V474h294v22c0%208.8%207.2%2016%2016%2016z%22%20%20%20%20p-id%3D%2233995%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E";
+
+console.log(svgUrl, /*#__PURE__*/React.createElement(SvgMenu, null));
diff --git a/packages/core/build/src/fixtures/build/rollup-svgr/package.json b/packages/core/build/src/fixtures/build/rollup-svgr/package.json
new file mode 100755
index 000000000..55ef290f1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-svgr/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "react": "16"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-svgr/src/index.jsx b/packages/core/build/src/fixtures/build/rollup-svgr/src/index.jsx
new file mode 100755
index 000000000..769d90a58
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-svgr/src/index.jsx
@@ -0,0 +1,3 @@
+import svgUrl, { ReactComponent as MenuComponent } from './menu.svg';
+
+console.log(svgUrl, );
diff --git a/packages/core/build/src/fixtures/build/rollup-svgr/src/menu.svg b/packages/core/build/src/fixtures/build/rollup-svgr/src/menu.svg
new file mode 100755
index 000000000..bd7bb1417
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-svgr/src/menu.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/.fatherrc.ts b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/.fatherrc.ts
new file mode 100755
index 000000000..35309e6f8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/.fatherrc.ts
@@ -0,0 +1,7 @@
+export default {
+ cjs: 'rollup',
+ esm: 'rollup',
+ typescriptOpts: {
+ useTsconfigDeclarationDir: true,
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/index.esm.js
new file mode 100755
index 000000000..a0ca5bfdf
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/index.esm.js
@@ -0,0 +1,5 @@
+function foo(opts) {
+ return opts.foo ? 'foo' : 'bar';
+}
+
+export default foo;
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/index.js b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/index.js
new file mode 100755
index 000000000..39a5ac989
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/index.js
@@ -0,0 +1,7 @@
+'use strict';
+
+function foo(opts) {
+ return opts.foo ? 'foo' : 'bar';
+}
+
+module.exports = foo;
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/type/index.d.ts b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/type/index.d.ts
new file mode 100755
index 000000000..9eea9c0f1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/expected/type/index.d.ts
@@ -0,0 +1,5 @@
+interface IOpts {
+ foo: boolean;
+}
+export default function foo(opts: IOpts): string;
+export {};
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/src/index.ts b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/src/index.ts
new file mode 100755
index 000000000..3a0363ce2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/src/index.ts
@@ -0,0 +1,7 @@
+interface IOpts {
+ foo: boolean;
+}
+
+export default function foo(opts: IOpts): string {
+ return opts.foo ? 'foo' : 'bar';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/tsconfig.json b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/tsconfig.json
new file mode 100755
index 000000000..59dd44386
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "target": "esnext",
+ "moduleResolution": "node",
+ "jsx": "preserve",
+ "esModuleInterop": true,
+ "declarationDir": "dist/type"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/typings.d.ts b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/typings.d.ts
new file mode 100755
index 000000000..211708df8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript-declarationDir/typings.d.ts
@@ -0,0 +1,7 @@
+declare module '*.less' {
+ interface IClassNames {
+ [className: string]: string;
+ }
+ const classNames: IClassNames;
+ export = classNames;
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript/.fatherrc.ts b/packages/core/build/src/fixtures/build/rollup-typescript/.fatherrc.ts
new file mode 100755
index 000000000..3e130204e
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript/.fatherrc.ts
@@ -0,0 +1,4 @@
+export default {
+ cjs: 'rollup',
+ esm: 'rollup',
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.d.ts b/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.d.ts
new file mode 100755
index 000000000..9eea9c0f1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.d.ts
@@ -0,0 +1,5 @@
+interface IOpts {
+ foo: boolean;
+}
+export default function foo(opts: IOpts): string;
+export {};
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.esm.js b/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.esm.js
new file mode 100755
index 000000000..a0ca5bfdf
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.esm.js
@@ -0,0 +1,5 @@
+function foo(opts) {
+ return opts.foo ? 'foo' : 'bar';
+}
+
+export default foo;
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.js b/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.js
new file mode 100755
index 000000000..39a5ac989
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript/expected/index.js
@@ -0,0 +1,7 @@
+'use strict';
+
+function foo(opts) {
+ return opts.foo ? 'foo' : 'bar';
+}
+
+module.exports = foo;
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript/src/index.ts b/packages/core/build/src/fixtures/build/rollup-typescript/src/index.ts
new file mode 100755
index 000000000..3a0363ce2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript/src/index.ts
@@ -0,0 +1,7 @@
+interface IOpts {
+ foo: boolean;
+}
+
+export default function foo(opts: IOpts): string {
+ return opts.foo ? 'foo' : 'bar';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript/tsconfig.json b/packages/core/build/src/fixtures/build/rollup-typescript/tsconfig.json
new file mode 100755
index 000000000..d322bf935
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "target": "esnext",
+ "moduleResolution": "node",
+ "jsx": "preserve",
+ "esModuleInterop": true
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-typescript/typings.d.ts b/packages/core/build/src/fixtures/build/rollup-typescript/typings.d.ts
new file mode 100755
index 000000000..211708df8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-typescript/typings.d.ts
@@ -0,0 +1,7 @@
+declare module '*.less' {
+ interface IClassNames {
+ [className: string]: string;
+ }
+ const classNames: IClassNames;
+ export = classNames;
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-auto-name/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/.fatherrc.js
new file mode 100755
index 000000000..da054b287
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ umd: {
+ minFile: false
+ },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-auto-name/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/expected/index.umd.js
new file mode 100755
index 000000000..07691b4fa
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/expected/index.umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.fooBar = factory());
+}(this, (function () { 'use strict';
+
+ function index () {
+ return 'foo';
+ }
+
+ return index;
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-auto-name/package.json b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/package.json
new file mode 100755
index 000000000..a02a5e12d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "@umi/foo-bar"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-auto-name/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/src/index.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-auto-name/src/index.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-commonjs/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/.fatherrc.js
new file mode 100755
index 000000000..6a76fec2f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/.fatherrc.js
@@ -0,0 +1,6 @@
+export default {
+ umd: {
+ name: 'foo',
+ minFile: false,
+ }
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-commonjs/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/expected/index.umd.js
new file mode 100755
index 000000000..0cbb8eb4d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/expected/index.umd.js
@@ -0,0 +1,17 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ var parse = function parse() {};
+
+ var stringify = function stringify() {};
+
+ var queryString = {
+ parse: parse,
+ stringify: stringify
+ };
+
+ queryString.parse();
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-commonjs/package.json b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/package.json
new file mode 100755
index 000000000..6a3252ea8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/package.json
@@ -0,0 +1,3 @@
+{
+ "version": "0.1.0"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-commonjs/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/src/index.js
new file mode 100755
index 000000000..9ffbd962d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-commonjs/src/index.js
@@ -0,0 +1,2 @@
+import querystring from 'query-string';
+querystring.parse();
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/.fatherrc.js
new file mode 100755
index 000000000..e1ea4fca3
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/.fatherrc.js
@@ -0,0 +1,5 @@
+
+export default {
+ extractCSS: true,
+ umd: {},
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.css b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.css
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.css
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.js
new file mode 100755
index 000000000..62e3a909f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.js
@@ -0,0 +1,8 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ console.log('foo');
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.min.css b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.min.css
new file mode 100755
index 000000000..de2080200
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.min.css
@@ -0,0 +1 @@
+.a{color:green}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.min.js b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.min.js
new file mode 100755
index 000000000..e383c2dd0
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/expected/index.umd.min.js
@@ -0,0 +1 @@
+!function(n){"function"==typeof define&&define.amd?define(n):n()}((function(){"use strict";console.log("foo")}));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/src/foo.css b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/src/foo.css
new file mode 100755
index 000000000..ec0af869a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/src/foo.css
@@ -0,0 +1,2 @@
+
+.a { color: green; }
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/src/index.js
new file mode 100755
index 000000000..9a761d97a
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-css-extract-minFile/src/index.js
@@ -0,0 +1,3 @@
+import './foo.css';
+
+console.log('foo');
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/.fatherrc.js
new file mode 100755
index 000000000..f3ec30554
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/.fatherrc.js
@@ -0,0 +1,6 @@
+export default {
+ umd: {
+ name: 'foo',
+ minFile: false,
+ },
+};
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/expected/index.umd.js
new file mode 100755
index 000000000..7c4701511
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/expected/index.umd.js
@@ -0,0 +1,20 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.foo = {}));
+}(this, (function (exports) { 'use strict';
+
+ var hierarchy = function hierarchy() {};
+
+ const foo = () => {
+ };
+
+ var a = function a() {};
+
+ exports.a = a;
+ exports.foo = foo;
+ exports.hierarchy = hierarchy;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/package.json b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/package.json
new file mode 100755
index 000000000..6a3252ea8
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/package.json
@@ -0,0 +1,3 @@
+{
+ "version": "0.1.0"
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/src/a.js b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/src/a.js
new file mode 100755
index 000000000..a641ceb26
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/src/a.js
@@ -0,0 +1,3 @@
+const a = () => {
+}
+export { a };
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/src/index.js
new file mode 100755
index 000000000..8d5d40d2f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-es5ImcompatibleVersions/src/index.js
@@ -0,0 +1,7 @@
+
+// 在 es5ImcompatibleVersions 里配置的包
+export * from 'd3-hierarchy';
+// 不在 es5ImcompatibleVersions 里配置的包
+export * from 'foo';
+// 当前项目中的代码
+export * from './a';
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-globals/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-globals/.fatherrc.js
new file mode 100755
index 000000000..44cc7c460
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-globals/.fatherrc.js
@@ -0,0 +1,9 @@
+
+export default {
+ umd: {
+ minFile: false,
+ globals: {
+ foo: '$',
+ },
+ },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-globals/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-globals/expected/index.umd.js
new file mode 100755
index 000000000..07054a168
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-globals/expected/index.umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('foo')) :
+ typeof define === 'function' && define.amd ? define(['foo'], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.$));
+}(this, (function (foo) { 'use strict';
+
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
+
+ var foo__default = /*#__PURE__*/_interopDefaultLegacy(foo);
+
+ foo__default['default'].bar();
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-globals/package.json b/packages/core/build/src/fixtures/build/rollup-umd-globals/package.json
new file mode 100755
index 000000000..7390bd3d2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-globals/package.json
@@ -0,0 +1,5 @@
+{
+ "peerDependencies": {
+ "foo": "0.1.0"
+ }
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-globals/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-globals/src/index.js
new file mode 100755
index 000000000..5a079bee1
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-globals/src/index.js
@@ -0,0 +1,3 @@
+import foo from 'foo';
+
+foo.bar();
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-name/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-name/.fatherrc.js
new file mode 100755
index 000000000..be174297f
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-name/.fatherrc.js
@@ -0,0 +1,7 @@
+
+export default {
+ umd: {
+ minFile: false,
+ name: 'foo',
+ },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-name/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-name/expected/index.umd.js
new file mode 100755
index 000000000..0d2fbbcec
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-name/expected/index.umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.foo = factory());
+}(this, (function () { 'use strict';
+
+ function index () {
+ return 'foo';
+ }
+
+ return index;
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-name/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-name/src/index.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-name/src/index.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-overrides/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-overrides/.fatherrc.js
new file mode 100755
index 000000000..242848d42
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-overrides/.fatherrc.js
@@ -0,0 +1,18 @@
+
+export default {
+ entry: [
+ 'src/index.js',
+ 'src/fetch.js',
+ ],
+ umd: {
+ minFile: false,
+ name: 'foo',
+ },
+ overridesByEntry: {
+ 'src/fetch.js': {
+ umd: {
+ name: 'foo.fetch',
+ },
+ },
+ },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-overrides/expected/fetch.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-overrides/expected/fetch.umd.js
new file mode 100755
index 000000000..42b7f10ee
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-overrides/expected/fetch.umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, (global.foo = global.foo || {}, global.foo.fetch = factory()));
+}(this, (function () { 'use strict';
+
+ function fetch () {
+ return 'foo.fetch';
+ }
+
+ return fetch;
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-overrides/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-overrides/expected/index.umd.js
new file mode 100755
index 000000000..0d2fbbcec
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-overrides/expected/index.umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.foo = factory());
+}(this, (function () { 'use strict';
+
+ function index () {
+ return 'foo';
+ }
+
+ return index;
+
+})));
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-overrides/src/fetch.js b/packages/core/build/src/fixtures/build/rollup-umd-overrides/src/fetch.js
new file mode 100755
index 000000000..3fdd6c676
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-overrides/src/fetch.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo.fetch';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-overrides/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-overrides/src/index.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-overrides/src/index.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/.fatherrc.js b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/.fatherrc.js
new file mode 100755
index 000000000..ff17b2079
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/.fatherrc.js
@@ -0,0 +1,8 @@
+
+export default {
+ umd: {
+ minFile: false,
+ name: 'foo',
+ sourcemap: true,
+ },
+}
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/expected/index.umd.js b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/expected/index.umd.js
new file mode 100755
index 000000000..04e44df50
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/expected/index.umd.js
@@ -0,0 +1,14 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.foo = factory());
+}(this, (function () { 'use strict';
+
+ function index () {
+ return 'foo';
+ }
+
+ return index;
+
+})));
+//# sourceMappingURL=index.umd.js.map
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/expected/index.umd.js.map b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/expected/index.umd.js.map
new file mode 100755
index 000000000..bf6d50af4
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/expected/index.umd.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.umd.js","sources":["../src/index.js"],"sourcesContent":["\nexport default function () {\n return 'foo';\n}\n"],"names":[],"mappings":";;;;;;EACe,kBAAY;EACzB,SAAO,KAAP;EACD;;;;;;;;"}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/src/index.js b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/src/index.js
new file mode 100755
index 000000000..8fcf68e1b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/rollup-umd-sourcemap/src/index.js
@@ -0,0 +1,4 @@
+
+export default function () {
+ return 'foo';
+}
diff --git a/packages/core/build/src/fixtures/build/target-node-version/.fatherrc.js b/packages/core/build/src/fixtures/build/target-node-version/.fatherrc.js
new file mode 100755
index 000000000..41a0b5982
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/target-node-version/.fatherrc.js
@@ -0,0 +1,7 @@
+
+export default {
+ cjs: 'babel',
+ esm: 'babel',
+ target: 'node',
+ nodeVersion: 8,
+}
diff --git a/packages/core/build/src/fixtures/build/target-node-version/expected/es/index.js b/packages/core/build/src/fixtures/build/target-node-version/expected/es/index.js
new file mode 100755
index 000000000..ae6a5bdb2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/target-node-version/expected/es/index.js
@@ -0,0 +1,4 @@
+const foo = 'bar';
+export default async function () {
+ return foo;
+}
\ No newline at end of file
diff --git a/packages/core/build/src/fixtures/build/target-node-version/src/index.js b/packages/core/build/src/fixtures/build/target-node-version/src/index.js
new file mode 100755
index 000000000..8ab0b3a2d
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/target-node-version/src/index.js
@@ -0,0 +1,6 @@
+
+const foo = 'bar';
+
+export default async function() {
+ return foo;
+}
diff --git a/packages/core/build/src/fixtures/build/target-node/.fatherrc.js b/packages/core/build/src/fixtures/build/target-node/.fatherrc.js
new file mode 100755
index 000000000..a56516e62
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/target-node/.fatherrc.js
@@ -0,0 +1,6 @@
+
+export default {
+ cjs: 'rollup',
+ esm: 'rollup',
+ target: 'node',
+}
diff --git a/packages/core/build/src/fixtures/build/target-node/expected/index.esm.js b/packages/core/build/src/fixtures/build/target-node/expected/index.esm.js
new file mode 100755
index 000000000..3199bfb84
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/target-node/expected/index.esm.js
@@ -0,0 +1,6 @@
+var foo = 'bar';
+function index () {
+ return foo;
+}
+
+export default index;
diff --git a/packages/core/build/src/fixtures/build/target-node/expected/index.js b/packages/core/build/src/fixtures/build/target-node/expected/index.js
new file mode 100755
index 000000000..b1ccfd8a2
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/target-node/expected/index.js
@@ -0,0 +1,8 @@
+'use strict';
+
+const foo = 'bar';
+function index () {
+ return foo;
+}
+
+module.exports = index;
diff --git a/packages/core/build/src/fixtures/build/target-node/src/index.js b/packages/core/build/src/fixtures/build/target-node/src/index.js
new file mode 100755
index 000000000..1354e696b
--- /dev/null
+++ b/packages/core/build/src/fixtures/build/target-node/src/index.js
@@ -0,0 +1,6 @@
+
+const foo = 'bar';
+
+export default function() {
+ return foo;
+}
diff --git a/packages/core/build/src/getBabelConfig.ts b/packages/core/build/src/getBabelConfig.ts
new file mode 100755
index 000000000..2a2dba49b
--- /dev/null
+++ b/packages/core/build/src/getBabelConfig.ts
@@ -0,0 +1,95 @@
+import { extname } from 'path';
+import { ModuleFormat } from 'rollup';
+
+interface IGetBabelConfigOpts {
+ target: 'browser' | 'node';
+ type?: ModuleFormat;
+ typescript?: boolean;
+ runtimeHelpers?: boolean;
+ filePath?: string;
+ browserFiles?: {
+ [value: string]: any;
+ };
+ nodeVersion?: number;
+ nodeFiles?: {
+ [value: string]: any;
+ };
+ lazy?: boolean;
+ lessInBabelMode?: boolean|{
+ paths?: any[];
+ plugins?: any[];
+ };
+}
+
+function transformImportLess2Css() {
+ return {
+ name: 'transform-import-less-to-css',
+ visitor: {
+ ImportDeclaration(path, source) {
+ const re = /\.less$/;
+ if(re.test(path.node.source.value)){
+ path.node.source.value = path.node.source.value.replace(re, '.css');
+ }
+ }
+ }
+ }
+}
+
+export default function(opts: IGetBabelConfigOpts) {
+ const { target, typescript, type, runtimeHelpers, filePath, browserFiles, nodeFiles, nodeVersion, lazy, lessInBabelMode } = opts;
+ let isBrowser = target === 'browser';
+ // rollup 场景下不会传入 filePath
+ if (filePath) {
+ if (extname(filePath) === '.tsx' || extname(filePath) === '.jsx') {
+ isBrowser = true;
+ } else {
+ if (isBrowser) {
+ if (nodeFiles.includes(filePath)) isBrowser = false;
+ } else {
+ if (browserFiles.includes(filePath)) isBrowser = true;
+ }
+ }
+ }
+ const targets = isBrowser ? { browsers: ['last 2 versions', 'IE 10'] } : { node: nodeVersion || 6 };
+
+ return {
+ opts: {
+ presets: [
+ ...(typescript ? [require.resolve('@babel/preset-typescript')] : []),
+ [require.resolve('@babel/preset-env'), {
+ targets,
+ modules: type === 'esm' ? false : 'auto'
+ }],
+ ...(isBrowser ? [require.resolve('@babel/preset-react')] : []),
+ ],
+ plugins: [
+ ...((type === 'cjs' && lazy && !isBrowser)
+ ? [[require.resolve('@babel/plugin-transform-modules-commonjs'), {
+ lazy: true,
+ }]]
+ : []),
+ ...(lessInBabelMode ? [transformImportLess2Css] : []),
+ ...(isBrowser ? [require.resolve('babel-plugin-react-require')] : []),
+ require.resolve('@babel/plugin-syntax-dynamic-import'),
+ require.resolve('@babel/plugin-proposal-export-default-from'),
+ require.resolve('@babel/plugin-proposal-export-namespace-from'),
+ require.resolve('@babel/plugin-proposal-do-expressions'),
+ require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
+ require.resolve('@babel/plugin-proposal-optional-chaining'),
+ [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
+ [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }],
+ ...(runtimeHelpers
+ ? [[require.resolve('@babel/plugin-transform-runtime'), {
+ useESModules: isBrowser && (type === 'esm'),
+ version: require('@babel/runtime/package.json').version,
+ }]]
+ : []),
+ ...(process.env.COVERAGE
+ ? [require.resolve('babel-plugin-istanbul')]
+ : []
+ )
+ ],
+ },
+ isBrowser,
+ };
+}
diff --git a/packages/core/build/src/getRollupConfig.ts b/packages/core/build/src/getRollupConfig.ts
new file mode 100755
index 000000000..c7513bec4
--- /dev/null
+++ b/packages/core/build/src/getRollupConfig.ts
@@ -0,0 +1,343 @@
+import { existsSync } from 'fs'
+import { basename, extname, join } from 'path';
+import { ModuleFormat, RollupOptions, Plugin } from 'rollup';
+import url from '@rollup/plugin-url';
+import json from '@rollup/plugin-json';
+import replace from '@rollup/plugin-replace';
+import commonjs from '@rollup/plugin-commonjs';
+import nodeResolve from '@rollup/plugin-node-resolve';
+import inject, { RollupInjectOptions } from '@rollup/plugin-inject';
+import babel, { RollupBabelInputPluginOptions } from '@rollup/plugin-babel';
+import { createFilter } from '@rollup/pluginutils';
+import postcss from 'rollup-plugin-postcss';
+import { terser } from 'rollup-plugin-terser';
+import typescript2 from 'rollup-plugin-typescript2';
+import { camelCase } from 'lodash';
+import tempDir from 'temp-dir';
+import autoprefixer from 'autoprefixer';
+import NpmImport from 'less-plugin-npm-import';
+import svgr from '@svgr/rollup';
+import getBabelConfig from './getBabelConfig';
+import { getPkgPath, shouldTransform } from './es5ImcompatibleVersions';
+import { IBundleOptions } from './types';
+
+interface IGetRollupConfigOpts {
+ cwd: string;
+ rootPath: string;
+ entry: string;
+ type: ModuleFormat;
+ importLibToEs?: boolean;
+ bundleOpts: IBundleOptions;
+}
+
+interface IPkg {
+ dependencies?: Object;
+ peerDependencies?: Object;
+ name?: string;
+}
+
+export default function(opts: IGetRollupConfigOpts): RollupOptions[] {
+ const { type, entry, cwd, rootPath, importLibToEs, bundleOpts } = opts;
+ const {
+ umd,
+ esm,
+ cjs,
+ file,
+ target = 'browser',
+ extractCSS = false,
+ injectCSS = true,
+ cssModules: modules,
+ extraPostCSSPlugins = [],
+ extraBabelPresets = [],
+ extraBabelPlugins = [],
+ extraRollupPlugins = [],
+ autoprefixer: autoprefixerOpts,
+ include = /node_modules/,
+ runtimeHelpers: runtimeHelpersOpts,
+ replace: replaceOpts,
+ inject: injectOpts,
+ extraExternals = [],
+ externalsExclude = [],
+ nodeVersion,
+ typescriptOpts,
+ nodeResolveOpts = {},
+ disableTypeCheck,
+ lessInRollupMode = {},
+ sassInRollupMode = {},
+ } = bundleOpts;
+ const entryExt = extname(entry);
+ const name = file || basename(entry, entryExt);
+ const isTypeScript = entryExt === '.ts' || entryExt === '.tsx';
+ const extensions = ['.js', '.jsx', '.ts', '.tsx', '.es6', '.es', '.mjs'];
+
+ let pkg = {} as IPkg;
+ try {
+ pkg = require(join(cwd, 'package.json')); // eslint-disable-line
+ } catch (e) {}
+
+ // cjs 不给浏览器用,所以无需 runtimeHelpers
+ const runtimeHelpers = type === 'cjs' ? false : runtimeHelpersOpts;
+ const babelOpts = {
+ ...(getBabelConfig({
+ type,
+ target: type === 'esm' ? 'browser' : target,
+ // watch 模式下有几率走的 babel?原因未知。
+ // ref: https://github.com/umijs/father/issues/158
+ typescript: true,
+ runtimeHelpers,
+ nodeVersion,
+ }).opts),
+ // ref: https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers
+ babelHelpers: (runtimeHelpers ? 'runtime' : 'bundled') as RollupBabelInputPluginOptions['babelHelpers'],
+ // exclude: /\/node_modules\//,
+ filter: (filePath: string) => {
+ const rollupFilter = createFilter(null, /\/node_modules\//);
+ // 默认过滤 node_modules
+ if (!rollupFilter(filePath)) {
+ const pkgPath = getPkgPath(filePath);
+ return shouldTransform(pkgPath);
+ }
+ return true;
+ },
+ babelrc: false,
+ // ref: https://github.com/rollup/rollup-plugin-babel#usage
+ extensions,
+ };
+ if (importLibToEs && type === 'esm') {
+ babelOpts.plugins.push(require.resolve('../lib/importLibToEs'));
+ }
+ babelOpts.presets.push(...extraBabelPresets);
+ babelOpts.plugins.push(...extraBabelPlugins);
+
+ // rollup configs
+ const input = join(cwd, entry);
+ const format = type;
+
+ // ref: https://rollupjs.org/guide/en#external
+ // 潜在问题:引用包的子文件时会报 warning,比如 @babel/runtime/helpers/esm/createClass
+ // 解决方案:可以用 function 处理
+ const external = [
+ ...Object.keys(pkg.dependencies || {}),
+ ...Object.keys(pkg.peerDependencies || {}),
+ ...extraExternals,
+ ];
+ // umd 只要 external peerDependencies
+ const externalPeerDeps = [
+ ...Object.keys(pkg.peerDependencies || {}),
+ ...extraExternals,
+ ];
+
+ function getPkgNameByid(id) {
+ const splitted = id.split('/');
+ // @ 和 @tmp 是为了兼容 umi 的逻辑
+ if (id.charAt(0) === '@' && splitted[0] !== '@' && splitted[0] !== '@tmp') {
+ return splitted
+ .slice(0, 2)
+ .join('/');
+ } else {
+ return id.split('/')[0];
+ }
+ }
+
+ function testExternal(pkgs, excludes, id) {
+ if (excludes.includes(id)) {
+ return false;
+ }
+ return pkgs.includes(getPkgNameByid(id));
+ }
+
+ const terserOpts = {
+ compress: {
+ pure_getters: true,
+ unsafe: true,
+ unsafe_comps: true,
+ warnings: false,
+ },
+ };
+
+ // https://github.com/umijs/father/issues/164
+ function mergePlugins(defaultRollupPlugins: Array = [], extraRollupPlugins: Array = []) {
+ const pluginsMap: Record = Object.assign(
+ defaultRollupPlugins.reduce((r, plugin) => ({ ...r, [plugin.name]: plugin }), {}),
+ extraRollupPlugins.reduce((r, plugin) => ({ ...r, [plugin.name]: plugin }), {}),
+ );
+ return Object.values(pluginsMap);
+ }
+
+ function getPlugins(opts = {} as { minCSS: boolean; }) {
+ const { minCSS } = opts;
+ const defaultRollupPlugins = [
+ url(),
+ svgr(),
+ postcss({
+ extract: extractCSS,
+ inject: injectCSS,
+ modules,
+ // modules => all .less will convert into css modules
+ ...(modules ? { autoModules: false } : {}),
+ minimize: !!minCSS,
+ use: {
+ less: {
+ plugins: [new NpmImport({ prefix: '~' })],
+ javascriptEnabled: true,
+ ...lessInRollupMode
+ },
+ sass: {
+ ...sassInRollupMode,
+ },
+ stylus: false,
+ },
+ plugins: [autoprefixer({
+ // https://github.com/postcss/autoprefixer/issues/776
+ remove: false,
+ ...autoprefixerOpts,
+ }), ...extraPostCSSPlugins],
+ }),
+ ...(injectOpts ? [inject(injectOpts as RollupInjectOptions)] : []),
+ ...(replaceOpts && Object.keys(replaceOpts || {}).length ? [replace(replaceOpts)] : []),
+ nodeResolve({
+ mainFields: ['module', 'jsnext:main', 'main'],
+ extensions,
+ ...nodeResolveOpts,
+ }),
+ ...(isTypeScript
+ ? [
+ typescript2({
+ cwd,
+ // @see https://github.com/umijs/father/issues/61#issuecomment-544822774
+ clean: true,
+ cacheRoot: `${tempDir}/.rollup_plugin_typescript2_cache`,
+ // 支持往上找 tsconfig.json
+ // 比如 lerna 的场景不需要每个 package 有个 tsconfig.json
+ tsconfig: [join(cwd, 'tsconfig.json'), join(rootPath, 'tsconfig.json')].find(existsSync),
+ tsconfigDefaults: {
+ compilerOptions: {
+ // Generate declaration files by default
+ declaration: true,
+ },
+ },
+ tsconfigOverride: {
+ compilerOptions: {
+ // Support dynamic import
+ target: 'esnext',
+ },
+ },
+ check: !disableTypeCheck,
+ ...(typescriptOpts || {}),
+ }),
+ ]
+ : []),
+ babel(babelOpts),
+ json(),
+ ];
+ return mergePlugins(defaultRollupPlugins, extraRollupPlugins || []);
+ }
+
+ switch (type) {
+ case 'esm':
+ const output: Record = {
+ dir: join(cwd, `${esm && (esm as any).dir || 'dist'}`),
+ entryFileNames: `${(esm && (esm as any).file) || `${name}.esm`}.js`,
+ }
+
+ return [
+ {
+ input,
+ output: {
+ format,
+ ...output,
+ },
+ plugins: [...getPlugins(), ...(esm && (esm as any).minify ? [terser(terserOpts)] : [])],
+ external: testExternal.bind(null, external, externalsExclude),
+ },
+ ...(esm && (esm as any).mjs
+ ? [
+ {
+ input,
+ output: {
+ format,
+ file: join(cwd, `dist/${(esm && (esm as any).file) || `${name}`}.mjs`),
+ },
+ plugins: [
+ ...getPlugins(),
+ replace({
+ 'process.env.NODE_ENV': JSON.stringify('production'),
+ }),
+ terser(terserOpts),
+ ],
+ external: testExternal.bind(null, externalPeerDeps, externalsExclude),
+ },
+ ]
+ : []),
+ ];
+
+ case 'cjs':
+ return [
+ {
+ input,
+ output: {
+ format,
+ file: join(cwd, `dist/${(cjs && (cjs as any).file) || name}.js`),
+ },
+ plugins: [...getPlugins(), ...(cjs && (cjs as any).minify ? [terser(terserOpts)] : [])],
+ external: testExternal.bind(null, external, externalsExclude),
+ },
+ ];
+
+ case 'umd':
+ // Add umd related plugins
+ const extraUmdPlugins = [
+ commonjs({
+ include,
+ // namedExports options has been remove from https://github.com/rollup/plugins/pull/149
+ }),
+ ];
+
+ return [
+ {
+ input,
+ output: {
+ format,
+ sourcemap: umd && umd.sourcemap,
+ file: join(cwd, `dist/${(umd && umd.file) || `${name}.umd`}.js`),
+ globals: umd && umd.globals,
+ name: (umd && umd.name) || (pkg.name && camelCase(basename(pkg.name))),
+ },
+ plugins: [
+ ...extraUmdPlugins,
+ ...getPlugins(),
+ replace({
+ 'process.env.NODE_ENV': JSON.stringify('development'),
+ }),
+ ],
+ external: testExternal.bind(null, externalPeerDeps, externalsExclude),
+ },
+ ...(umd && umd.minFile === false
+ ? []
+ : [
+ {
+ input,
+ output: {
+ format,
+ sourcemap: umd && umd.sourcemap,
+ file: join(cwd, `dist/${(umd && umd.file) || `${name}.umd`}.min.js`),
+ globals: umd && umd.globals,
+ name: (umd && umd.name) || (pkg.name && camelCase(basename(pkg.name))),
+ },
+ plugins: [
+ ...extraUmdPlugins,
+ ...getPlugins({ minCSS: true }),
+ replace({
+ 'process.env.NODE_ENV': JSON.stringify('production'),
+ }),
+ terser(terserOpts),
+ ],
+ external: testExternal.bind(null, externalPeerDeps, externalsExclude),
+ },
+ ]),
+ ];
+
+ default:
+ throw new Error(`Unsupported type ${type}`);
+ }
+}
diff --git a/packages/core/build/src/getUserConfig.ts b/packages/core/build/src/getUserConfig.ts
new file mode 100755
index 000000000..02cb05f7f
--- /dev/null
+++ b/packages/core/build/src/getUserConfig.ts
@@ -0,0 +1,87 @@
+import AJV from 'ajv';
+import { existsSync } from 'fs';
+import { isAbsolute, relative, resolve } from 'path';
+import signale from 'signale';
+import slash from 'slash2';
+import schema from './schema';
+import { IBundleOptions } from './types';
+import { getExistFile } from './utils';
+
+function testDefault(obj) {
+ return obj.default || obj;
+}
+
+export const CONFIG_FILES = [
+ '.buildrc.js',
+ '.buildrc.jsx',
+ '.buildrc.ts',
+ '.buildrc.tsx',
+ '.fatherrc.js',
+ '.fatherrc.jsx',
+ '.fatherrc.ts',
+ '.fatherrc.tsx',
+ '.umirc.library.js',
+ '.umirc.library.jsx',
+ '.umirc.library.ts',
+ '.umirc.library.tsx',
+];
+const CLASSES = {
+ Function: Function,
+};
+const extendAjv = (ajv: AJV.Ajv) => {
+ ajv.addKeyword('instanceof', {
+ compile: function(schema: string) {
+ var Class = CLASSES[schema];
+ return function(data: any) {
+ return data instanceof Class;
+ };
+ },
+ });
+ return ajv;
+};
+export default function({ cwd, customPath }: { cwd: string; customPath?: string }): IBundleOptions {
+ let finalPath = '';
+
+ if (customPath) {
+ finalPath = isAbsolute(customPath) ? customPath : resolve(process.cwd(), customPath);
+ if (!existsSync(finalPath)) {
+ throw new Error(`can\'t found config file: ${customPath}`);
+ }
+ }
+
+ const configFile =
+ finalPath ||
+ getExistFile({
+ cwd,
+ files: CONFIG_FILES,
+ returnRelative: false,
+ });
+
+ if (configFile) {
+ if (configFile.includes('.umirc.library.')) {
+ signale.warn(`.umirc.library.js is deprecated, please use .fatherrc.js instead.`);
+ }
+
+ const userConfig = testDefault(require(configFile)); // eslint-disable-line
+ const userConfigs = Array.isArray(userConfig) ? userConfig : [userConfig];
+ userConfigs.forEach((userConfig) => {
+ const ajv = extendAjv(new AJV({ allErrors: true }));
+ const isValid = ajv.validate(schema, userConfig);
+ if (!isValid) {
+ const errors = ajv.errors.map(({ dataPath, message }, index) => {
+ return `${index + 1}. ${dataPath}${dataPath ? ' ' : ''}${message}`;
+ });
+ throw new Error(
+ `
+Invalid options in ${slash(relative(cwd, configFile))}
+
+${errors.join('\n')}
+`.trim()
+ );
+ }
+ });
+ return userConfig;
+ } else {
+ return {};
+ }
+}
diff --git a/packages/core/build/src/importLibToEs.js b/packages/core/build/src/importLibToEs.js
new file mode 100755
index 000000000..e7d278a64
--- /dev/null
+++ b/packages/core/build/src/importLibToEs.js
@@ -0,0 +1,26 @@
+import { join, dirname } from 'path';
+import fs from 'fs';
+
+const cwd = process.cwd();
+
+function replacePath(path) {
+ if (path.node.source && /\/lib\//.test(path.node.source.value)) {
+ const esModule = path.node.source.value.replace('/lib/', '/es/');
+ const esPath = dirname(join(cwd, `node_modules/${esModule}`));
+ if (fs.existsSync(esPath)) {
+ console.log(`[es build] replace ${path.node.source.value} with ${esModule}`);
+ path.node.source.value = esModule;
+ }
+ }
+}
+
+function replaceLib() {
+ return {
+ visitor: {
+ ImportDeclaration: replacePath,
+ ExportNamedDeclaration: replacePath,
+ },
+ };
+}
+
+export default replaceLib;
diff --git a/packages/core/build/src/index.ts b/packages/core/build/src/index.ts
new file mode 100755
index 000000000..1bff2b7bf
--- /dev/null
+++ b/packages/core/build/src/index.ts
@@ -0,0 +1,3 @@
+
+import build from './build';
+export default build;
diff --git a/packages/core/build/src/normalizeBundleOpts.test.ts b/packages/core/build/src/normalizeBundleOpts.test.ts
new file mode 100755
index 000000000..54bfdbe23
--- /dev/null
+++ b/packages/core/build/src/normalizeBundleOpts.test.ts
@@ -0,0 +1,53 @@
+import normalizeBundleOpts from './normalizeBundleOpts';
+
+test('normal', () => {
+ expect(
+ normalizeBundleOpts('a', {
+ umd: { name: 'foo' },
+ overridesByEntry: {
+ a: { umd: { name: 'bar' } },
+ },
+ }),
+ ).toEqual({
+ umd: { name: 'bar' },
+ });
+});
+
+test('ignore ./ prefix in entry', () => {
+ expect(
+ normalizeBundleOpts('./a', {
+ umd: { name: 'foo' },
+ overridesByEntry: {
+ a: { umd: { name: 'bar' } },
+ },
+ }),
+ ).toEqual({
+ umd: { name: 'bar' },
+ });
+});
+
+test('ignore ./ prefix in overridesByEntry', () => {
+ expect(
+ normalizeBundleOpts('a', {
+ umd: { name: 'foo' },
+ overridesByEntry: {
+ './a': { umd: { name: 'bar' } },
+ },
+ }),
+ ).toEqual({
+ umd: { name: 'bar' },
+ });
+});
+
+test('deep merge', () => {
+ expect(
+ normalizeBundleOpts('a', {
+ umd: { minFile: false, name: 'foo' },
+ overridesByEntry: {
+ a: { umd: { name: 'bar' } },
+ },
+ }),
+ ).toEqual({
+ umd: { minFile: false, name: 'bar' },
+ });
+});
diff --git a/packages/core/build/src/normalizeBundleOpts.ts b/packages/core/build/src/normalizeBundleOpts.ts
new file mode 100755
index 000000000..1767ff9ce
--- /dev/null
+++ b/packages/core/build/src/normalizeBundleOpts.ts
@@ -0,0 +1,24 @@
+import { cloneDeep, merge } from 'lodash';
+import { IBundleOptions } from './types';
+
+function stripDotSlashPrefix(path) {
+ return path.replace(/^\.\//, '');
+}
+
+export default function(entry: string, opts: IBundleOptions): IBundleOptions {
+ let clone = cloneDeep(opts);
+ const stripedEntry = stripDotSlashPrefix(entry);
+ if (clone.overridesByEntry) {
+ Object.keys(clone.overridesByEntry).forEach(key => {
+ const stripedKey = stripDotSlashPrefix(key);
+ if (stripedKey !== key) {
+ clone.overridesByEntry[stripedKey] = clone.overridesByEntry[key];
+ }
+ });
+ if (clone.overridesByEntry[stripedEntry]) {
+ clone = merge(clone, clone.overridesByEntry[stripedEntry]);
+ }
+ delete clone.overridesByEntry;
+ }
+ return clone;
+}
diff --git a/packages/core/build/src/randomColor.ts b/packages/core/build/src/randomColor.ts
new file mode 100755
index 000000000..bf44d2527
--- /dev/null
+++ b/packages/core/build/src/randomColor.ts
@@ -0,0 +1,34 @@
+import chalk from 'chalk';
+
+const colors = [
+ 'red',
+ 'green',
+ 'yellow',
+ 'blue',
+ 'magenta',
+ 'cyan',
+ 'gray',
+ 'redBright',
+ 'greenBright',
+ 'yellowBright',
+ 'blueBright',
+ 'magentaBright',
+ 'cyanBright',
+];
+
+let index = 0;
+const cache = {};
+
+export default function (pkg) {
+ if (!cache[pkg]) {
+ const color = colors[index];
+ let str = chalk[color].bold(pkg);
+ cache[pkg] = str;
+ if (index === colors.length - 1) {
+ index = 0;
+ } else {
+ index += 1;
+ }
+ }
+ return cache[pkg];
+}
diff --git a/packages/core/build/src/registerBabel.ts b/packages/core/build/src/registerBabel.ts
new file mode 100755
index 000000000..c7b52c3e8
--- /dev/null
+++ b/packages/core/build/src/registerBabel.ts
@@ -0,0 +1,23 @@
+import { join, isAbsolute } from 'path';
+import slash from 'slash2';
+import getBabelConfig from './getBabelConfig';
+
+interface IRegisterBabelOpts {
+ cwd: string;
+ only: string[];
+}
+
+export default function(opts: IRegisterBabelOpts) {
+ const { cwd, only } = opts;
+ const { opts: babelConfig } = getBabelConfig({
+ target: 'node',
+ typescript: true,
+ });
+ require('@babel/register')({
+ ...babelConfig,
+ extensions: ['.es6', '.es', '.jsx', '.js', '.mjs', '.ts', '.tsx'],
+ only: only.map((file) => slash(isAbsolute(file) ? file : join(cwd, file))),
+ babelrc: false,
+ cache: false,
+ });
+}
diff --git a/packages/core/build/src/rollup.ts b/packages/core/build/src/rollup.ts
new file mode 100755
index 000000000..e7b73098c
--- /dev/null
+++ b/packages/core/build/src/rollup.ts
@@ -0,0 +1,77 @@
+import { ModuleFormat, rollup, watch } from 'rollup';
+import signale from 'signale';
+import chalk from 'chalk';
+import getRollupConfig from './getRollupConfig';
+import { Dispose, IBundleOptions } from './types';
+import normalizeBundleOpts from './normalizeBundleOpts';
+
+interface IRollupOpts {
+ cwd: string;
+ rootPath?: string;
+ entry: string | string[];
+ type: ModuleFormat;
+ log: (string) => void;
+ bundleOpts: IBundleOptions;
+ watch?: boolean;
+ dispose?: Dispose[];
+ importLibToEs?: boolean;
+}
+
+async function build(entry: string, opts: IRollupOpts) {
+ const { cwd, rootPath, type, log, bundleOpts, importLibToEs, dispose } = opts;
+ const rollupConfigs = getRollupConfig({
+ cwd,
+ rootPath:rootPath || cwd,
+ type,
+ entry,
+ importLibToEs,
+ bundleOpts: normalizeBundleOpts(entry, bundleOpts),
+ });
+
+ for (const rollupConfig of rollupConfigs) {
+ if (opts.watch) {
+ const watcher = watch([
+ {
+ ...rollupConfig,
+ watch: {},
+ },
+ ]);
+ await (new Promise((resolve) => {
+ watcher.on('event', (event) => {
+ // 每次构建完成都会触发 BUNDLE_END 事件
+ // 当第一次构建完成或出错就 resolve
+ if (event.code === 'ERROR') {
+ signale.error(event.error);
+ resolve();
+ } else if (event.code === 'BUNDLE_END') {
+ log(`${chalk.green(`Build ${type} success`)} ${chalk.gray(`entry: ${entry}`)}`);
+ resolve();
+ }
+ });
+ }));
+ process.once('SIGINT', () => {
+ watcher.close();
+ });
+ dispose?.push(() => watcher.close());
+ } else {
+ const { output, ...input } = rollupConfig;
+ const bundle = await rollup(input); // eslint-disable-line
+ await bundle.write(output); // eslint-disable-line
+ log(`${chalk.green(`Build ${type} success`)} ${chalk.gray(`entry: ${entry}`)}`);
+ }
+ }
+}
+
+export default async function(opts: IRollupOpts) {
+ if (Array.isArray(opts.entry)) {
+ const { entry: entries } = opts;
+ for (const entry of entries) {
+ await build(entry, opts);
+ }
+ } else {
+ await build(opts.entry, opts);
+ }
+ if (opts.watch) {
+ opts.log(chalk.magentaBright(`Rebuild ${opts.type} since file changed 👀`));
+ }
+}
diff --git a/packages/core/build/src/schema.test.ts b/packages/core/build/src/schema.test.ts
new file mode 100755
index 000000000..effae7f20
--- /dev/null
+++ b/packages/core/build/src/schema.test.ts
@@ -0,0 +1,39 @@
+import AJV from 'ajv';
+import schema from './schema';
+
+const ajv = new AJV();
+
+const successValidates = {
+ entry: ['a', ['a'], ['a', 'b']],
+ file: ['a'],
+ esm: [false, true, { type: 'rollup' }, { type: 'babel' }, { file: 'a' }, { mjs: true }, {dir: 'a'}],
+ cjs: [false, true, { type: 'rollup' }, { type: 'babel' }, { file: 'a' }],
+ umd: [{ globals: {} }, { file: 'a' }, { name: 'a' }, { minFile: false }, { minFile: true }, { sourcemap: true }],
+ extraBabelPlugins: [[]],
+ extraBabelPresets: [[]],
+ extraPostCSSPlugins: [[]],
+ lessInRollupMode: [{}],
+ cssModules: [true, false, {}],
+ autoprefixer: [{}],
+ include: ['node_modules', /node_modules/],
+ nodeResolveOpts: [{}],
+ runtimeHelpers: [true, false],
+ target: ['node', 'browser'],
+ overridesByEntry: [{}],
+ doc: [{}],
+ typescriptOpts: [{}],
+ pkgs: [[]],
+ pkgFilter: [{}],
+};
+
+Object.keys(successValidates).forEach(key => {
+ test(key, () => {
+ successValidates[key].forEach(item => {
+ expect(
+ ajv.validate(schema, {
+ [key]: item,
+ }),
+ ).toEqual(true);
+ });
+ });
+});
diff --git a/packages/core/build/src/schema.ts b/packages/core/build/src/schema.ts
new file mode 100755
index 000000000..ec04a3bc0
--- /dev/null
+++ b/packages/core/build/src/schema.ts
@@ -0,0 +1,175 @@
+const noEmptyStr = { type: 'string', minLength: 1 };
+
+export default {
+ type: 'object',
+ additionalProperties: false,
+ properties: {
+ entry: {
+ oneOf: [noEmptyStr, { type: 'array', items: noEmptyStr }],
+ },
+ file: { type: 'string' },
+ esm: {
+ oneOf: [
+ noEmptyStr,
+ { type: 'boolean' },
+ {
+ type: 'object',
+ additionalProperties: false,
+ properties: {
+ type: {
+ type: 'string',
+ pattern: '^(rollup|babel)$',
+ },
+ file: noEmptyStr,
+ mjs: { type: 'boolean' },
+ minify: { type: 'boolean' },
+ importLibToEs: {
+ type: 'boolean',
+ },
+ dir: noEmptyStr
+ },
+ },
+ ],
+ },
+ cjs: {
+ oneOf: [
+ noEmptyStr,
+ { type: 'boolean' },
+ {
+ type: 'object',
+ additionalProperties: false,
+ properties: {
+ type: {
+ type: 'string',
+ pattern: '^(rollup|babel)$',
+ },
+ file: noEmptyStr,
+ minify: { type: 'boolean' },
+ lazy: { type: 'boolean' },
+ },
+ },
+ ],
+ },
+ umd: {
+ oneOf: [
+ { type: 'boolean' },
+ {
+ type: 'object',
+ additionalProperties: false,
+ properties: {
+ globals: { type: 'object' },
+ file: noEmptyStr,
+ name: noEmptyStr,
+ minFile: { type: 'boolean' },
+ sourcemap: {
+ oneOf: [
+ { type: 'boolean' },
+ { type: 'string', pattern: '^(inline|hidden)$', },
+ ]
+ },
+ },
+ },
+ ],
+ },
+ extraBabelPlugins: {
+ type: 'array',
+ },
+ extraBabelPresets: {
+ type: 'array',
+ },
+ extraPostCSSPlugins: {
+ type: 'array',
+ },
+ extraRollupPlugins: {
+ type: 'array',
+ },
+ extraExternals: {
+ type: 'array',
+ },
+ externalsExclude: {
+ type: 'array',
+ },
+ cssModules: {
+ oneOf: [{ type: 'boolean' }, { type: 'object' }],
+ },
+ extractCSS: {
+ type: 'boolean',
+ },
+ injectCSS: {
+ oneOf: [{ type: 'boolean' }, { instanceof: 'Function' }],
+ },
+ autoprefixer: {
+ type: 'object',
+ },
+ include: {
+ oneOf: [
+ { type: 'string' },
+ { type: 'object' },
+ { type: 'array' },
+ ]
+ },
+ runtimeHelpers: {
+ type: 'boolean',
+ },
+ overridesByEntry: {
+ type: 'object',
+ },
+ nodeResolveOpts: {
+ type: 'object',
+ },
+ target: noEmptyStr,
+ doc: {
+ type: 'object',
+ },
+ replace: {
+ type: 'object',
+ },
+ inject: {
+ type: 'object',
+ },
+ lessInRollupMode: {
+ type: 'object'
+ },
+ sassInRollupMode: {
+ type: 'object'
+ },
+ lessInBabelMode: {
+ oneOf: [
+ { type: 'boolean' },
+ { type: 'object' },
+ ],
+ },
+ browserFiles: {
+ type: 'array',
+ },
+ nodeFiles: {
+ type: 'array',
+ },
+ nodeVersion: {
+ type: 'number',
+ },
+ disableTypeCheck: {
+ type: 'boolean',
+ },
+ preCommit: {
+ type: 'object',
+ additionalProperties: false,
+ properties: {
+ eslint: { type: 'boolean' },
+ prettier: { type: 'boolean' },
+ },
+ },
+ typescriptOpts: {
+ type: 'object',
+ },
+ pkgs: {
+ type: 'array',
+ },
+ excludePkgs: {
+ type: 'array',
+ },
+ pkgFilter: {
+ type: 'object',
+ },
+ },
+};
diff --git a/packages/core/build/src/types.d.ts b/packages/core/build/src/types.d.ts
new file mode 100755
index 000000000..f4060ff2b
--- /dev/null
+++ b/packages/core/build/src/types.d.ts
@@ -0,0 +1,118 @@
+export type BundleType = 'rollup' | 'babel';
+
+interface IBundleTypeOutput {
+ type: BundleType;
+ file?: string;
+}
+
+export interface ICjs extends IBundleTypeOutput {
+ minify?: boolean;
+ lazy?: boolean;
+}
+
+interface IEsm extends IBundleTypeOutput {
+ mjs?: boolean;
+ minify?: boolean;
+ importLibToEs?: boolean;
+}
+
+interface IStringObject {
+ [prop: string]: string;
+}
+
+interface IUmd {
+ globals?: IStringObject;
+ name?: string;
+ minFile?: boolean;
+ file?: string;
+ sourcemap?: boolean;
+}
+
+export interface IBundleOptions {
+ entry?: string | string[];
+ file?: string;
+ esm?: BundleType | IEsm | false;
+ cjs?: BundleType | ICjs | false;
+ umd?: IUmd | false;
+ extraBabelPlugins?: any[];
+ extraBabelPresets?: any[];
+ extraPostCSSPlugins?: any[];
+ extraRollupPlugins?: any[];
+ extraExternals?: string[];
+ externalsExclude?: string[];
+ cssModules?: boolean | Object;
+ extractCSS?: boolean;
+ injectCSS?: boolean | ((varname: string, filename: string) => string);
+ inject?: Object;
+ autoprefixer?: Object;
+ include?: string | RegExp;
+ runtimeHelpers?: boolean;
+ target?: 'node' | 'browser';
+ overridesByEntry?: {
+ [entry: string]: any;
+ };
+ replace?: {
+ [value: string]: any;
+ };
+ browserFiles?: {
+ [value: string]: any;
+ };
+ nodeFiles?: {
+ [value: string]: any;
+ };
+ nodeVersion?: number;
+ disableTypeCheck?: boolean;
+ preCommit?: {
+ eslint?: boolean;
+ prettier?: boolean;
+ };
+ lessInBabelMode?:
+ | boolean
+ | {
+ paths?: any[];
+ plugins?: any[];
+ };
+ typescriptOpts?: {
+ [value: string]: any;
+ };
+ nodeResolveOpts?: {
+ [value: string]: any;
+ };
+ lessInRollupMode?: {
+ [opt: string]: any;
+ };
+ sassInRollupMode?: {
+ [opt: string]: any;
+ };
+ pkgs?: string[];
+ excludePkgs?: string[];
+ /** 处理 lerna 包 */
+ pkgFilter?: {
+ /** 指定包含的包 */
+ include?: string[];
+ /** 指定排除的包 */
+ exclude?: string[];
+ /**
+ * 跳过私有的包 package.json private
+ * @default false
+ * */
+ skipPrivate?: boolean;
+ };
+ config?: string;
+}
+
+export interface IOpts {
+ cwd: string;
+ watch?: boolean;
+ /**
+ * 构建时清空outputDir
+ * @default true
+ * */
+ clean?: boolean;
+ buildArgs?: IBundleOptions;
+ rootConfig?: IBundleOptions;
+ rootPath?: string;
+ packages?: string[];
+}
+
+export type Dispose = () => void;
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core1/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core1/package.json
new file mode 100755
index 000000000..00e2e0d0e
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core1/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "core1",
+ "version": "1.0.0",
+ "dependencies": {
+ "foo": "1.0.0"
+ }
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core1/src/index.js b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core1/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core1/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core2/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core2/package.json
new file mode 100755
index 000000000..203f31261
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core2/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "core2",
+ "private": true,
+ "version": "1.0.0"
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core2/src/index.js b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core2/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/core/core2/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/lerna.json b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/lerna.json
new file mode 100755
index 000000000..d780dfc5f
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/lerna.json
@@ -0,0 +1,6 @@
+{
+ "packages": [
+ "core/*",
+ "packages/*"
+ ]
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/package.json
new file mode 100755
index 000000000..cb5e0b6fe
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "default-packages",
+ "private": true
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/bar/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/bar/package.json
new file mode 100755
index 000000000..06a8b8dcc
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/bar/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "bar",
+ "version": "1.0.0"
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/bar/src/index.js b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/foo/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/foo/package.json
new file mode 100755
index 000000000..215274b02
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/foo/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "foo",
+ "version": "1.0.0",
+ "dependencies": {
+ "bar": "1.0.0"
+ }
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/foo/src/index.js b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/customize/packages/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/default/lerna.json b/packages/core/build/src/utils/getLernaPackages/fixtures/default/lerna.json
new file mode 100755
index 000000000..0967ef424
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/default/lerna.json
@@ -0,0 +1 @@
+{}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/default/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/default/package.json
new file mode 100755
index 000000000..cb5e0b6fe
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/default/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "default-packages",
+ "private": true
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/bar/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/bar/package.json
new file mode 100755
index 000000000..06a8b8dcc
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/bar/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "bar",
+ "version": "1.0.0"
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/bar/src/index.js b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/bar/src/index.js
new file mode 100755
index 000000000..9638d025d
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/bar/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('bar');
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/foo/package.json b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/foo/package.json
new file mode 100755
index 000000000..215274b02
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/foo/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "foo",
+ "version": "1.0.0",
+ "dependencies": {
+ "bar": "1.0.0"
+ }
+}
diff --git a/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/foo/src/index.js b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/foo/src/index.js
new file mode 100755
index 000000000..695557eab
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/fixtures/default/packages/foo/src/index.js
@@ -0,0 +1,2 @@
+
+console.log('foo');
diff --git a/packages/core/build/src/utils/getLernaPackages/index.test.ts b/packages/core/build/src/utils/getLernaPackages/index.test.ts
new file mode 100755
index 000000000..b59740702
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/index.test.ts
@@ -0,0 +1,83 @@
+import path from 'path';
+import fs from 'fs-extra';
+import { getLernaPackages } from './';
+
+export const FIXTURES_DIR = path.resolve(__dirname, 'fixtures');
+
+export function getDirs() {
+ return fs
+ .readdirSync(FIXTURES_DIR)
+ .filter(fixturePath =>
+ fs.statSync(path.resolve(FIXTURES_DIR, fixturePath)).isDirectory(),
+ );
+}
+
+export function fixture(...args: string[]) {
+ return path.join(FIXTURES_DIR, ...args)
+}
+
+describe('default', () => {
+ const fixturePath = fixture('default');
+
+ it('获取所有的包', async () => {
+ expect.assertions(1);
+
+ const pkgs = await getLernaPackages(fixturePath);
+
+ const pkgNames = ['bar', 'foo'];
+
+ expect(pkgNames).toEqual(pkgs.map(item => item.name));
+ })
+});
+
+describe('customize', () => {
+ const fixturePath = fixture('customize');
+
+ it('获取所有的包', async () => {
+ expect.assertions(1);
+
+ const pkgs = await getLernaPackages(fixturePath, {});
+
+ const pkgNames = ['core2', 'bar', 'foo', 'core1'];
+
+ expect(pkgNames).toEqual(pkgs.map(item => item.name));
+ });
+
+ it('过滤私有的包', async () => {
+ expect.assertions(1);
+
+ const pkgs = await getLernaPackages(fixturePath, {
+ skipPrivate: true,
+ });
+
+ const pkgNames = ['bar', 'foo', 'core1'];
+
+ expect(pkgNames).toEqual(pkgs.map(item => item.name));
+ });
+
+ it('设置包含部分包', async () => {
+ expect.assertions(1);
+
+ const pkgs = await getLernaPackages(fixturePath, {
+ include: [
+ 'core*'
+ ]
+ });
+ const pkgNames = ['core1', 'core2'];
+
+ expect(pkgNames).toEqual(pkgs.map(item => item.name));
+ })
+
+ it('设置包含部分包', async () => {
+ expect.assertions(1);
+
+ const pkgs = await getLernaPackages(fixturePath, {
+ exclude: [
+ 'core1'
+ ]
+ });
+ const pkgNames = ['core2', 'bar', 'foo'];
+
+ expect(pkgNames).toEqual(pkgs.map(item => item.name));
+ })
+});
diff --git a/packages/core/build/src/utils/getLernaPackages/index.ts b/packages/core/build/src/utils/getLernaPackages/index.ts
new file mode 100755
index 000000000..f9d45da48
--- /dev/null
+++ b/packages/core/build/src/utils/getLernaPackages/index.ts
@@ -0,0 +1,57 @@
+import { getPackagesSync } from '@lerna/project';
+import { QueryGraph } from '@lerna/query-graph';
+import { filterPackages } from '@lerna/filter-packages';
+
+export interface Options {
+ /** 指定包含的包 */
+ include?: string[];
+ /** 指定排除的包 */
+ exclude?: string[];
+ /**
+ * 跳过私有的包
+ * @default false
+ * */
+ skipPrivate?: boolean;
+}
+
+/**
+ * 获取lerna项目包集合
+ * @param cwd
+ */
+export async function getLernaPackages(cwd: string, ops: Options = {}): Promise {
+ const {
+ include = [],
+ exclude = [],
+ skipPrivate = false,
+ } = ops;
+
+ const allPkgs = getPackagesSync(cwd) ?? [];
+
+ const pkgs = filterPackages(allPkgs, include, exclude, !skipPrivate, true);
+
+ return await getStreamPackages(pkgs);
+}
+
+export function getStreamPackages(pkgs: any[]): Promise {
+ const graph = new QueryGraph(pkgs, 'allDependencies', true);
+
+ return new Promise((resolve) => {
+ const returnValues: any[] = [];
+
+ const queueNextAvailablePackages = () =>
+ graph.getAvailablePackages()
+ // @ts-ignore
+ .forEach(({ pkg, name }) => {
+ graph.markAsTaken(name);
+
+ Promise.resolve(pkg)
+ .then((value) => returnValues.push(value))
+ .then(() => graph.markAsDone(pkg))
+ .then(() => queueNextAvailablePackages())
+ });
+
+ queueNextAvailablePackages();
+
+ setTimeout(() => { resolve(returnValues); }, 0);
+ });
+}
diff --git a/packages/core/build/src/utils/index.ts b/packages/core/build/src/utils/index.ts
new file mode 100755
index 000000000..4784d57c6
--- /dev/null
+++ b/packages/core/build/src/utils/index.ts
@@ -0,0 +1,13 @@
+import { existsSync } from 'fs';
+import { join } from 'path';
+
+export function getExistFile({ cwd, files, returnRelative }) {
+ for (const file of files) {
+ const absFilePath = join(cwd, file);
+ if (existsSync(absFilePath)) {
+ return returnRelative ? file : absFilePath;
+ }
+ }
+}
+
+export { getLernaPackages } from './getLernaPackages';
diff --git a/packages/core/build/template/tsconfig.json b/packages/core/build/template/tsconfig.json
new file mode 100755
index 000000000..9a8969019
--- /dev/null
+++ b/packages/core/build/template/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "allowSyntheticDefaultImports": true,
+ "declaration": true,
+ "module": "esnext",
+ "target": "esnext",
+ "moduleResolution": "node",
+ "jsx": "react"
+ },
+ "include": ["./src", "./typings/"],
+ "typings": "./typings/index.d.ts",
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "tslint:latest",
+ "tslint-config-prettier"
+ ]
+}
diff --git a/packages/core/cli/.npmignore b/packages/core/cli/.npmignore
new file mode 100644
index 000000000..eb03e3e1e
--- /dev/null
+++ b/packages/core/cli/.npmignore
@@ -0,0 +1,2 @@
+node_modules
+*.log
diff --git a/packages/core/cli/bin/index.js b/packages/core/cli/bin/index.js
new file mode 100755
index 000000000..830f49b15
--- /dev/null
+++ b/packages/core/cli/bin/index.js
@@ -0,0 +1,30 @@
+#!/usr/bin/env node
+
+const dotenv = require('dotenv');
+const { resolve } = require('path');
+
+const env = {
+ APP_PACKAGE_ROOT: 'app',
+ APP_ENV: 'development',
+ APP_KEY: 'test-jwt-secret',
+ APP_PORT: 13000,
+ API_BASE_PATH: '/api/',
+ DB_DIALECT: 'sqlite',
+ DB_STORAGE: 'storage/db/nocobase.sqlite',
+ DEFAULT_STORAGE_TYPE: 'local',
+ LOCAL_STORAGE_DEST: 'storage/uploads',
+};
+
+dotenv.config({
+ path: resolve(process.cwd(), process.env.APP_ENV_PATH || '.env'),
+});
+
+for (const key in env) {
+ if (!process.env[key]) {
+ process.env[key] = env[key];
+ }
+}
+
+const cli = require('../src/cli');
+
+cli.parse(process.argv);
diff --git a/packages/core/cli/package.json b/packages/core/cli/package.json
new file mode 100644
index 000000000..afe0d4212
--- /dev/null
+++ b/packages/core/cli/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@nocobase/cli",
+ "version": "0.7.0-alpha.55",
+ "description": "",
+ "license": "Apache-2.0",
+ "licenses": [
+ {
+ "type": "Apache-2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0"
+ }
+ ],
+ "main": "./src/index.js",
+ "bin": {
+ "nocobase": "./bin/index.js"
+ },
+ "dependencies": {
+ "chalk": "^4.1.1",
+ "commander": "^9.2.0",
+ "dotenv": "^10.0.0",
+ "execa": "^5.1.1",
+ "pm2": "^5.2.0",
+ "portfinder": "^1.0.28",
+ "serve": "^13.0.2"
+ },
+ "devDependencies": {
+ "@nocobase/devtools": "0.7.0-alpha.55"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/nocobase/nocobase.git",
+ "directory": "packages/core/cli"
+ },
+ "gitHead": "a00b45a2686695c5f4824d074ac5e1aff210793a"
+}
diff --git a/packages/core/cli/src/cli.js b/packages/core/cli/src/cli.js
new file mode 100644
index 000000000..9662194af
--- /dev/null
+++ b/packages/core/cli/src/cli.js
@@ -0,0 +1,10 @@
+const { Command } = require('commander');
+const commands = require('./commands');
+
+const cli = new Command();
+
+cli.version(require('../package.json').version);
+
+commands(cli);
+
+module.exports = cli;
diff --git a/packages/core/cli/src/commands/build.js b/packages/core/cli/src/commands/build.js
new file mode 100644
index 000000000..eb9d0da1c
--- /dev/null
+++ b/packages/core/cli/src/commands/build.js
@@ -0,0 +1,38 @@
+const { resolve } = require('path');
+const { Command } = require('commander');
+const { run, nodeCheck, isPackageValid, promptForTs } = require('../util');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+ const clientPackage = `${APP_PACKAGE_ROOT}/client`;
+ cli
+ .command('build')
+ .allowUnknownOption()
+ .argument('[packages...]')
+ .option('-c, --compile', 'compile the @nocobase/build package')
+ .action(async (pkgs, options) => {
+ promptForTs();
+ nodeCheck();
+ if (isPackageValid('umi-tools/cli')) {
+ if (options.compile || !isPackageValid('@nocobase/build/lib')) {
+ await run('umi-tools', ['build'], {
+ cwd: resolve(process.cwd(), 'packages/core/build'),
+ });
+ }
+ }
+ if (!pkgs.length || !pkgs.includes(clientPackage) || (pkgs.includes(clientPackage) && pkgs.length > 1)) {
+ await run('nocobase-build', process.argv.slice(3));
+ }
+ if (!pkgs.length || pkgs.includes(clientPackage)) {
+ await run('umi', ['build'], {
+ env: {
+ APP_ROOT: `packages/${APP_PACKAGE_ROOT}/client`,
+ },
+ });
+ }
+ });
+};
diff --git a/packages/core/cli/src/commands/clean.js b/packages/core/cli/src/commands/clean.js
new file mode 100644
index 000000000..9d0de95d5
--- /dev/null
+++ b/packages/core/cli/src/commands/clean.js
@@ -0,0 +1,19 @@
+const chalk = require('chalk');
+const { Command } = require('commander');
+const { run, isDev } = require('../util');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ cli
+ .command('clean')
+ .allowUnknownOption()
+ .action(() => {
+ if (!isDev()) {
+ return;
+ }
+ run('rimraf', ['-rf', 'packages/*/*/{lib,esm,es,dist}']);
+ });
+};
diff --git a/packages/core/cli/src/commands/dev.js b/packages/core/cli/src/commands/dev.js
new file mode 100644
index 000000000..12dc74876
--- /dev/null
+++ b/packages/core/cli/src/commands/dev.js
@@ -0,0 +1,77 @@
+const chalk = require('chalk');
+const { Command } = require('commander');
+const { runInstall, run, postCheck, nodeCheck, promptForTs } = require('../util');
+const { getPortPromise } = require('portfinder');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+ cli
+ .command('dev')
+ .option('-p, --port [port]')
+ .option('--client')
+ .option('--server')
+ .allowUnknownOption()
+ .action(async (opts) => {
+ promptForTs();
+ if (process.argv.includes('-h') || process.argv.includes('--help')) {
+ run('ts-node', [
+ '-P',
+ './tsconfig.server.json',
+ '-r',
+ 'tsconfig-paths/register',
+ `./packages/${APP_PACKAGE_ROOT}/server/src/index.ts`,
+ ...process.argv.slice(2),
+ ]);
+ return;
+ }
+ const { port, client, server } = opts;
+ if (port) {
+ process.env.APP_PORT = opts.port;
+ }
+ const { APP_PORT } = process.env;
+ let clientPost = APP_PORT;
+ let serverPost;
+ nodeCheck();
+ await postCheck(opts);
+ if (server) {
+ serverPost = APP_PORT;
+ } else if (!server && !client) {
+ serverPost = await getPortPromise({
+ port: 1 * clientPost + 1,
+ });
+ }
+ await runInstall();
+ if (server || !client) {
+ console.log('starting server', serverPost);
+ const argv = [
+ '-P',
+ './tsconfig.server.json',
+ '-r',
+ 'tsconfig-paths/register',
+ `./packages/${APP_PACKAGE_ROOT}/server/src/index.ts`,
+ 'start',
+ ...process.argv.slice(3),
+ `--port=${serverPost}`,
+ ];
+ run('ts-node-dev', argv, {
+ env: {
+ APP_PORT: serverPost,
+ },
+ });
+ }
+ if (client || !server) {
+ console.log('starting client', 1 * clientPost);
+ run('umi', ['dev'], {
+ env: {
+ PORT: clientPost,
+ APP_ROOT: `packages/${APP_PACKAGE_ROOT}/client`,
+ PROXY_TARGET_URL: serverPost ? `http://127.0.0.1:${serverPost}` : undefined,
+ },
+ });
+ }
+ });
+};
diff --git a/packages/core/cli/src/commands/doc.js b/packages/core/cli/src/commands/doc.js
new file mode 100644
index 000000000..3834b0a36
--- /dev/null
+++ b/packages/core/cli/src/commands/doc.js
@@ -0,0 +1,37 @@
+const { Command } = require('commander');
+const { resolve, isAbsolute } = require('path');
+const { run, isDev } = require('../util');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ cli
+ .command('doc')
+ .option('--lang [lang]')
+ .allowUnknownOption()
+ .action((options) => {
+ if (!isDev()) {
+ return;
+ }
+ process.env.DOC_LANG = options.lang || 'en-US';
+ const docThemePath = process.env.DOC_THEME_PATH;
+ if (!docThemePath) {
+ process.env.DUMI_THEME = resolve(process.cwd(), 'packages/core/dumi-theme-nocobase/src');
+ } else {
+ process.env.DUMI_THEME = isAbsolute(docThemePath) ? docThemePath : resolve(process.cwd(), docThemePath);
+ }
+ const index = process.argv.indexOf(`--lang=${options.lang}`);
+ if (index > 0) {
+ process.argv.splice(index, 1);
+ }
+ const argv = process.argv.slice(3);
+ const argument = argv.shift() || 'dev';
+ if (argument === 'serve') {
+ run('serve', [`${resolve(process.cwd(), 'docs/dist', process.env.DOC_LANG)}`, ...argv]);
+ } else {
+ run('dumi', [argument, ...argv]);
+ }
+ });
+};
diff --git a/packages/core/cli/src/commands/global.js b/packages/core/cli/src/commands/global.js
new file mode 100644
index 000000000..5cc6e6523
--- /dev/null
+++ b/packages/core/cli/src/commands/global.js
@@ -0,0 +1,30 @@
+const { Command } = require('commander');
+const { run, isDev, promptForTs } = require('../util');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+ cli
+ .allowUnknownOption()
+ .option('-h, --help')
+ .option('--ts-node-dev')
+ .action((options) => {
+ const { tsNodeDev } = options;
+ if (isDev()) {
+ promptForTs();
+ run(tsNodeDev ? 'ts-node-dev' : 'ts-node', [
+ '-P',
+ './tsconfig.server.json',
+ '-r',
+ 'tsconfig-paths/register',
+ `./packages/${APP_PACKAGE_ROOT}/server/src/index.ts`,
+ ...process.argv.slice(2),
+ ]);
+ } else {
+ run('node', [`./packages/${APP_PACKAGE_ROOT}/server/lib/index.js`, ...process.argv.slice(2)]);
+ }
+ });
+};
diff --git a/packages/core/cli/src/commands/index.js b/packages/core/cli/src/commands/index.js
new file mode 100644
index 000000000..0c8a677c9
--- /dev/null
+++ b/packages/core/cli/src/commands/index.js
@@ -0,0 +1,18 @@
+const { Command } = require('commander');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ require('./global')(cli);
+ require('./build')(cli);
+ require('./dev')(cli);
+ require('./start')(cli);
+ require('./test')(cli);
+ require('./clean')(cli);
+ require('./doc')(cli);
+ require('./umi')(cli);
+ require('./upgrade')(cli);
+ require('./postinstall')(cli);
+}
diff --git a/packages/core/cli/src/commands/postinstall.js b/packages/core/cli/src/commands/postinstall.js
new file mode 100644
index 000000000..22198b06a
--- /dev/null
+++ b/packages/core/cli/src/commands/postinstall.js
@@ -0,0 +1,31 @@
+const { Command } = require('commander');
+const { run, isDev } = require('../util');
+const { resolve } = require('path');
+const { existsSync } = require('fs');
+const { readFile, writeFile } = require('fs').promises;
+
+/**
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+ cli
+ .command('postinstall')
+ .allowUnknownOption()
+ .action(async () => {
+ if (!isDev()) {
+ return;
+ }
+ const cwd = process.cwd();
+ if (!existsSync(resolve(cwd, '.env')) && existsSync(resolve(cwd, '.env.example'))) {
+ const content = await readFile(resolve(cwd, '.env.example'), 'utf-8');
+ await writeFile(resolve(cwd, '.env'), content, 'utf-8');
+ }
+ run('umi', ['generate', 'tmp'], {
+ stdio: 'pipe',
+ env: {
+ APP_ROOT: `packages/${APP_PACKAGE_ROOT}/client`,
+ },
+ });
+ });
+};
diff --git a/packages/core/cli/src/commands/start.js b/packages/core/cli/src/commands/start.js
new file mode 100644
index 000000000..8e77e16b4
--- /dev/null
+++ b/packages/core/cli/src/commands/start.js
@@ -0,0 +1,44 @@
+const { Command } = require('commander');
+const { isDev, run, postCheck, runInstall, promptForTs } = require('../util');
+const { existsSync } = require('fs');
+const { resolve } = require('path');
+const chalk = require('chalk');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+ cli
+ .command('start')
+ .option('-p, --port [port]')
+ .allowUnknownOption()
+ .action(async (opts) => {
+ if (opts.port) {
+ process.env.APP_PORT = opts.port;
+ }
+ if (process.argv.includes('-h') || process.argv.includes('--help')) {
+ promptForTs();
+ run('ts-node', [
+ '-P',
+ './tsconfig.server.json',
+ '-r',
+ 'tsconfig-paths/register',
+ `./packages/${APP_PACKAGE_ROOT}/server/src/index.ts`,
+ ...process.argv.slice(2),
+ ]);
+ return;
+ }
+ if (!existsSync(resolve(process.cwd(), `./packages/${APP_PACKAGE_ROOT}/server/lib/index.js`))) {
+ console.log('The code is not compiled, please execute it first');
+ console.log(chalk.yellow('$ yarn build'));
+ console.log('If you want to run in development mode, please execute');
+ console.log(chalk.yellow('$ yarn dev'));
+ return;
+ }
+ await postCheck(opts);
+ await run('node', [`./packages/${APP_PACKAGE_ROOT}/server/lib/index.js`, 'install', '-s']);
+ run('pm2-runtime', ['start', `packages/${APP_PACKAGE_ROOT}/server/lib/index.js`, '--', ...process.argv.slice(2)]);
+ });
+};
diff --git a/packages/core/cli/src/commands/test.js b/packages/core/cli/src/commands/test.js
new file mode 100644
index 000000000..7934b1ba4
--- /dev/null
+++ b/packages/core/cli/src/commands/test.js
@@ -0,0 +1,22 @@
+const { Command } = require('commander');
+const { nodeCheck, runAppCommand, promptForTs } = require('../util');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ cli
+ .command('test')
+ .option('-c, --db-clean')
+ .allowUnknownOption()
+ .action(async (options) => {
+ nodeCheck();
+ if (options.dbClean) {
+ promptForTs();
+ await runAppCommand('db:clean', '-y');
+ }
+ process.argv.splice(2, 1, '-i');
+ require('jest-cli/bin/jest');
+ });
+};
diff --git a/packages/core/cli/src/commands/umi.js b/packages/core/cli/src/commands/umi.js
new file mode 100644
index 000000000..c87f934c1
--- /dev/null
+++ b/packages/core/cli/src/commands/umi.js
@@ -0,0 +1,24 @@
+const chalk = require('chalk');
+const { Command } = require('commander');
+const { run, isDev } = require('../util');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+ cli
+ .command('umi')
+ .allowUnknownOption()
+ .action(() => {
+ if (!isDev()) {
+ return;
+ }
+ run('umi', process.argv.slice(3), {
+ env: {
+ APP_ROOT: `packages/${APP_PACKAGE_ROOT}/client`,
+ },
+ });
+ });
+};
diff --git a/packages/core/cli/src/commands/upgrade.js b/packages/core/cli/src/commands/upgrade.js
new file mode 100644
index 000000000..2a68346ba
--- /dev/null
+++ b/packages/core/cli/src/commands/upgrade.js
@@ -0,0 +1,41 @@
+const chalk = require('chalk');
+const { Command } = require('commander');
+const { resolve } = require('path');
+const { getVersion, run, promptForTs, runAppCommand, hasCorePackages, updateJsonFile, hasTsNode } = require('../util');
+
+/**
+ *
+ * @param {Command} cli
+ */
+module.exports = (cli) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+ cli
+ .command('upgrade')
+ .allowUnknownOption()
+ .action(async () => {
+ promptForTs();
+ const version = await getVersion();
+ if (hasCorePackages()) {
+ await run('yarn', ['install']);
+ await runAppCommand('upgrade');
+ return;
+ }
+ if (!hasTsNode()) {
+ return;
+ }
+ await run('yarn', ['add', '@nocobase/cli', '@nocobase/devtools', '-W']);
+ const clientPackage = resolve(process.cwd(), `packages/${APP_PACKAGE_ROOT}/client/package.json`);
+ const serverPackage = resolve(process.cwd(), `packages/${APP_PACKAGE_ROOT}/server/package.json`);
+ await updateJsonFile(clientPackage, (data) => {
+ data.devDependencies['@nocobase/client'] = version;
+ return data;
+ });
+ await updateJsonFile(serverPackage, (data) => {
+ data.dependencies['@nocobase/preset-nocobase'] = version;
+ return data;
+ });
+ await run('yarn', ['install']);
+ await run('nocobase', ['build']);
+ await runAppCommand('upgrade');
+ });
+};
diff --git a/packages/core/cli/src/index.js b/packages/core/cli/src/index.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/core/cli/src/util.js b/packages/core/cli/src/util.js
new file mode 100644
index 000000000..21b5a7880
--- /dev/null
+++ b/packages/core/cli/src/util.js
@@ -0,0 +1,143 @@
+const net = require('net');
+const chalk = require('chalk');
+const execa = require('execa');
+const { resolve } = require('path');
+const { readFile, writeFile } = require('fs').promises;
+const { existsSync } = require('fs');
+
+exports.isPackageValid = (package) => {
+ try {
+ require.resolve(package);
+ return true;
+ } catch (error) {
+ return false;
+ }
+};
+
+exports.hasCorePackages = () => {
+ const coreDir = resolve(process.cwd(), 'packages/core/build');
+ return existsSync(coreDir);
+};
+
+exports.hasTsNode = () => {
+ return exports.isPackageValid('ts-node/dist/bin');
+};
+
+exports.isDev = function isDev() {
+ if (process.env.APP_ENV === 'production') {
+ return false;
+ }
+ return exports.hasTsNode();
+};
+
+exports.nodeCheck = () => {
+ if (!exports.hasTsNode()) {
+ console.log('Please install all dependencies');
+ console.log(chalk.yellow('$ yarn install'));
+ process.exit(0);
+ }
+};
+
+exports.run = (command, argv, options = {}) => {
+ return execa(command, argv, {
+ shell: true,
+ stdio: 'inherit',
+ ...options,
+ env: {
+ ...process.env,
+ ...options.env,
+ },
+ });
+};
+
+exports.isPortReachable = async (port, { timeout = 1000, host } = {}) => {
+ const promise = new Promise((resolve, reject) => {
+ const socket = new net.Socket();
+
+ const onError = () => {
+ socket.destroy();
+ reject();
+ };
+
+ socket.setTimeout(timeout);
+ socket.once('error', onError);
+ socket.once('timeout', onError);
+
+ socket.connect(port, host, () => {
+ socket.end();
+ resolve();
+ });
+ });
+
+ try {
+ await promise;
+ return true;
+ } catch (_) {
+ return false;
+ }
+};
+
+exports.postCheck = async (opts) => {
+ const port = opts.port || process.env.APP_PORT;
+ const result = await exports.isPortReachable(port);
+ if (result) {
+ console.error(chalk.red(`post already in use ${port}`));
+ process.exit(1);
+ }
+};
+
+exports.runInstall = async () => {
+ const { APP_PACKAGE_ROOT } = process.env;
+
+ if (exports.isDev()) {
+ const argv = [
+ '-P',
+ './tsconfig.server.json',
+ '-r',
+ 'tsconfig-paths/register',
+ `./packages/${APP_PACKAGE_ROOT}/server/src/index.ts`,
+ 'install',
+ '-s',
+ ];
+ await exports.run('ts-node', argv);
+ } else {
+ const argv = [`./packages/${APP_PACKAGE_ROOT}/server/lib/index.js`, 'install', '-s'];
+ await exports.run('node', argv);
+ }
+};
+
+exports.runAppCommand = async (command, args = []) => {
+ const { APP_PACKAGE_ROOT } = process.env;
+
+ if (exports.isDev()) {
+ const argv = [
+ '-P',
+ './tsconfig.server.json',
+ '-r',
+ 'tsconfig-paths/register',
+ `./packages/${APP_PACKAGE_ROOT}/server/src/index.ts`,
+ command,
+ ...args,
+ ];
+ await exports.run('ts-node', argv);
+ } else {
+ const argv = [`./packages/${APP_PACKAGE_ROOT}/server/lib/index.js`, command, ...args];
+ await exports.run('node', argv);
+ }
+};
+
+exports.promptForTs = () => {
+ console.log(chalk.green('WAIT: ') + 'TypeScript compiling...');
+};
+
+exports.updateJsonFile = async (target, fn) => {
+ const content = await readFile(target, 'utf-8');
+ const json = JSON.parse(content);
+ await writeFile(target, JSON.stringify(fn(json), null, 2), 'utf-8');
+};
+
+exports.getVersion = async () => {
+ const { stdout } = await execa('npm', ['v', '@nocobase/app-server', 'versions']);
+ const versions = new Function(`return ${stdout}`)();
+ return versions[versions.length - 1];
+};
diff --git a/packages/core/client/.buildrc.ts b/packages/core/client/.buildrc.ts
new file mode 100644
index 000000000..f0c3466d6
--- /dev/null
+++ b/packages/core/client/.buildrc.ts
@@ -0,0 +1,5 @@
+export default {
+ target: 'browser',
+ cjs: 'babel',
+ esm: 'babel',
+};
diff --git a/packages/core/client/package.json b/packages/core/client/package.json
index 4288640db..a8fb43a77 100644
--- a/packages/core/client/package.json
+++ b/packages/core/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@nocobase/client",
- "version": "0.7.0-alpha.34",
+ "version": "0.7.0-alpha.55",
"license": "Apache-2.0",
"licenses": [
{
@@ -9,19 +9,8 @@
}
],
"main": "lib",
- "module": "esm",
- "sideEffects": [
- "dist/*",
- "esm/*.js",
- "lib/*.js",
- "src/*.ts",
- "*.less",
- "**/*/style.js"
- ],
- "types": "esm/index.d.ts",
- "engines": {
- "npm": ">=3.0.0"
- },
+ "module": "es/index.js",
+ "typings": "es/index.d.ts",
"dependencies": {
"@dnd-kit/core": "^5.0.1",
"@dnd-kit/sortable": "^6.0.0",
@@ -29,10 +18,10 @@
"@formily/antd": "2.0.20",
"@formily/core": "2.0.20",
"@formily/react": "2.0.20",
- "@nocobase/utils": "0.7.0-alpha.34",
+ "@nocobase/utils": "0.7.0-alpha.55",
"ahooks": "^3.0.5",
"antd": "~4.19.5",
- "axios": "^0.24.0",
+ "axios": "^0.26.1",
"classnames": "^2.3.1",
"file-saver": "^2.0.5",
"i18next": "^21.6.0",
@@ -57,12 +46,8 @@
"react-dom": ">=16.8.0",
"react-is": ">=16.8.0 || >=17.0.0"
},
- "scripts": {
- "build": "rimraf -rf lib esm dist && npm run build:cjs && npm run build:esm",
- "build:cjs": "tsc --project tsconfig.build.json",
- "build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir esm"
- },
"devDependencies": {
+ "@testing-library/react": "^12.1.2",
"@types/marked": "^4.0.1",
"axios-mock-adapter": "^1.20.0"
},
diff --git a/packages/core/client/src/block-provider/KanbanBlockProvider.tsx b/packages/core/client/src/block-provider/KanbanBlockProvider.tsx
index 58002cac2..0ed4a567f 100644
--- a/packages/core/client/src/block-provider/KanbanBlockProvider.tsx
+++ b/packages/core/client/src/block-provider/KanbanBlockProvider.tsx
@@ -4,7 +4,7 @@ import { Spin } from 'antd';
import React, { createContext, useContext, useEffect } from 'react';
import { useACLRoleContext } from '../acl';
import { useCollection } from '../collection-manager';
-import { toColumns } from '../schema-component/antd/kanban-v2/Kanban';
+import { toColumns } from '../schema-component/antd/kanban/Kanban';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
export const KanbanBlockContext = createContext({});
diff --git a/packages/core/client/src/schema-component/antd/calendar-v2/Calendar.Designer.tsx b/packages/core/client/src/schema-component/antd/calendar-v2/Calendar.Designer.tsx
deleted file mode 100644
index a1219566f..000000000
--- a/packages/core/client/src/schema-component/antd/calendar-v2/Calendar.Designer.tsx
+++ /dev/null
@@ -1,142 +0,0 @@
-import { ISchema, useField, useFieldSchema } from '@formily/react';
-import React from 'react';
-import { useTranslation } from 'react-i18next';
-import { useCompile, useDesignable } from '../..';
-import { useCalendarBlockContext } from '../../../block-provider';
-import { useCollection } from '../../../collection-manager';
-import { useCollectionFilterOptions } from '../../../collection-manager/action-hooks';
-import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
-import { useSchemaTemplate } from '../../../schema-templates';
-
-const useOptions = () => {
- const compile = useCompile();
- const { fields } = useCollection();
- const options = fields?.map((field) => {
- return {
- value: field.name,
- label: compile(field?.uiSchema?.title),
- };
- });
- return options;
-}
-
-export const CalendarDesigner = () => {
- const field = useField();
- const fieldSchema = useFieldSchema();
- const { name, title, fields } = useCollection();
- const dataSource = useCollectionFilterOptions(name);
- const { service } = useCalendarBlockContext();
- const { dn } = useDesignable();
- const compile = useCompile();
- const { t } = useTranslation();
- const template = useSchemaTemplate();
- const defaultFilter = fieldSchema?.['x-decorator-props']?.params?.filter || {};
- const options = useOptions();
- const fieldNames = fieldSchema?.['x-decorator-props']?.['fieldNames'] || {};
- return (
-
- {
- const fieldNames = field.decoratorProps.fieldNames || {};
- fieldNames['title'] = title;
- field.decoratorProps.params = fieldNames;
- fieldSchema['x-decorator-props']['params'] = fieldNames;
- service.refresh();
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- 'x-decorator-props': field.decoratorProps,
- },
- });
- dn.refresh();
- }}
- />
- {
- const fieldNames = field.decoratorProps.fieldNames || {};
- fieldNames['start'] = start;
- field.decoratorProps.params = fieldNames;
- fieldSchema['x-decorator-props']['params'] = fieldNames;
- service.refresh();
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- 'x-decorator-props': field.decoratorProps,
- },
- });
- dn.refresh();
- }}
- />
- {
- const fieldNames = field.decoratorProps.fieldNames || {};
- fieldNames['end'] = end;
- field.decoratorProps.params = fieldNames;
- fieldSchema['x-decorator-props']['params'] = fieldNames;
- service.refresh();
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- 'x-decorator-props': field.decoratorProps,
- },
- });
- dn.refresh();
- }}
- />
- {
- const params = field.decoratorProps.params || {};
- params.filter = filter;
- field.decoratorProps.params = params;
- fieldSchema['x-decorator-props']['params'] = params;
- service.run({ ...service?.params?.[0], filter });
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- 'x-decorator-props': field.decoratorProps,
- },
- });
- }}
- />
-