diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml
index 7c564cce6..793009536 100644
--- a/.github/workflows/node-ci.yml
+++ b/.github/workflows/node-ci.yml
@@ -1,6 +1,9 @@
name: Nocobase test
-on: [push, pull_request]
+on:
+ pull_request:
+ paths-ignore:
+ - 'docs/**'
jobs:
test:
diff --git a/.gitignore b/.gitignore
index 315ab3b4d..2be23bcba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@ lerna-debug.log
*.sqlite
coverage
.umi
+.umi-production
/uploads
.env.test
docs-dist/
diff --git a/.umirc.ts b/.umirc.ts
index d1fae6822..2f49ac228 100644
--- a/.umirc.ts
+++ b/.umirc.ts
@@ -42,8 +42,8 @@ const getTitle = (item, lang) => {
return item.title;
};
-const parseMenuItems = (items, lang = null) => {
- const menuItems = [];
+const parseMenuItems = (items: any[], lang: string) => {
+ const menuItems: any[] = [];
for (const item of items) {
if (typeof item === 'string') {
const result = markdown(item, lang);
@@ -86,18 +86,63 @@ export default defineConfig({
locales: [[lang, lang]],
hash: true,
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),
+ navs: {
+ 'en-US': [
+ {
+ title: 'Introduction',
+ path: '/introduction'
+ },
+ {
+ title: 'Getting started',
+ path: '/getting-started'
+ },
+ {
+ title: 'Manual',
+ path: '/manual'
+ },
+ {
+ title: 'Development',
+ path: '/development'
+ },
+ {
+ title: 'API reference',
+ path: '/api'
+ },
+ {
+ title: 'GitHub',
+ path: 'https://github.com/nocobase/nocobase',
+ },
+ ],
+ 'zh-CN': [
+ {
+ title: '介绍',
+ path: '/introduction'
+ },
+ {
+ title: '快速开始',
+ path: '/getting-started'
+ },
+ {
+ title: '使用手册',
+ path: '/manual'
+ },
+ {
+ title: '开发教程',
+ path: '/development'
+ },
+ {
+ title: 'API 参考',
+ path: '/api'
+ },
+ {
+ title: 'GitHub',
+ path: 'https://github.com/nocobase/nocobase',
+ },
+ ]
},
+ menus: Object.keys(menus).reduce((result, key) => {
+ const items = menus[key];
+ result[key] = parseMenuItems(items, lang);
+ return result;
+ }, {})
});
diff --git a/docs/menus.ts b/docs/menus.ts
index acf6ee310..9db587035 100644
--- a/docs/menus.ts
+++ b/docs/menus.ts
@@ -1,140 +1,240 @@
-export default [
- {
- title: 'Welcome',
- 'title.zh-CN': '欢迎',
- type: 'group',
- children: [
- '/index',
- '/why',
- '/who',
- '/release-notes',
- ],
- },
- {
- 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',
- '/translations',
- '/roadmap',
- '/faq',
- '/thanks',
- ],
- }
-];
+export default {
+ '/introduction': [
+ '/introduction/index',
+ '/introduction/features',
+ '/introduction/when',
+ '/introduction/quickstart',
+ '/introduction/roadmap',
+ '/introduction/thanks',
+ ],
+ '/getting-started': [
+ {
+ title: 'Installation',
+ 'title.zh-CN': '安装',
+ type: 'subMenu',
+ children: [
+ '/getting-started/installation/index',
+ '/getting-started/installation/docker-compose',
+ '/getting-started/installation/create-nocobase-app',
+ '/getting-started/installation/git-clone',
+ ],
+ },
+ '/getting-started/upgrading',
+ '/getting-started/deployment',
+ ],
+ '/manual': [
+ '/manual/functional-zoning',
+ '/manual/collections',
+ '/manual/menus',
+ '/manual/blocks',
+ '/manual/actions',
+ '/manual/roles-permissions',
+ '/manual/tabs',
+ '/manual/file-storages',
+ '/manual/system-settings',
+ '/manual/plugins',
+ ],
+ '/development': [
+ {
+ title: 'Getting started',
+ 'title.zh-CN': '快速开始',
+ type: 'group',
+ children: [
+ '/development/index',
+ '/development/your-fisrt-plugin'
+ ],
+ },
+ {
+ title: 'Extension Guides',
+ 'title.zh-CN': '扩展指南',
+ type: 'group',
+ children: [
+ '/development/guide/index',
+ '/development/guide/collections-fields',
+ '/development/guide/commands',
+ '/development/guide/hooks',
+ '/development/guide/i18n',
+ '/development/guide/middleware',
+ '/development/guide/migration',
+ '/development/guide/resources-actions',
+ {
+ title: 'UI Schema Designer',
+ type: 'subMenu',
+ children: [
+ // '/development/guide/ui-schema-designer/index',
+ '/development/guide/ui-schema-designer/what-is-ui-schema',
+ '/development/guide/ui-schema-designer/extending-schema-components',
+ // '/development/guide/ui-schema-designer/insert-adjacent',
+ '/development/guide/ui-schema-designer/designable',
+ '/development/guide/ui-schema-designer/component-library',
+ '/development/guide/ui-schema-designer/collection-manager',
+ '/development/guide/ui-schema-designer/acl',
+ ],
+ },
+ '/development/guide/ui-router',
+ ],
+ },
+ {
+ title: 'Test & Build',
+ 'title.zh-CN': '测试与构建',
+ type: 'group',
+ children: ['/development/pre-release/test', '/development/pre-release/build'],
+ },
+ {
+ title: 'HTTP API',
+ type: 'group',
+ children: [
+ '/api/http-api/index',
+ '/api/http-api/rest-api',
+ ],
+ },
+ ],
+ // {
+ // 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',
+ // ],
+ // },
+ // ],
+ // },
+ // ],
+ // },
+ // ],
+ // },
+ '/api': [
+ '/api/index',
+ '/api/env',
+ {
+ title: '@nocobase/server',
+ type: 'subMenu',
+ children: ['/api/server/application', '/api/server/plugin-manager', '/api/server/i18n'],
+ },
+ {
+ title: '@nocobase/database',
+ type: 'subMenu',
+ children: [
+ '/api/database/index',
+ '/api/database/collection',
+ '/api/database/field',
+ '/api/database/repository',
+ '/api/database/relation-repository',
+ '/api/database/operators',
+ ],
+ },
+ {
+ title: '@nocobase/resourcer',
+ type: 'subMenu',
+ children: [
+ '/api/resourcer/index',
+ '/api/resourcer/resource',
+ '/api/resourcer/action',
+ '/api/resourcer/middleware',
+ ],
+ },
+ {
+ title: '@nocobase/acl',
+ path: '/api/acl',
+ },
+ {
+ title: '@nocobase/client',
+ type: 'subMenu',
+ children: [
+ '/api/client/index',
+ '/api/client/application',
+ '/api/client/route-switch',
+ {
+ title: 'SchemaDesigner',
+ 'title.zh-CN': 'SchemaDesigner',
+ type: 'subMenu',
+ children: [
+ '/api/client/schema-designer/schema-component',
+ '/api/client/schema-designer/schema-initializer',
+ '/api/client/schema-designer/schema-settings',
+ ],
+ },
+ {
+ title: 'Extensions',
+ 'title.zh-CN': 'Extensions',
+ type: 'subMenu',
+ children: [
+ '/api/client/extensions/schema-component',
+ '/api/client/extensions/collection-manager',
+ '/api/client/extensions/block-provider',
+ '/api/client/extensions/acl',
+ ],
+ },
+ ],
+ },
+ {
+ title: '@nocobase/cli',
+ path: '/api/cli',
+ },
+ {
+ title: '@nocobase/actions',
+ path: '/api/actions',
+ },
+ {
+ title: '@nocobase/sdk',
+ path: '/api/sdk',
+ },
+ ],
+};
diff --git a/docs/zh-CN/development/plugin-development/server/acl.md b/docs/zh-CN/api/acl.md
similarity index 100%
rename from docs/zh-CN/development/plugin-development/server/acl.md
rename to docs/zh-CN/api/acl.md
diff --git a/docs/zh-CN/api/actions.md b/docs/zh-CN/api/actions.md
new file mode 100644
index 000000000..672e7c4b0
--- /dev/null
+++ b/docs/zh-CN/api/actions.md
@@ -0,0 +1,2 @@
+# Actions API
+
diff --git a/docs/zh-CN/api/cli.md b/docs/zh-CN/api/cli.md
new file mode 100644
index 000000000..d6bf24b97
--- /dev/null
+++ b/docs/zh-CN/api/cli.md
@@ -0,0 +1 @@
+# @nocobase/cli
\ No newline at end of file
diff --git a/docs/zh-CN/api/client/application.md b/docs/zh-CN/api/client/application.md
new file mode 100644
index 000000000..4fd84f9c5
--- /dev/null
+++ b/docs/zh-CN/api/client/application.md
@@ -0,0 +1,33 @@
+# Application
+
+```ts
+const app = new Application({
+ apiClient: {
+ baseURL: process.env.API_BASE_URL,
+ },
+ dynamicImport: (name: string) => {
+ return import(`../plugins/${name}`);
+ },
+});
+```
+
+## 属性
+
+## 方法
+
+
+
+## Providers
+
+- APIClientProvider
+- I18nextProvider
+- AntdConfigProvider
+- RemoteRouteSwitchProvider
+- SystemSettingsProvider
+- PluginManagerProvider
+- SchemaComponentProvider
+- SchemaInitializerProvider
+- BlockSchemaComponentProvider
+- AntdSchemaComponentProvider
+- ACLProvider
+- RemoteDocumentTitleProvider
diff --git a/docs/zh-CN/development/plugin-development/client/providers/acl.md b/docs/zh-CN/api/client/extensions/acl.md
similarity index 100%
rename from docs/zh-CN/development/plugin-development/client/providers/acl.md
rename to docs/zh-CN/api/client/extensions/acl.md
diff --git a/docs/zh-CN/api/client/extensions/block-provider.md b/docs/zh-CN/api/client/extensions/block-provider.md
new file mode 100644
index 000000000..a277e3d54
--- /dev/null
+++ b/docs/zh-CN/api/client/extensions/block-provider.md
@@ -0,0 +1 @@
+# BlockProvider
\ No newline at end of file
diff --git a/docs/zh-CN/development/plugin-development/client/providers/collection-manager.md b/docs/zh-CN/api/client/extensions/collection-manager.md
similarity index 100%
rename from docs/zh-CN/development/plugin-development/client/providers/collection-manager.md
rename to docs/zh-CN/api/client/extensions/collection-manager.md
diff --git a/docs/zh-CN/api/client/extensions/schema-component.md b/docs/zh-CN/api/client/extensions/schema-component.md
new file mode 100644
index 000000000..efc9c4667
--- /dev/null
+++ b/docs/zh-CN/api/client/extensions/schema-component.md
@@ -0,0 +1,22 @@
+# SchemaComponent
+
+## Core
+
+- SchemaComponentProvider
+- SchemaComponent
+- createDesignable
+- useDesignable
+- useCompile
+
+## Common
+
+- DndContext
+- SortableItem
+
+## And Design
+
+- Action
+- BlockItem
+- Calendar
+- CardItem
+- Cascader
diff --git a/docs/zh-CN/api/client/index.md b/docs/zh-CN/api/client/index.md
new file mode 100644
index 000000000..3a2170da0
--- /dev/null
+++ b/docs/zh-CN/api/client/index.md
@@ -0,0 +1,3 @@
+# Overview
+
+test
diff --git a/docs/zh-CN/api/client/route-switch.md b/docs/zh-CN/api/client/route-switch.md
new file mode 100644
index 000000000..325b432b2
--- /dev/null
+++ b/docs/zh-CN/api/client/route-switch.md
@@ -0,0 +1,35 @@
+# RouteSwitch
+
+```tsx | pure
+import React from 'react';
+import { Link, MemoryRouter as Router } from 'react-router-dom';
+import { RouteRedirectProps, RouteSwitchProvider, RouteSwitch } from '@nocobase/client';
+
+const Home = () =>
Home
;
+const About = () => About
;
+
+const routes: RouteRedirectProps[] = [
+ {
+ type: 'route',
+ path: '/',
+ exact: true,
+ component: 'Home',
+ },
+ {
+ type: 'route',
+ path: '/about',
+ component: 'About',
+ },
+];
+
+export default () => {
+ return (
+
+
+ Home, About
+
+
+
+ );
+};
+```
\ No newline at end of file
diff --git a/docs/zh-CN/api/client/schema-designer/schema-component.md b/docs/zh-CN/api/client/schema-designer/schema-component.md
new file mode 100644
index 000000000..efc9c4667
--- /dev/null
+++ b/docs/zh-CN/api/client/schema-designer/schema-component.md
@@ -0,0 +1,22 @@
+# SchemaComponent
+
+## Core
+
+- SchemaComponentProvider
+- SchemaComponent
+- createDesignable
+- useDesignable
+- useCompile
+
+## Common
+
+- DndContext
+- SortableItem
+
+## And Design
+
+- Action
+- BlockItem
+- Calendar
+- CardItem
+- Cascader
diff --git a/docs/zh-CN/api/client/schema-designer/schema-initializer.md b/docs/zh-CN/api/client/schema-designer/schema-initializer.md
new file mode 100644
index 000000000..1947d22cf
--- /dev/null
+++ b/docs/zh-CN/api/client/schema-designer/schema-initializer.md
@@ -0,0 +1 @@
+# SchemaInitializer
\ No newline at end of file
diff --git a/docs/zh-CN/api/client/schema-designer/schema-settings.md b/docs/zh-CN/api/client/schema-designer/schema-settings.md
new file mode 100644
index 000000000..a7700ee3c
--- /dev/null
+++ b/docs/zh-CN/api/client/schema-designer/schema-settings.md
@@ -0,0 +1 @@
+# SchemaSettings
\ No newline at end of file
diff --git a/docs/zh-CN/api/database/collection.md b/docs/zh-CN/api/database/collection.md
new file mode 100644
index 000000000..8be6651ea
--- /dev/null
+++ b/docs/zh-CN/api/database/collection.md
@@ -0,0 +1,484 @@
+# Collection
+
+数据表结构管理类。
+
+大部分接口通常不会直接由开发者调用,除非进行较底层的扩展开发。
+
+## 构造函数
+
+通常不会直接使用,主要通过 `Database` 实例的 `collection` 方法作为代理入口调用。
+
+**签名**
+
+* `constructor(options: CollectionOptions, context: CollectionContext)`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options.name` | `string` | - | collection 标识 |
+| `options.tableName?` | `string` | - | 数据库表名,如不传则使用 `options.name` 的值 |
+| `options.fields?` | `FieldOptions[]` | - | 字段定义,详见 [Field](./field) |
+| `options.model?` | `string \| ModelCtor` | - | Sequelize 的 Model 类型,如果使用的是 `string`,则需要调用之前在 db 上注册过该模型名称 |
+| `options.repository?` | `string \| RepositoryType` | - | 数据仓库类型,如果使用 `string`,则需要调用之前在 db 上注册过该仓库类型 |
+| `options.sortable?` | `string \| boolean \| { name?: string; scopeKey?: string }` | - | 数据可排序字段配置,默认不排序 |
+| `options.autoGenId?` | `boolean` | `true` | 是否自动生成唯一主键,默认为 `true` |
+| `context.database` | `Database` | - | 所在的上下文环境数据库 |
+
+**示例**
+
+创建一张文章表:
+
+```ts
+const posts = new Collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ },
+ {
+ type: 'double',
+ name: 'price',
+ }
+ ]
+}, {
+ // 已存在的数据库实例
+ database: db
+});
+```
+
+## 实例成员
+
+### `options`
+
+数据表配置初始参数。与构造函数的 `options` 参数一致。
+
+### `context`
+
+当前数据表所属的上下文环境,目前主要是数据库实例。
+
+### `name`
+
+数据表名称。
+
+### `db`
+
+所属数据库实例。
+
+### `filterTargetKey`
+
+作为主键的字段名。
+
+### `isThrough`
+
+是否为中间表。
+
+### `model`
+
+匹配 Sequelize 的 Model 类型。
+
+### `repository`
+
+数据仓库实例。
+
+## 字段配置方法
+
+### `getField()`
+
+获取数据表已定义对应名称的字段对象。
+
+**签名**
+
+* `getField(name: string): Field`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `name` | `string` | - | 字段名称 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+const field = posts.getField('title');
+```
+
+### `setField()`
+
+对数据表设置字段。
+
+**签名**
+
+* `setField(name: string, options: FieldOptions): Field`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `name` | `string` | - | 字段名称 |
+| `options` | `FieldOptions` | - | 字段配置,详见 [Field](./field) |
+
+**示例**
+
+```ts
+const posts = db.collection({ name: 'posts' });
+
+posts.setField('title', { type: 'string' });
+```
+
+### `setFields()`
+
+对数据表批量设置多个字段。
+
+**签名**
+
+* `setFields(fields: FieldOptions[], resetFields = true): Field[]`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `fields` | `FieldOptions[]` | - | 字段配置,详见 [Field](./field) |
+| `resetFields` | `boolean` | `true` | 是否重置已存在的字段 |
+
+**示例**
+
+```ts
+const posts = db.collection({ name: 'posts' });
+
+posts.setFields([
+ { type: 'string', name: 'title' },
+ { type: 'double', name: 'price' }
+]);
+```
+
+### `removeField()`
+
+移除数据表已定义对应名称的字段对象。
+
+**签名**
+
+* `removeField(name: string): void | Field`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `name` | `string` | - | 字段名称 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+posts.removeField('title');
+```
+
+### `resetFields()`
+
+重置(清空)数据表的字段。
+
+**签名**
+
+* `resetFields(): void`
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+posts.resetFields();
+```
+
+### `hasField()`
+
+判断数据表是否已定义对应名称的字段对象。
+
+**签名**
+
+* `hasField(name: string): boolean`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `name` | `string` | - | 字段名称 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+posts.hasField('title'); // true
+```
+
+### `findField()`
+
+查找数据表中符合条件的字段对象。
+
+**签名**
+
+* `findField(predicate: (field: Field) => boolean): Field | undefined`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `predicate` | `(field: Field) => boolean` | - | 查找条件 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+posts.findField(field => field.name === 'title');
+```
+
+### `forEachField()`
+
+遍历数据表中的字段对象。
+
+**签名**
+
+* `forEachField(callback: (field: Field) => void): void`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `callback` | `(field: Field) => void` | - | 回调函数 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+posts.forEachField(field => console.log(field.name));
+```
+
+## 索引配置方法
+
+### `addIndex()`
+
+添加数据表索引。
+
+**签名**
+
+* `addIndex(index: string | string[] | { fields: string[], unique?: boolean,[key: string]: any })`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `index` | `string \| string[]` | - | 需要配置索引的字段名 |
+| `index` | `{ fields: string[], unique?: boolean, [key: string]: any }` | - | 完整配置 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+posts.addIndex({
+ fields: ['title'],
+ unique: true
+});
+```
+
+### `removeIndex()`
+
+移除数据表索引。
+
+**签名**
+
+* `removeIndex(fields: string[])`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `fields` | `string[]` | - | 需要移除索引的字段名组合 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ],
+ indexes: [
+ {
+ fields: ['title'],
+ unique: true
+ }
+ ]
+});
+
+posts.removeIndex(['title']);
+```
+
+## 表配置方法
+
+### `remove()`
+
+删除数据表。
+
+**签名**
+
+* `remove(): void`
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+posts.remove();
+```
+
+## 数据库操作方法
+
+### `sync()`
+
+同步数据表定义到数据库。除了 Sequelize 中默认的 `Model.sync` 的逻辑,还会一并处理关系字段对应的数据表。
+
+**签名**
+
+* `sync(): Promise`
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+await posts.sync();
+```
+
+### `existsInDb()`
+
+判断数据表是否存在于数据库中。
+
+**签名**
+
+* `existsInDb(options?: Transactionable): Promise`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options?.transaction` | `Transaction` | - | 事务实例 |
+
+**示例**
+
+```ts
+const posts = db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ }
+ ]
+});
+
+const existed = await posts.existsInDb();
+
+console.log(existed); // false
+```
+
+### `removeFromDb()`
+
+**签名**
+
+* `removeFromDb(): Promise`
+
+**示例**
+
+```ts
+const books = db.collection({
+ name: 'books'
+});
+
+// 同步书籍表到数据库
+await db.sync();
+
+// 删除数据库中的书籍表
+await books.removeFromDb();
+```
diff --git a/docs/zh-CN/api/database/field.md b/docs/zh-CN/api/database/field.md
new file mode 100644
index 000000000..340b97cde
--- /dev/null
+++ b/docs/zh-CN/api/database/field.md
@@ -0,0 +1,554 @@
+# Field
+
+数据表字段管理类(抽象类)。同时是所有字段类型的基类,其他任意字段类型均通过继承该类来实现。
+
+## 构造函数
+
+通常不会直接由开发者调用,主要通过 `db.collection({ fields: [] })` 方法作为代理入口调用。
+
+在扩展字段时主要通过继承 `Field` 抽象类,再注册到 Database 实例中来实现。
+
+**签名**
+
+* `constructor(options: FieldOptions, context: FieldContext)`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options` | `FieldOptions` | - | 字段配置对象 |
+| `options.name` | `string` | - | 字段名称 |
+| `options.type` | `string` | - | 字段类型,对应在 db 中注册的字段类型名称 |
+| `context` | `FieldContext` | - | 字段上下文对象 |
+| `context.database` | `Database` | - | 数据库实例 |
+| `context.collection` | `Collection` | - | 数据表实例 |
+
+## 实例成员
+
+### `name`
+
+字段名称。
+
+### `type`
+
+字段类型。
+
+### `dataType`
+
+字段数据库存储类型。
+
+### `options`
+
+字段初始化配置参数。
+
+### `context`
+
+字段上下文对象。
+
+## 配置方法
+
+### `on()`
+
+基于数据表事件的快捷定义方式。相当于 `db.on(this.collection.name + '.' + eventName, listener)`。
+
+继承时通常无需覆盖此方法。
+
+**签名**
+
+* `on(eventName: string, listener: (...args: any[]) => void)`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `eventName` | `string` | - | 事件名称 |
+| `listener` | `(...args: any[]) => void` | - | 事件监听器 |
+
+### `off()`
+
+基于数据表事件的快捷移除方式。相当于 `db.off(this.collection.name + '.' + eventName, listener)`。
+
+继承时通常无需覆盖此方法。
+
+**签名**
+
+* `off(eventName: string, listener: (...args: any[]) => void)`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `eventName` | `string` | - | 事件名称 |
+| `listener` | `(...args: any[]) => void` | - | 事件监听器 |
+
+### `bind()`
+
+当字段被添加到数据表时触发的执行内容。通常用于添加数据表事件监听器和其他处理。
+
+继承时需要先调用对应的 `super.bind()` 方法。
+
+**签名**
+
+* `bind()`
+
+### `unbind()`
+
+当字段从数据表中移除时触发的执行内容。通常用于移除数据表事件监听器和其他处理。
+
+继承时需要先调用对应的 `super.unbind()` 方法。
+
+**签名**
+
+* `unbind()`
+
+### `get()`
+
+获取字段的配置项的值。
+
+**签名**
+
+* `get(key: string): any`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `key` | `string` | - | 配置项名称 |
+
+**示例**
+
+```ts
+const field = db.collection('users').getField('name');
+
+// 获取字段名称配置项的值,返回 'name'
+console.log(field.get('name'));
+```
+
+### `merge()`
+
+合并字段的配置项的值。
+
+**签名**
+
+* `merge(options: { [key: string]: any }): void`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options` | `{ [key: string]: any }` | - | 要合并的配置项对象 |
+
+**示例**
+
+```ts
+const field = db.collection('users').getField('name');
+
+field.merge({
+ // 添加一个索引配置
+ index: true
+});
+```
+
+### `remove()`
+
+从数据表中移除字段(仅从内存中移除)。
+
+**示例**
+
+```ts
+const books = db.getCollections('books');
+
+books.getField('isbn').remove();
+
+// really remove from db
+await books.sync();
+```
+
+## 数据库方法
+
+### `removeFromDb()`
+
+从数据库中移除字段。
+
+**签名**
+
+* `removeFromDb(options?: Transactionable): Promise`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options.transaction?` | `Transaction` | - | 事务实例 |
+
+### `existsInDb()`
+
+判断字段是否存在于数据库中。
+
+**签名**
+
+* `existsInDb(options?: Transactionable): Promise`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options.transaction?` | `Transaction` | - | 事务实例 |
+
+## 内置字段类型列表
+
+NocoBase 内置了一些常用的字段类型,可以直接在定义数据表的字段是使用对应的 type 名称来指定类型。不同类型的字段参数配置不同,具体可参考下面的列表。
+
+所有字段类型的配置项除了以下额外介绍的以外,都会透传至 Sequelize,所以所有 Sequelize 支持的字段配置项都可以在这里使用(如 `allowNull`、`defaultValue` 等)。
+
+另外 server 端的字段类型主要解决数据库存储和部分算法的问题,与前端的字段展示类型和使用组件基本无关。前端字段类型可以参考教程对应说明。
+
+### `'boolean'`
+
+逻辑值类型。
+
+**示例**
+
+```js
+db.collection({
+ name: 'books',
+ fields: [
+ {
+ type: 'boolean',
+ name: 'published'
+ }
+ ]
+});
+```
+
+### `'integer'`
+
+整型(32 位)。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'books',
+ fields: [
+ {
+ type: 'integer',
+ name: 'pages'
+ }
+ ]
+});
+```
+
+### `'bigInt'`
+
+长整型(64 位)。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'books',
+ fields: [
+ {
+ type: 'bigInt',
+ name: 'words'
+ }
+ ]
+});
+```
+
+### `'double'`
+
+双精度浮点型(64 位)。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'books',
+ fields: [
+ {
+ type: 'double',
+ name: 'price'
+ }
+ ]
+});
+```
+
+### `'real'`
+
+实数类型(仅 PG 适用)。
+
+### `'decimal'`
+
+十进制小数类型。
+
+### `'string'`
+
+字符串类型。相当于大部分数据库的 `VARCHAR` 类型。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'books',
+ fields: [
+ {
+ type: 'string',
+ name: 'title'
+ }
+ ]
+});
+```
+
+### `'text'`
+
+文本类型。相当于大部分数据库的 `TEXT` 类型。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'books',
+ fields: [
+ {
+ type: 'text',
+ name: 'content'
+ }
+ ]
+});
+```
+
+### `'password'`
+
+密码类型(NocoBase 扩展)。基于 Node.js 原生的 crypto 包的 `scrypt` 方法进行密码加密。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'users',
+ fields: [
+ {
+ type: 'password',
+ name: 'password',
+ length: 64, // 长度,默认 64
+ randomBytesSize: 8 // 随机字节长度,默认 8
+ }
+ ]
+});
+```
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `length` | `number` | 64 | 字符长度 |
+| `randomBytesSize` | `number` | 8 | 随机字节大小 |
+
+### `'date'`
+
+日期类型。
+
+### `'time'`
+
+时间类型。
+
+### `'array'`
+
+数组类型(仅 PG 适用)。
+
+### `'json'`
+
+JSON 类型。
+
+### `'jsonb'`
+
+JSONB 类型(仅 PG 适用,其他会被兼容为 `'json'` 类型)。
+
+### `'uuid'`
+
+UUID 类型。
+
+### `'uid'`
+
+UID 类型(NocoBase 扩展)。短随机字符串标识符类型。
+
+### `'formula'`
+
+公式类型(NocoBase 扩展)。可配置基于 [mathjs](https://www.npmjs.com/package/mathjs) 的数学公式计算,公式中可以引用同一条记录中其他列的数值参与计算。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'orders',
+ fields: [
+ {
+ type: 'double',
+ name: 'price'
+ },
+ {
+ type: 'integer',
+ name: 'quantity'
+ },
+ {
+ type: 'formula',
+ name: 'total',
+ expression: 'price * quantity'
+ }
+ ]
+});
+```
+
+### `'radio'`
+
+单选类型(NocoBase 扩展)。全表最多有一行数据的该字段值为 `true`,其他都为 `false` 或 `null`。
+
+**示例**
+
+整个系统只有一个被标记为 root 的用户,任意另一个用户的 root 值被改为 `true` 之后,其他所有 root 为 `true` 的记录均会被修改为 `false`:
+
+```ts
+db.collection({
+ name: 'users',
+ fields: [
+ {
+ type: 'radio',
+ name: 'root',
+ }
+ ]
+});
+```
+
+### `'sort'`
+
+排序类型(NocoBase 扩展)。基于整型数字进行排序,为新记录自动生成新序号,当移动数据时进行序号重排。
+
+数据表如果定义了 `sortable` 选项,也会自动生成对应字段。
+
+**示例**
+
+文章基于所属用户可排序:
+
+```ts
+db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'belongsTo',
+ name: 'user',
+ },
+ {
+ type: 'sort',
+ name: 'priority',
+ scopeKey: 'userId' // 以 userId 相同值分组的数据进行排序
+ }
+ ]
+});
+```
+
+### `'virtual'`
+
+虚拟类型。不实际储存数据,仅用于特殊 getter/setter 定义时使用。
+
+### `'belongsTo'`
+
+多对一关联类型。外键储存在自身表,与 hasOne/hasMany 相对。
+
+**示例**
+
+任意文章属于某个作者:
+
+```ts
+db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'belongsTo',
+ name: 'author',
+ target: 'users', // 不配置默认为 name 复数名称的表名
+ foreignKey: 'authorId', // 不配置默认为 + Id 的格式
+ sourceKey: 'id' // 不配置默认为 target 表的 id
+ }
+ ]
+});
+```
+
+### `'hasOne'`
+
+一对一关联类型。外键储存在关联表,与 belongsTo 相对。
+
+**示例**
+
+任意用户都有一份个人资料:
+
+```ts
+db.collection({
+ name: 'users',
+ fields: [
+ {
+ type: 'hasOne',
+ name: 'profile',
+ target: 'profiles', // 可省略
+ }
+ ]
+})
+```
+
+### `'hasMany'`
+
+一对多关联类型。外键储存在关联表,与 belongsTo 相对。
+
+**示例**
+
+任意用户可以拥有多篇文章:
+
+```ts
+db.collection({
+ name: 'users',
+ fields: [
+ {
+ type: 'hasMany',
+ name: 'posts',
+ foreignKey: 'authorId',
+ sourceKey: 'id'
+ }
+ ]
+});
+```
+
+### `'belongsToMany'`
+
+多对多关联类型。使用中间表储存双方外键,如不指定已存在的表为中间表的话,将会自动创建中间表。
+
+**示例**
+
+任意文章可以加任意多个标签,任意标签也可以被任意多篇文章添加:
+
+```ts
+db.collection({
+ name: 'posts',
+ fields: [
+ {
+ type: 'belongsToMany',
+ name: 'tags',
+ target: 'tags', // 同名可省略
+ through: 'postsTags', // 中间表不配置将自动生成
+ foreignKey: 'postId', // 自身表在中间表的外键
+ sourceKey: 'id', // 自身表的主键
+ otherKey: 'tagId' // 关联表在中间表的外键
+ }
+ ]
+});
+
+db.collection({
+ name: 'tags',
+ fields: [
+ {
+ type: 'belongsToMany',
+ name: 'posts',
+ through: 'postsTags', // 同一组关系指向同一张中间表
+ }
+ ]
+});
+```
diff --git a/docs/zh-CN/api/database/index.md b/docs/zh-CN/api/database/index.md
new file mode 100644
index 000000000..77af5cd16
--- /dev/null
+++ b/docs/zh-CN/api/database/index.md
@@ -0,0 +1,753 @@
+# Database
+
+NocoBase 内置的数据库访问类,通过封装 [Sequelize](https://sequelize.org/) 提供了更加简单的数据库访问接口和统一化的 JSON 数据库表配置方式,同时也提供了扩展字段类型和查询操作符的能力。
+
+Database 类继承自 EventEmitter,可以通过 `db.on('event', callback)` 监听数据库事件,以及 `db.off('event', callback)` 移除监听。
+
+## 包结构
+
+可通过以下方式引入相关实体:
+
+```ts
+import Database, {
+ Field,
+ Collection,
+ Repository,
+ RelationRepository,
+ extend
+} from '@nocobase/database';
+```
+
+## 构造函数
+
+**签名**
+
+* `constructor(options: DatabaseOptions)`
+
+创建一个数据库实例。
+
+**参数**
+
+`options` 参数与 [Sequelize 的构造参数](https://sequelize.org/api/v6/class/src/sequelize.js~sequelize#instance-constructor-constructor)一致的部分会透传至 Sequelize,同时 NocoBase 也会使用一些额外的参数:
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options.host` | `string` | `'localhost'` | 数据库主机 |
+| `options.port` | `number` | - | 数据库服务端口,根据使用的数据库有对应默认端口 |
+| `options.username` | `string` | - | 数据库用户名 |
+| `options.password` | `string` | - | 数据库密码 |
+| `options.database` | `string` | - | 数据库名称 |
+| `options.dialect` | `string` | `'mysql'` | 数据库类型 |
+| `options.storage?` | `string` | `':memory:'` | SQLite 的存储模式 |
+| `options.logging?` | `boolean` | `false` | 是否开启日志 |
+| `options.define?` | `Object` | `{}` | 默认的表定义参数 |
+| `options.tablePrefix?` | `string` | `''` | NocoBase 扩展,表名前缀 |
+| `options.migrator?` | `UmzugOptions` | `{}` | NocoBase 扩展,迁移管理器相关参数,参考 [Umzug](https://github.com/sequelize/umzug/blob/main/src/types.ts#L15) 实现 |
+
+**示例**
+
+```ts
+import Database from '@nocobase/database';
+
+const app = new Database({
+ dialect: 'mysql',
+ host: 'localhost',
+ port: 3306,
+ username: 'root',
+ password: '123456',
+ database: 'test',
+ tablePrefix: 'my_'
+});
+```
+
+## 实例成员
+
+### `sequelize`
+
+初始化后的 Sequelize 实例,在需要使用 sequelize 底层方法时可以调用,相关信息可以直接参考 sequelize 的文档。
+
+### `options`
+
+初始化的配置参数,包含了 Sequelize 的配置参数和 NocoBase 的额外配置参数。
+
+### `version`
+
+连接的数据库的版本信息对象,可通过 `await db.version.satisfies()` 检查是否满足特定数据库版本要求。
+
+**示例**
+
+```ts
+const r = await this.db.version.satisfies({
+ mysql: '>=8.0.17',
+ sqlite: '3.x',
+ postgres: '>=10',
+});
+```
+
+## 迁移相关方法
+
+### `addMigration()`
+
+添加单个迁移文件。
+
+**签名**
+
+* `addMigration(options: MigrationItem)`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options.name` | `string` | - | 迁移文件名称 |
+| `options.context?` | `string` | - | 迁移文件的 `up` 方法 |
+| `options.migration?` | `typeof Migration` | - | 迁移文件的自定义类 |
+| `options.up` | `Function` | - | 迁移文件的 `up` 方法 |
+| `options.down` | `Function` | - | 迁移文件的 `down` 方法 |
+
+**示例**
+
+```ts
+db.addMigration({
+ name: '20220916120411-test-1',
+ async up() {
+ const queryInterface = this.context.db.sequelize.getQueryInterface();
+ await queryInterface.query(/* your migration sqls */);
+ }
+});
+```
+
+### `addMigrations()`
+
+添加指定目录下的迁移文件。
+
+**签名**
+
+* `addMigrations(options: AddMigrationsOptions): void`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `options.directory` | `string` | `''` | 迁移文件所在目录 |
+| `options.extensions` | `string[]` | `['js', 'ts']` | 文件扩展名 |
+| `options.namespace?` | `string` | `''` | 命名空间 |
+| `options.context?` | `Object` | `{ db }` | 迁移文件的上下文 |
+
+**示例**
+
+```ts
+db.addMigrations({
+ directory: path.resolve(__dirname, './migrations'),
+ namespace: 'test'
+});
+```
+
+## 工具方法
+
+### `inDialect()`
+
+判断当前数据库类型是否为指定类型。
+
+**签名**
+
+* `inDialect(dialect: string[]): boolean`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `dialect` | `string[]` | - | 数据库类型,可选值为 `mysql`/`postgres`/`sqlite` |
+
+### `getTablePrefix()`
+
+获取配置中的表名前缀。
+
+**签名**
+
+* `getTablePrefix(): string`
+
+## 数据表配置
+
+### `collection()`
+
+定义一个数据表。该调用类似与 Sequelize 的 `define` 方法,只在内存中创建表结构,如需持久化到数据库,需要调用 `sync` 方法。
+
+**签名**
+
+* `collection(options: CollectionOptions): Collection`
+
+**参数**
+
+`options` 所有配置参数与 `Collection` 类的构造函数一致,参考 [Collection](/api/server/database/collection#构造函数)。
+
+**事件**
+
+* `'beforeDefineCollection'`:在定义表之前触发。
+* `'afterDefineCollection'`:在定义表之后触发。
+
+**示例**
+
+```ts
+db.collection({
+ name: 'books',
+ fields: [
+ {
+ type: 'string',
+ name: 'title',
+ },
+ {
+ type: 'float',
+ name: 'price',
+ }
+ ]
+});
+
+// sync collection as table to db
+await db.sync();
+```
+
+### `getCollection()`
+
+获取已定义的数据表。
+
+**签名**
+
+* `getCollection(name: string): Collection`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `name` | `string` | - | 表名 |
+
+**示例**
+
+```ts
+const collection = db.getCollection('books');
+```
+
+### `hasCollection()`
+
+判断是否已定义指定的数据表。
+
+**签名**
+
+* `hasCollection(name: string): boolean`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `name` | `string` | - | 表名 |
+
+**示例**
+
+```ts
+db.collection({ name: 'books' });
+
+db.hasCollection('books'); // true
+
+db.hasCollection('authors'); // false
+```
+
+### `removeCollection()`
+
+移除已定义的数据表。仅在内存中移除,如需持久化,需要调用 `sync` 方法。
+
+**签名**
+
+* `removeCollection(name: string): void`
+
+**参数**
+
+| 参数名 | 类型 | 默认值 | 描述 |
+| --- | --- | --- | --- |
+| `name` | `string` | - | 表名 |
+
+**事件**
+
+* `'beforeRemoveCollection'`:在移除表之前触发。
+* `'afterRemoveCollection'`:在移除表之后触发。
+
+**示例**
+
+```ts
+db.collection({ name: 'books' });
+
+db.removeCollection('books');
+```
+
+### `import()`
+
+导入文件目录下所有文件作为 collection 配置载入内存。
+
+**签名**
+
+* `async import(options: { directory: string; extensions?: ImportFileExtension[] }): Promise