1. Project Overview & Quickstart (nocobase/README.pt-BR)
1. Project Overview & Quickstart (nocobase/README.pt-BR)
1. Project Overview & Quickstart (nocobase/README.pt-BR)
1. Project Overview & Quickstart (nocobase/README.pt-BR)
Technical Documentation: nocobase/README.pt-BR
โน๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference
README.pt-BR
Agent Skills & Rules
- Discovered 21 agent rule(s) and prompt configurations.
--- METRICS ---
- Files Extracted: 1
- Estimated Token Budget: ~25 tokens
- Canonical Reference: https://codewiki.google/github.com/nocobase/README.pt-BR
2. Official Technical Reference & Guides (nocobase/docs)
File: README.md
NocoBase V1 Documentation (Archived)
This repository is archived and no longer maintained. V2 documentation lives in the main repository: nocobase/nocobase (under the
docs/directory). For the latest docs, visit docs.nocobase.com.
If you need to access the V1 documentation, you can run it locally:
Local Development
git clone https://github.com/nocobase/docs.git
cd docs
yarn install
# Run English docs
yarn dev:en
# Run Chinese docs
yarn dev
# Run French docs
yarn dev:fr
# Run Japanese docs
yarn dev:ja
# Run Russian docs
yarn dev:ruBuild
yarn buildNote: yarn dev and yarn dev:en cannot be run at the same time.
File: package.json
{
"name": "nocobase-docs",
"version": "0.0.1",
"description": "A static site based on dumi",
"scripts": {
"start": "npm run dev",
"dev": "dumi dev",
"dev:en": "cross-env DOC_LANG=en-US dumi dev",
"dev:fr": "cross-env DOC_LANG=fr-FR dumi dev",
"dev:ja": "cross-env DOC_LANG=ja-JP dumi dev",
"dev:ru": "cross-env DOC_LANG=ru-RU dumi dev",
"build": "dumi build",
"build:en": "cross-env DOC_LANG=en-US dumi build",
"build:fr": "cross-env DOC_LANG=fr-FR dumi build",
"build:ja": "cross-env DOC_LANG=ja-JP dumi build",
"build:ru": "cross-env DOC_LANG=ru-RU dumi build",
"prepare": "husky install && dumi setup"
},
"authors": [],
"license": "MIT",
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"lint-staged": {
"*.{md,json}": [
"prettier --write --no-error-on-unmatched-pattern"
]
},
"devDependencies": {
"@alicloud/cdn20180510": "^4.2.2",
"@commitlint/cli": "^18.2.0",
"@commitlint/config-conventional": "^18.1.0",
"ali-oss": "^6.1.0",
"cross-env": "^7.0.3",
"dumi": "^2.2.14",
"husky": "^8.0.3",
"lint-staged": "^15.0.2",
"prettier": "^3.0.3"
},
"dependencies": {
"@formulajs/formulajs": "^4.4.9",
"@nocobase/client": "^0.21.0-alpha.6",
"axios-mock-adapter": "1.22.0",
"cytoscape": "^3.23.0",
"dumi-theme-nocobase": "^0.2.31",
"moment": "^2.30.1",
"sucrase": "^3.0.0",
"vditor": "^3.10.8"
},
"volta": {
"node": "20.14.0",
"yarn": "1.22.19"
},
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
File: tsconfig.json
{
"compilerOptions": {
"jsx": "react",
"strict": true,
"skipLibCheck": true,
"noImplicitAny": false,
"esModuleInterop": true,
"baseUrl": "./",
"paths": {
"@@/": [".dumi/tmp/"]
}
},
"include": [".dumirc.ts"]
}
File: docs/en-US/components.md
Components
File: docs/en-US/index.md
Index
File: docs/en-US/_partials/commercial-installation.md
Installation
This plugin is a commercial plugin, which needs to be uploaded and activated through the plugin manager๏ผ
File: docs/en-US/api/actions.md
@nocobase/actions
Overview
The @nocobase/actions package encapsulates frequently used CRUD-related methods. By simply registering it with the ResourceManager, CRUD operation interfaces can be globally added to system resources.
Basic Usage
import * as actions from `@nocobase/actions`;
const resourceManager = new ResourceManager({
// ...options
});
resourceManager.registerActionHandlers(actions);Action Methods
create
Creates a resource. POST /api/<resource>:create.
curl "http://localhost:13000/api/users:create" \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "admin"}'Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
list
Retrieves a list of resources. GET /api/<resource>:list.
curl -X GET http://localhost:13000/api/users:listParameters
| Parameter | Type | Description | Default |
|---|---|---|---|
filter |
Filter |
Filtering parameters, see Filter Operators | - |
fields |
string[] |
Fields to retrieve | - |
except |
string[] |
Fields to exclude | - |
appends |
string[] |
Related fields to append | - |
sort |
string[] |
Sorting parameters | - |
paginate |
boolean |
Whether to use pagination | true |
page |
number |
Current page number | 1 |
pageSize |
number |
Number of items per page | 20 |
get
Retrieves a specific resource. GET /api/<resource>:get.
curl -X GET http://localhost:13000/api/users:get?filterByTk=1Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
filterByTk |
number | string |
Filter by primary key value | - |
filter |
Filter |
Filtering parameters, see Filter Operators | - |
fields |
string[] |
Fields to retrieve | - |
except |
string[] |
Fields to exclude | - |
appends |
string[] |
Related fields to append | - |
update
Updates one or more resources. PUT /api/<resource>:update.
curl "http://localhost:13000/api/users:update?filterByTk=1" \
-X PUT \
-H "Content-Type: application/json" \
-d '{"username": "admin"}'Parameters
| Parameter | Type | Description |
|---|---|---|
filter |
Filter |
Filtering parameters, see Filter Operators |
filterByTk |
number | string |
Filter by primary key value |
Note: At least one of filter or filterByTk must be provided.
Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
destroy
Deletes one or more resources. DELETE /api/<resource>:destroy.
curl -X DELETE http://localhost:13000/api/users:destroy?filterByTk=1Parameters
| Parameter | Type | Description |
|---|---|---|
filter |
Filter |
Filtering parameters, see Filter Operators |
filterByTk |
number | string |
Filter by primary key value |
Note: At least one of filter or filterByTk must be provided.
firstOrCreate
Retrieves or creates a resource. POST /api/<resource>:firstOrCreate.
curl "http://localhost:13000/api/users:firstOrCreate?filterKeys[]=username" \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "admin", "nickname": "Admin"}'Parameters
| Parameter | Type | Description |
|---|---|---|
filterKeys |
string[] |
Fields in the request body used to find existing resources |
Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
updateOrCreate
Updates or creates a resource. POST /api/<resource>:updateOrCreate.
curl "http://localhost:13000/api/users:updateOrCreate?filterKeys[]=username" \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "admin", "nickname": "Admin"}'Parameters
| Parameter | Type | Description |
|---|---|---|
filterKeys |
string[] |
Fields in the request body used to find existing resources |
Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
move
Moves resources, adjusting the order. Typically used for drag-and-drop sorting in pages. POST /api/<resource>:move.
curl -X POST "http://localhost:13000/api/users:move?sourceId=1&targetId=2"Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
sourceId |
targetKey |
ID of the element to move | - |
targetId |
targetKey |
ID of the element to swap positions with | - |
sortField |
string |
Name of the field where sorting is stored | sort |
targetScope |
string |
Sorting scope, a resource can be sorted by different scopes | - |
sticky |
boolean |
Whether to stick the moved element | - |
method |
insertAfter | prepend |
Insertion method: whether to insert before |
set
Sets associated objects for a resource. POST /api/<resource>/<resourceKey>/<association>:set.
curl "http://localhost:13000/api/users/1/roles:set" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin", "member"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
add
Adds associated objects to a resource. POST /api/<resource>/<resourceKey>/<association>:add.
curl "http://localhost:13000/api/users/1/roles:add" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
remove
Removes associated objects from a resource. POST /api/<resource>/<resourceKey>/<association>:remove.
curl "http://localhost:13000/api/users/1/roles:remove" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
toggle
Toggles associated objects for a resource, adding them if they don't exist, or removing them if they do. POST /api/<resource>/<resourceKey>/<association>:toggle.
curl "http://localhost:13000/api/users/1/roles:toggle" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin", "member"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
File: docs/en-US/api/cli.md
@nocobase/cli
The NocoBase CLI is designed to help you develop, build, and deploy NocoBase applications.
NocoBase CLI supports ts-node and node two operation modes.
- ts-node mode (Default): Used for development environment, support real-time compilation, with relatively slow response
- node mode๏ผUsed for production environment, with quick response, but you need to execute
yarn nocobase buildto compile the entire source code first
Instructions For Use
$ yarn nocobase -h
Usage: nocobase [command] [options]
Options:
-h, --help
Commands:
console
db:auth Verify if the database is successfully connected
db:sync Generate relevant data tables and fields through the configuration of collections
install Install
start Start application in production environment
build Compile and package
clean Delete the compiled files
dev Start application for development environment with real-time compilation
doc Documentation development
test Testing
umi
upgrade Upgrade
migrator Data migration
pm Plugin manager
helpApplication in Scaffolding
scripts in the application scaffolding package.json is as below:
{
"scripts": {
"dev": "nocobase dev",
"start": "nocobase start",
"clean": "nocobase clean",
"build": "nocobase build",
"test": "nocobase test",
"pm": "nocobase pm",
"postinstall": "nocobase postinstall"
}
}Command Line Extensions
NocoBase CLI is built based on commander. You can write the extended commands freely in app/server/index.ts:
const app = new Application(config);
app.command('hello').action(() => {});or in the plugin:
class MyPlugin extends Plugin {
beforeLoad() {
this.app.command('hello').action(() => {});
}
}Run in the terminal:
$ yarn nocobase helloBuilt-in Commands
Sorted by frequency of use.
`dev`
Start application and compile code in real time in development environment.
Usage: nocobase dev [options]
Options:
-p, --port [port]
--client
--server
-h, --helpExample:
# Launch application for development environment, with real-time compilation
yarn nocobase dev
# Start the server side only
yarn nocobase dev --server
# Start the client side only
yarn nocobase dev --client`start`
Start application in production environment, the code needs yarn build.
- NocoBase is installed automatically if it is not installed (Refer to the
installcommand). - The source code needs to be re-packaged if it has any modification (Refer to the
buildcommand).
$ yarn nocobase start -h
Usage: nocobase start [options]
Options:
-p, --port
-s, --silent
-h, --helpExample:
# Launch application for production environment
yarn nocobase start`install`
Install.
$ yarn nocobase install -h
Usage: nocobase install [options]
Options:
-f, --force
-c, --clean
-s, --silent
-l, --lang [lang]
-e, --root-email <rootEmail>
-p, --root-password <rootPassword>
-n, --root-nickname [rootNickname]
-h, --helpExample:
# Initial installation
yarn nocobase install -l zh-CN -e [email protected] -p admin123
# Delete all data tables from NocoBase and reinstall
yarn nocobase install -f -l zh-CN -e [email protected] -p admin123
# Clear database and reinstall
yarn nocobase install -c -l zh-CN -e [email protected] -p admin123Difference between -f/--force and -c/--clean:
-f/--forceDelete data tables of NocoBase-c/--cleanClear database, all data tables are deleted
`upgrade`
Upgrade.
yarn nocobase upgrade`test`
jest test, which supports all jest-cli options, also supports -c, --db-clean.
$ yarn nocobase test -h
Usage: nocobase test [options]
Options:
-c, --db-clean Clear database before running all tests
-h, --helpExample:
# 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
# Clear database before running all tests
yarn nocobase test -c
yarn nocobase test packages/core/server -c`build`
The source code needs to be compiled and packaged before the code is deployed to the production environment; and you need to re-build the code if it has any modification.
# All packages
yarn nocobase build
# Specified packages
yarn nocobase build app/server app/client`clean`
Delete the compiled files.
yarn clean
# Equivalent to
yarn rimraf -rf packages/*/*/{lib,esm,es,dist}`doc`
Documentation development.
# Start the documentation
yarn doc --lang=zh-CN # 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 output documentation of dist
yarn doc serve --lang=zh-CN`db:auth`
Verify if the database is successfully connected.
$ yarn nocobase db:auth -h
Usage: nocobase db:auth [options]
Options:
-r, --retry [retry] Number of retries
-h, --help`db:sync`
Generate relevant data tables and fields through the configuration of collections.
$ yarn nocobase db:sync -h
Usage: nocobase db:sync [options]
Options:
-f, --force
-h, --help display help for command`migrator`
Data migration.
$ yarn nocobase migrator
Positional arguments:
<command>
up Applies pending migrations
down Revert migrations
pending Lists pending migrations
executed Lists executed migrations
create Create a migration file`pm`
Plugin manager.
# Create plugin
yarn pm create hello
# Register plugin
yarn pm add hello
# Enable plugin
yarn pm enable hello
# Disable plugin
yarn pm disable hello
# Remove plugin
yarn pm remove helloNot achieved yet:
# Upgrade plugin
yarn pm upgrade hello
# Publish plugin
yarn pm publish hello`umi`
app/client is built based on umi, you can run other relevant commands through nocobase umi.
# Generate the .umi cache needed for the development environment
yarn nocobase umi generate tmp`help`
The help command, you can also use the option parameter, -h and --help.
# View all cli
yarn nocobase help
# Use -h instead
yarn nocobase -h
# Or --help
yarn nocobase --help
# View options of command db:sync
yarn nocobase db:sync -hFile: docs/en-US/api/index.md
Overview
| Module | Package | Description |
|---|---|---|
| Server | @nocobase/server |
Server-side application |
| Database | @nocobase/database |
Database access layer |
| Resourcer | @nocobase/resourcer |
Resource and route mapping |
| ACL | @nocobase/acl |
Access Control |
| Auth | @nocobase/auth |
User Authentication |
| Client | @nocobase/client |
Client-side application |
| Cache | @nocobase/cache |
Server-side cache |
| Logger | @nocobase/logger |
Server-side logging |
| Telemetry | @nocobase/telemetry |
Server-side telemetry |
| CLI | @nocobase/cli |
NocoBase Command Line Interface |
| SDK | @nocobase/sdk |
NocoBase SDK |
| Actions | @nocobase/actions |
Built-in resource operations |
| Test | @nocobase/test |
Automated testing |
File: docs/en-US/api/logger.md
@nocobase/logger
Create Logger
createLogger()
Creates a custom logger.
Signature
createLogger(options: LoggerOptions)
Type
interface LoggerOptions
extends Omit<winston.LoggerOptions, 'transports' | 'format'> {
dirname?: string;
filename?: string;
format?: 'logfmt' | 'json' | 'delimiter' | 'console' | winston.Logform.Format;
transports?: ('console' | 'file' | 'dailyRotateFile' | winston.transport)[];
}Details
dirname: Log directoryfilename: Log file nameformat: Log formattransports: Log transports
createSystemLogger()
Creates system runtime logs printed in a specified method. Refer to Logger plugin - System log.
Signature
createSystemLogger(options: SystemLoggerOptions)
Type
export interface SystemLoggerOptions extends LoggerOptions {
seperateError?: boolean; // print error seperately, default true
}Details
seperateError: Whether to printerrorlevel logs separately
app.createLogger()
Definition
class Application {
createLogger(options: LoggerOptions) {
const { dirname } = options;
return createLogger({
...options,
dirname: getLoggerFilePath(this.name || 'main', dirname || ''),
});
}
}When dirname is a relative path, the log files will be output to the directory named after the current application.
plugin.createLogger()
Usage is the same as app.createLogger().
Definition
class Plugin {
createLogger(options: LoggerOptions) {
return this.app.createLogger(options);
}
}Configuration
getLoggerLevel()
getLoggerLevel(): 'debug' | 'info' | 'warn' | 'error'
Gets the log level currently configured in the system.
getLoggerFilePath()
getLoggerFilePath(...paths: string[]): string
Concatenates directory paths based on the log directory currently configured in the system.
getLoggerTransports()
getLoggerTransports(): ('console' | 'file' | 'dailyRotateFile')[]
Gets the log output methods currently configured in the system.
getLoggerFormat()
getLoggerFormat(): 'logfmt' | 'json' | 'delimiter' | 'console'
Gets the log format currently configured in the system.
Logger Transports
Transports
Predefined output methods.
Transports.consoleTransports.fileTransports.dailyRotateFile
import { Transports } from '@nocobase/logger';
const transport = Transports.console({
//...
});References
File: docs/en-US/api/acl/acl.md
ACL
Overview
ACL is the permission management module used in NocoBase, responsible for user role management, permission registration and authorization, as well as permission policy evaluation and access control.
Concepts
- Resource: Collections, or custom resources can be registered. Refer to
@nocobase/resourcer. - Action: An operation interface for a resource, such as create, read, update, delete, or other custom actions. Refer to
@nocobase/actions. - Strategy: Configures global permissions for roles, such as permissions for resource operations like create, read, update, delete, import, export, and system permissions like configuring the user interface.
- Snippet: Defines a collection of operations, enabling unified management of operation permissions. Snippet identifiers can be matched using the minimatch rules.
Class Methods
`define()`
Defines a role.
Signature
define(options: DefineOptions): ACLRole
Type Definitions
export interface DefineOptions {
role: string;
strategy?: string | AvailableStrategyOptions;
actions?: ResourceActionsOptions;
snippets?: string[];
}
export interface AvailableStrategyOptions {
displayName?: string;
actions?: false | string | string[];
allowConfigure?: boolean;
resource?: '*';
}
export interface ResourceActionsOptions {
[actionName: string]: RoleActionParams;
}
export interface RoleActionParams {
fields?: string[];
filter?: any;
own?: boolean;
whitelist?: string[];
blacklist?: string[];
}Details
DefineOptions
| Property | Type | Description |
|---|---|---|
role |
string |
Unique identifier for the role |
strategy |
string | AvailableStrategyOptions |
Optional, global access strategy for the role |
actions |
{ [actionName: string]: RoleActionParams; } |
Optional, permission configuration for actions |
snippets |
string[] |
Optional, defines snippets that the role has permission to access |
AvailableStrategyOptions
| Property | Type | Description |
|---|---|---|
displayName |
string |
Optional, display name for the strategy |
action |
false | string | string[] |
Optional, operation interfaces |
allowConfigure |
boolean |
Optional, whether to allow configuring the user interface |
resource |
* |
Applies to all resources |
RoleActionParams
| Property | Type | Description |
|---|---|---|
fields |
string[] |
Optional, fields of the data table to operate on |
filter |
any |
Optional, filter parameters that must be met, only records that meet the conditions can be operated on |
own |
boolean |
Optional, whether to operate only on records created by oneself |
whitelist |
string[] |
Optional, whitelist of fields that can be accessed, only fields in the whitelist can be accessed |
blacklist |
string[] |
Optional, blacklist of fields that cannot be accessed, fields in the blacklist cannot be accessed |
`can()`
Determines the permission to execute an action and returns the final action parameters. Returns null if no permission.
Signature
can(options: CanArgs): CanResult | null
Type Definitions
interface CanArgs {
role: string;
resource: string;
action: string;
ctx?: any;
}
interface CanResult {
role: string;
resource: string;
action: string;
params?: any;
}Details
CanArgs
| Property | Type | Description |
|---|---|---|
role |
string |
Role identifier |
resource |
string |
Resource identifier |
action |
string |
Action identifier |
ctx |
any |
Optional, request context |
CanResult
| Property | Type | Description |
|---|---|---|
role |
string |
Role identifier |
resource |
string |
Resource identifier |
action |
string |
Action identifier |
params |
any |
Optional, action parameters |
`registerSnippet()`
Registers a snippet.
Signature
registerSnippet(snippet: SnippetOptions)
Type Definitions
export type SnippetOptions = {
name: string;
actions: string[];
};Details
| Property | Type | Description |
|---|---|---|
name |
string |
Snippet identifier, can be matched using the minimatch rules. E.g., auth.auth matches auth.*. |
actions |
string[] |
Resource operations included in the snippet, in the format resource:action. E.g., users:list. |
`setAvailableAction()`
Sets allowed actions.
Signature
setAvailableAction(name: string, options: AvailableActionOptions = {})
export interface AvailableActionOptions {
displayName?: string;
aliases?: string[] | string;
resource?: string;
// Perform operations on new data
onNewRecord?: boolean;
// Allow configuring fields
allowConfigureFields?: boolean;
}Details
| Property | Type | Description |
|---|---|---|
displayName |
string |
Optional, display name for the action |
aliases |
string | string[] |
Optional, action aliases. E.g., aliases for get, list operations are both view. |
resource |
string |
Optional, resource |
onNewRecord |
boolean |
Optional, whether the operation applies to new data, such as create operation |
allowConfigureFields |
boolean |
Optional, whether to allow configuring fields |
`setAvailableStrategy()`
Sets allowed strategies for actions.
Signature
setAvailableStrategy(name: string, options: AvailableStrategyOptions)
Refer to AvailableStrategyOptions.
`allow()`
Defines the conditions under which operations are allowed.
acl.allow('plugins', '*', 'public');Signature
allow(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc)
Type
export type ConditionFunc = (ctx: any) => Promise<boolean> | boolean;Details
| Parameter | Type | Description | Default |
|---|---|---|---|
resourceName |
string |
Resource | - |
actionNames |
string | string[] |
Action | - |
condition |
string | ConditionFunc |
Optional, predefined condition identifier, or condition evaluation function | public |
Predefined condition identifiers:
public: Public interface.loggedIn: Allowed when the user is logged in.allowConfigure: Allowed when the current user role has permission to configure the user interface.
`addFixedParams()`
Adds fixed parameters to operations, merging them with current request parameters.
acl.addFixedParams('users', 'list', () => {
return {
filter: {
id: {
$eq: 1,
},
},
};
});Signature
addFixedParams(resource: string, action: string, merger: Merger)
Type Definitions
export type Merger = () => object;Details
| Parameter | Type | Description |
|---|---|---|
resource |
string |
Resource |
action |
string |
Action |
merger |
Merger |
Function returning the fixed parameter object to be added |
`use()`
Adds the ACL middleware.
acl.use(async () => {
return async function (ctx, next) {
// ...
await next();
};
});Signature
use(fn: any, options?: ToposortOptions)
Details
Refer to Middleware.
`middleware()`
NocoBase access control middleware.
File: docs/en-US/api/auth/auth-manager.md
AuthManager
Overview
AuthManager is the user authentication management module in NocoBase, used for registering different types of user authentication.
Basic Usage
const authManager = new AuthManager({
// Key to retrieve the current authenticator identifier from the request header
authKey: 'X-Authenticator',
});
// Set methods for storing and retrieving authenticators in AuthManager
authManager.setStorer({
get: async (name: string) => {
return db.getRepository('authenticators').find({ filter: { name } });
},
});
// Register an authentication type
authManager.registerTypes('basic', {
auth: BasicAuth,
title: 'Password',
});
// Use authentication middleware
app.resourceManager.use(authManager.middleware());Concepts
- Authentication type (
AuthType): Different types of authentication, such as Password, SMS, OIDC, SAML, etc. - Authenticator: An authenticator is a database-stored entity linked to a configuration record for a specific authentication type (
AuthType). Multiple authenticators can exist for one authentication type, each offering diffrent authentications. - Authenticator name: Unique identifier for an authenticator, used to determine the current authentication employed by the current request.
Class Methods
`constructor()`
Constructor, creates an instance of AuthManager.
Signature
constructor(options: AuthManagerOptions)
Types
export interface JwtOptions {
secret: string;
expiresIn?: string;
}
export type AuthManagerOptions = {
authKey: string;
default?: string;
jwt?: JwtOptions;
};Details
AuthManagerOptions
| Attribute | Type | Description | Default |
|---|---|---|---|
authKey |
string |
Optional key to save the current authenticator identifier in the request header | X-Authenticator |
default |
string |
Optional, default authenticator identifier | basic |
jwt |
JwtOptions |
Optional, configure if using JWT for authentication | - |
JwtOptions
| Attribute | Type | Description | Default |
|---|---|---|---|
secret |
string |
Token secret key | X-Authenticator |
expiresIn |
string |
Optional, token expiration period | 7d |
`setStorer()`
Set methods for storing and retrieving authenticator data.
Signature
setStorer(storer: Storer)
Types
export interface Authenticator = {
authType: string;
options: Record<string, any>;
[key: string]: any;
};
export interface Storer {
get: (name: string) => Promise<Authenticator>;
}Details
Authenticator
| Attribute | Type | Description |
|---|---|---|
authType |
string |
Authentication type |
options |
Record<string, any> |
Authenticator-related configurations |
Storer
Storer is the interface for authenticator storage, containing one method.
get(name: string): Promise<Authenticator>- Get authenticator by identifier. In NocoBase, the actual returned type is AuthModel.
`registerTypes()`
Register authentication types.
Signature
registerTypes(authType: string, authConfig: AuthConfig)
Types
export type AuthExtend<T extends Auth> = new (config: Config) => T;
type AuthConfig = {
auth: AuthExtend<Auth>; // The authentication class.
title?: string; // The display name of the authentication type.
};Details
| Attribute | Type | Description |
|---|---|---|
auth |
AuthExtend<Auth> |
Authentication type implementation, refer to Auth |
title |
string |
Optional. Title of the authentication type displayed on the frontend |
`listTypes()`
Get a list of registered authentication types.
Signature
listTypes(): { name: string; title: string }[]
Details
| Attribute | Type | Description |
|---|---|---|
name |
string |
Authentication type identifier |
title |
string |
Title of the authentication type |
`get()`
Get authenticator.
Signature
get(name: string, ctx: Context)
Details
| Attribute | Type | Description |
|---|---|---|
name |
string |
Authenticator identifier |
ctx |
Context |
Request context |
`middleware()`
Authentication middleware. Get the current authenticator and perform user authentication.
File: docs/en-US/api/auth/auth.md
Auth
Overview
Auth is an abstract class for user authentication types, defining the interfaces required to complete user authentication. To extend new user authentication types, you need to inherit from the Auth class and implement its methods. The basic implementation can be referred to as BaseAuth.
interface IAuth {
user: Model;
// Check the authentication status and return the current user.
check(): Promise<Model>;
signIn(): Promise<any>;
signUp(): Promise<any>;
signOut(): Promise<any>;
}
export abstract class Auth implements IAuth {
abstract user: Model;
abstract check(): Promise<Model>;
// ...
}
class CustomAuth extends Auth {
// check: Authentication
async check() {
// ...
}
}Instance Properties
`user`
Information of the authenticated user.
Signature
abstract user: Model
Class Methods
`constructor()`
Constructor, creates an instance of Auth.
Signature
constructor(config: AuthConfig)
Types
export type AuthConfig = {
authenticator: Authenticator;
options: {
[key: string]: any;
};
ctx: Context;
};Details
AuthConfig
| Attribute | Type | Description |
|---|---|---|
authenticator |
Authenticator |
Authenticator data model, the actual type in NocoBase applications is AuthModel |
options |
Record<string, any> |
Authenticator-related configurations |
ctx |
Context |
Request context |
`check()`
User authentication, returns user information. This is an abstract method that all authentication types must implement.
Signature
abstract check(): Promise<Model>
`signIn()`
User login.
Signature
signIn(): Promise<any>
`signUp()`
User registration.
Signature
signUp(): Promise<any>
`signOut()`
User logout.
Signature
signOut(): Promise<any>
File: docs/en-US/api/auth/base-auth.md
BaseAuth
Overview
BaseAuth inherits from the abstract class Auth and serves as the basic implementation for user authentication types, using JWT as the authentication method. In most cases, extending user authentication types can be achieved by inheriting from BaseAuth instead of directly inheriting from the Auth abstract class.
class BasicAuth extends BaseAuth {
constructor(config: AuthConfig) {
// Set user collection
const userCollection = config.ctx.db.getCollection('users');
super({ ...config, userCollection });
}
// User authentication logic, called by `auth.signIn`
// Returns user data
async validate() {
const ctx = this.ctx;
const { values } = ctx.action.params;
// ...
return user;
}
}Class Methods
`constructor()`
Constructor, creates an instance of BaseAuth.
Signature
constructor(config: AuthConfig & { userCollection: Collection })
Details
| Parameter | Type | Description |
|---|---|---|
config |
AuthConfig |
Refer to Auth - AuthConfig |
userCollection |
Collection |
User collection, e.g., db.getCollection('users'), refer to DataBase - Collection |
`user()`
Accessor for setting and getting user information, defaulting to using the ctx.state.currentUser object.
Signature
set user()get user()
`check()`
Authenticates through the request token and returns user information.
`signIn()`
User login, generates a token.
`signUp()`
User registration.
`signOut()`
User logout, token expiration.
`validate()` \*
Core authentication logic, called by the signIn interface, to determine whether the user can successfully log in.
File: docs/en-US/api/cache/cache-manager.md
CacheManager
Overview
CacheManager is based on node-cache-manager and provides caching module management for NocoBase. The built-in cache types are:
- memory: Provided by the default lru-cache of node-cache-manager.
- redis: Supported by node-cache-manager-redis-yet for Redis caching.
More types can be extended and registered through the API.
Concepts
Store: Defines a caching method, including a factory method for creating caches and other related configurations. Each caching method has a unique identifier provided during registration. The two built-in caching methods correspond to the unique identifiers
memoryandredis.Store Factory Method: Provided by
node-cache-managerand related extension packages, used to create caches. Examples includememoryprovided bynode-cache-managerby default, andredisStoreprovided bynode-cache-manager-redis-yet. In this context, the object to be provided corresponds toStoreOptions, which is the first parameter of thecachingmethod innode-cache-manager.Cache: A class encapsulated by NocoBase, providing methods related to cache usage. When actually using caching, operations are performed on instances of
Cache. EachCacheinstance has a unique identifier, which serves as a namespace for distinguishing different modules.
Class Methods
`constructor()`
Signature
constructor(options?: CacheManagerOptions)
Type
export type CacheManagerOptions = Partial<{
defaultStore: string;
stores: {
[storeType: string]: StoreOptions;
};
}>;
type StoreOptions = {
store?: 'memory' | FactoryStore<Store, any>;
close?: (store: Store) => Promise<void>;
// global config
[key: string]: any;
};Details
CacheManagerOptions
| Property | Type | Description |
|---|---|---|
defaultStore |
string |
Unique identifier for the default cache type. |
stores |
Record<string, StoreOptions> |
Registers cache types. The key is the unique identifier for the cache type, and the value is an object containing the registration method and global configurations. |
StoreOptions
| Property | Type | Description |
|---|---|---|
store |
memory | FactoryStore<Store, any> |
The store factory method, corresponding to the first parameter of the caching method. |
close |
(store: Store) => Promise<void> |
Optional. For middleware that requires establishing a connection, such as Redis, provide a callback method for closing the connection. The parameter is the object returned by the store factory method. |
[key: string] |
any |
Other global configurations for the store, corresponding to the second parameter of the caching method. |
Default `options`
import { redisStore, RedisStore } from 'cache-manager-redis-yet';
const defaultOptions: CacheManagerOptions = {
defaultStore: 'memory',
stores: {
memory: {
store: 'memory',
// global config
max: 2000,
},
redis: {
store: redisStore,
close: async (redis: RedisStore) => {
await redis.client.quit();
},
},
},
};The options parameter will be merged with the default options. Existing default options can be omitted. For example:
const cacheManager = new CacheManager({
stores: {
defaultStore: 'redis',
redis: {
// redisStore is already provided in the default options, so only need to provide redisStore configuration.
url: 'redis://localhost:6379',
},
},
});`registerStore()`
Register a new caching method. Example:
import { redisStore } from 'cache-manager-redis-yet';
cacheManager.registerStore({
// Unique identifier for the store
name: 'redis',
// Factory method for creating the store
store: redisStore,
// Callback method for closing the store connection
close: async (redis: RedisStore) => {
await redis.client.quit();
},
// Global configurations
url: 'xxx',
});Signature
registerStore(options: { name: string } & StoreOptions)
`createCache()`
Create a cache. Example:
await cacheManager.createCache({
name: 'default', // Unique identifier for the cache
store: 'memory', // Unique identifier for the store
prefix: 'mycache', // Automatically adds the 'mycache:' prefix to cache keys, optional
// Other store configurations, custom configurations that will be merged with global store configurations
max: 2000,
});Signature
createCache(options: { name: string; prefix?: string; store?: string; [key: string]: any }): Promise<Cache>
Details
options
| Property | Type | Description |
|---|---|---|
name |
string |
Unique identifier for the cache |
store |
string |
Unique identifier for the store |
prefix |
string |
Optional. Prefix automatically added to cache keys |
[key: string] |
any |
Other custom store configurations |
When store is omitted, the defaultStore will be used. In this case, the caching
File: docs/en-US/api/cache/cache.md
Cache
Basic Methods
You can refer to the documentation of node-cache-manager.
get()set()del()reset()wrap()mset()mget()mdel()keys()ttl()
Other Methods
`wrapWithCondition()`
Similar to wrap(), but can decide whether to use caching based on conditions.
async wrapWithCondition<T>(
key: string,
fn: () => T | Promise<T>,
options?: {
// External parameter to control whether to use cache results
useCache?: boolean;
// Determine whether to cache based on data results
isCacheable?: (val: unknown) => boolean | Promise<boolean>;
ttl?: Milliseconds;
},
): Promise<T> {`setValueInObject()`
When the cached content is an object, changes the value of a specific key.
async setValueInObject(key: string, objectKey: string, value: unknown)`getValueInObject()`
When the cached content is an object, retrieves the value of a specific key.
async getValueInObject(key: string, objectKey: string)`delValueInObject()`
When the cached content is an object, deletes a specific key.
async delValueInObject(key: string, objectKey: string)File: docs/en-US/api/client/application.md
Application
Constructor
`constructor()`
Create an application instance.
Signature
constructor(options: ApplicationOptions)
Example
const app = new Application({
apiClient: {
baseURL: process.env.API_BASE_URL,
},
dynamicImport: (name: string) => {
return import(`../plugins/${name}`);
},
});Methods
use()
Add Providers, build-in Providers are:
- APIClientProvider
- I18nextProvider
- AntdConfigProvider
- SystemSettingsProvider
- PluginManagerProvider
- SchemaComponentProvider
- SchemaInitializerProvider
- BlockSchemaComponentProvider
- AntdSchemaComponentProvider
- ACLProvider
- RemoteDocumentTitleProvider
render()
Component to render the App.
import { Application } from '@nocobase/client';
export const app = new Application({
apiClient: {
baseURL: process.env.API_BASE_URL,
},
dynamicImport: (name: string) => {
return import(`../plugins/${name}`);
},
});
export default app.render();File: docs/en-US/api/client/index.md
Overview
test
File: docs/en-US/api/client/router.md
Router
API
Initial
const app = new Application({
router: {
type: 'browser', // type default value is `browser`
},
});
// or
const app = new Application({
router: {
type: 'memory',
initialEntries: ['/'],
},
});add Route
basic
import { RouteObject } from 'react-router-dom';
const app = new Application();
const Hello = () => {
return <div>Hello</div>;
};
// first argument is `name` of route, second argument is `RouteObject`
app.router.add('root', {
path: '/',
element: <Hello />,
});
app.router.add('root', {
path: '/',
Component: Hello,
});Component is String
app.addComponents({
Hello,
});
app.router.add('root', {
path: '/',
Component: 'Hello',
});nested
import { Outlet } from 'react-router-dom';
const Layout = () => {
return (
<div>
<Link to="/home">Home</Link>
<Link to="/about">about</Link>
<Outlet />
</div>
);
};
const Home = () => {
return <div>Home</div>;
};
const About = () => {
return <div>About</div>;
};
app.router.add('root', {
element: <Layout />,
});
app.router.add('root.home', {
path: '/home',
element: <Home />,
});
app.router.add('root.about', {
path: '/about',
element: <About />,
});It will generate the following routes:
{
element: <Layout />,
children: [
{
path: '/home',
element: <Home />
},
{
path: '/about',
element: <About />
}
]
}remove Route
// remove route by name
app.router.remove('root.home');
app.router.remove('hello');Router in plugin
class MyPlugin extends Plugin {
async load() {
// add route
this.app.router.add('hello', {
path: '/hello',
element: <div>hello</div>,
});
// remove route
this.app.router.remove('world');
}
}Example
/**
* defaultShowCode: true
*/
import React from 'react';
import { Link, Outlet } from 'react-router-dom';
import { Application } from '@nocobase/client';
const Home = () => <h1>Home</h1>;
const About = () => <h1>About</h1>;
const Layout = () => {
return (
<div>
<div>
<Link to={'/'}>Home</Link>, <Link to={'/about'}>About</Link>
</div>
<Outlet />
</div>
);
};
const app = new Application({
router: {
type: 'memory',
initialEntries: ['/'],
},
});
app.router.add('root', {
element: <Layout />,
});
app.router.add('root.home', {
path: '/',
element: <Home />,
});
app.router.add('root.about', {
path: '/about',
element: <About />,
});
export default app.getRootComponent();File: docs/en-US/api/client/extensions/acl.md
ACL
Components
` `
` `
` `
` `
` `
` `
Hooks
`useACLContext()`
`useACLRoleContext()`
`useRoleRecheck()`
File: docs/en-US/api/client/extensions/block-provider.md
BlockProvider
Kernel Methods
``
`useBlockRequestContext()`
Build-in BlockProvider Components
` `
``
``
``
` `
` `
``
` `
File: docs/en-US/api/client/extensions/collection-manager.md
CollectionManager
Components
CollectionManagerProvider
<CollectionManagerProvider
interfaces={{}}
collections={[]}
></CollectionManagerProvider>CollectionProvider
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}></CollectionProvider>;If there is no collection parameter passed in, get the collection from CollectionManagerProvider with the corresponding name.
const collections = [
{
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
},
];
<CollectionManagerProvider collections={collections}>
<CollectionProvider name={'tests'}></CollectionProvider>
</CollectionManagerProvider>;CollectionFieldProvider
const field = {
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
};
<CollectionFieldProvider field={field}></CollectionFieldProvider>;If there is no field parameter passed in, get the field from CollectionProvider with the corresponding name.
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}>
<CollectionFieldProvider name={'title'}></CollectionFieldProvider>
</CollectionProvider>;CollectionField
Universal field component that needs to be used with <CollectionProvider/>, but only in schema scenarios. Get the field schema from CollectionProvider with the corresponding name. Extend the configuration via the schema where the CollectionField is located.
{
name: 'title',
'x-decorator': 'FormItem',
'x-decorator-props': {},
'x-component': 'CollectionField',
'x-component-props': {},
properties: {},
}Hooks
useCollectionManager()
Use with <CollectionManagerProvider/>.
const { collections, get } = useCollectionManager();useCollection()
Use with <CollectionProvider/>.
const { name, fields, getField, findField, resource } = useCollection();useCollectionField()
Use with <CollectionFieldProvider/>.
const { name, uiSchema, resource } = useCollectionField();The resource needs to be used with <RecordProvider/> to provide context of the record of the current data table row.
CollectionManager
Components
CollectionManagerProvider
<CollectionManagerProvider
interfaces={{}}
collections={[]}
></CollectionManagerProvider>CollectionProvider
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}></CollectionProvider>;If there is no collection parameter passed in, get the collection from CollectionManagerProvider with the corresponding name.
const collections = [
{
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
},
];
<CollectionManagerProvider collections={collections}>
<CollectionProvider name={'tests'}></CollectionProvider>
</CollectionManagerProvider>;CollectionFieldProvider
const field = {
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
};
<CollectionFieldProvider field={field}></CollectionFieldProvider>;If there is no field parameter passed in, get the field from CollectionProvider with the corresponding name.
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}>
<CollectionFieldProvider name={'title'}></CollectionFieldProvider>
</CollectionProvider>;CollectionField
Universal field component that needs to be used with <CollectionProvider/>, but only in schema scenarios. Get the field schema from CollectionProvider with the corresponding name. Extend the configuration via the schema where the CollectionField is located.
{
name: 'title',
'x-decorator': 'FormItem',
'x-decorator-props': {},
'x-component': 'CollectionField',
'x-component-props': {},
properties: {},
}Hooks
useCollectionManager()
Use with <CollectionManagerProvider/>.
const { collections, get } = useCollectionManager();useCollection()
Use with <CollectionProvider/>.
const { name, fields, getField, findField, resource } = useCollection();useCollectionField()
Use with <CollectionFieldProvider/>.
const { name, uiSchema, resource } = useCollectionField();The resource needs to be used with <RecordProvider/> to provide context of the record of the current data table row.
File: docs/en-US/api/client/extensions/schema-component.md
้้ ็ Schema ็ปไปถ
Common
- DndContext
- SortableItem
And Design
- Action
- BlockItem
- Calendar
- CardItem
- Cascader
File: docs/en-US/api/client/schema-designer/schema-component.md
SchemaComponent
Core Components
` `
``
``
Core Methods
`createDesignable()`
`useDesignable()`
`useCompile()`
File: docs/en-US/api/client/schema-designer/schema-initializer.md
SchemaInitializer
Used for the initialization of various schemas. Newly added schema can be inserted anywhere in an existing schema node, including:
{
properties: {
// beforeBegin - Insert in front of the current node
node1: {
properties: {
// afterBegin - Insert in front of the first child node of the current node
// ...
// beforeEnd - After the last child node of the current node
},
},
// afterEnd - After the current node
},
}The core of SchemaInitializer includes <SchemaInitializer.Button /> and <SchemaInitializer.Item /> the two components. <SchemaInitializer.Button /> is used to create the dropdown menu button of schema, and the options of the dropdown menu is <SchemaInitializer.Item/>.
` `
` `
` `
File: docs/en-US/api/client/schema-designer/schema-settings.md
SchemaSettings
` `
` `
` `
` `
` `
` `
` `
` `
` `
` `
` `
` `
File: docs/en-US/api/data-source-manager/data-source.md
DataSource (abstract)
The DataSource abstract class is used to represent a type of data source, which can be a database, API, etc.
Members
collectionManager
The CollectionManager instance of the data source, which needs to implement the ICollectionManager interface.
resourceManager
The resourceManager instance of the data source, see: resourceManager
acl
The ACL instance of the data source, see: ACL
API
constructor()
Constructor, creates a DataSource instance.
Signature
constructor(options: DataSourceOptions)
init()
Initialization function, called immediately after constructor.
Signature
init(options: DataSourceOptions)
name
Signature
get name()
Returns the instance name of the data source.
middleware()
Gets the middleware of the DataSource, used to mount to the Server to receive requests.
testConnection()
Static method, called during the test connection operation, can be used for parameter validation, specific logic is implemented by subclasses.
Signature
static testConnection(options?: any): Promise
load()
Signature
async load(options: any = {})
The loading operation of the data source, logic is implemented by subclasses.
createCollectionManager()
Signature
abstract createCollectionManager(options?: any): ICollectionManager
Creates a CollectionManager instance for the data source, logic is implemented by subclasses.
createResourceManager()
Creates a ResourceManager instance for the data source, subclasses can override the implementation, by default creates ResourceManager from @nocobase/resourcer.
createACL()
- Creates an ACL instance for the DataSource, subclasses can override the implementation, by default creates
ACLfrom@nocobase/acl.
File: docs/en-US/api/data-source-manager/i-collection-manager.md
ICollectionManager
The ICollectionManager interface is used to manage Collection instances of data sources.
API
registerFieldTypes()
Registers the field types in a Collection.
Signature
registerFieldTypes(types: Record<string, any>): void
registerFieldInterfaces()
Registers the Interface for a Collection.
Signature
registerFieldInterfaces(interfaces: Record<string, any>): void
registerCollectionTemplates()
Registers Collection Templates.
Signature
registerCollectionTemplates(templates: Record<string, any>): void
registerModels()
Registers Models.
Signature
registerModels(models: Record<string, any>): void
registerRepositories()
Registers Repositories.
Signature
registerRepositories(repositories: Record<string, any>): void
getRegisteredRepository()
Retrieves an instance of a registered repository.
Signature
getRegisteredRepository(key: string): IRepository
defineCollection()
Defines a Collection.
Signature
defineCollection(options: CollectionOptions): ICollection
extendCollection()
Modifies an existing Collection property.
Signature
extendCollection(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions): ICollection
hasCollection()
Determines if a Collection exists.
Signature
hasCollection(name: string): boolean
getCollection()
Retrieves an instance of a Collection.
Signature
getCollection(name: string): ICollection
getCollections()
Retrieves all instances of Collection.
Signature
getCollections(): Array
getRepository()
Retrieves an instance of a Repository.
Signature
getRepository(name: string, sourceId?: string | number): IRepository
sync()
Synchronizes the data source, with the logic implemented by subclasses.
Signature
sync(): Promise<void>
File: docs/en-US/api/data-source-manager/i-collection.md
ICollection
ICollection is an interface for data models, which includes information such as the model's name, fields, associations, etc.
export interface ICollection {
repository: IRepository;
updateOptions(options: any): void;
setField(name: string, options: any): IField;
removeField(name: string): void;
getFields(): Array<IField>;
getField(name: string): IField;
[key: string]: any;
}Members
repository
The Repository instance to which ICollection belongs.
API
updateOptions()
Updates the properties of the Collection.
Signature
updateOptions(options: any): void
setField()
Sets a field of the Collection.
Signature
setField(name: string, options: any): IField
removeField()
Removes a field from the Collection.
Signature
removeField(name: string): void
getFields()
Retrieves all fields of the Collection.
Signature
getFields(): Array
getField()
Retrieves a field of the Collection by name.
Signature
getField(name: string): IField
File: docs/en-US/api/data-source-manager/i-field.md
IField
IField defines the interface that fields need to implement.
export type FieldOptions = {
name: string;
field: string;
rawType: string;
type: string;
description?: string;
interface?: string;
uiSchema?: any;
possibleTypes?: string[];
defaultValue?: any;
primaryKey: boolean;
unique: boolean;
allowNull?: boolean;
autoIncrement?: boolean;
[key: string]: any;
};
export interface IField {
options: FieldOptions;
}Properties
options
- Type:
FieldOptions
File: docs/en-US/api/data-source-manager/i-model.md
IModel
The IModel interface defines the basic properties and methods of a model object.
export interface IModel {
toJSON: () => any;
}API
toJSON()
Converts the model object to JSON format.
File: docs/en-US/api/data-source-manager/i-repository.md
IRepository
The Repository interface defines a series of model operation methods for adapting CRUD (Create, Read, Update, Delete) operations on data sources.
API
find()
Returns a list of models that match the query parameters.
Signature
find(options?: any): Promise
findOne()
Returns the first model that matches the query parameters. If multiple models match, only the first one is returned.
Signature
findOne(options?: any): Promise
count()
Returns the number of models that match the query parameters.
Signature
count(options?: any): Promise<Number>
findAndCount()
Returns both the list of models and the count of models that match the query parameters.
Signature
findAndCount(options?: any): Promise<[IModel[], Number]>
create()
Creates a model data object.
Signature
create(options: any): void
update()
Updates the model data object based on the query conditions.
Signature
update(options: any): void
destroy()
Deletes the model data object based on the query conditions.
Signature
destroy(options: any): void
File: docs/en-US/api/data-source-manager/index.md
DataSourceManager
DataSourceManager is a management class for multiple dataSource instances.
API
add()
Adds a dataSource instance.
Signature
add(dataSource: DataSource, options: any = {}): Promise<void>
use()
Adds a global middleware to the dataSource instance.
middleware()
Retrieves the middleware of the current dataSourceManager instance, which can be used to respond to HTTP requests.
afterAddDataSource()
A hook function that is triggered after a new dataSource is added.
Signature
afterAddDataSource(hook: DataSourceHook)
type DataSourceHook = (dataSource: DataSource) => void;registerDataSourceType()
Registers the data source type and its class.
Signature
registerDataSourceType(type: string, dataSourceClass: typeof DataSource)
getDataSourceType()
Retrieves the data source class.
Signature
getDataSourceType(type: string): typeof DataSource
buildDataSourceByType()
Creates a data source instance based on the registered data source type and instance parameters.
Signature
buildDataSourceByType(type: string, options: any): DataSource
File: docs/en-US/api/database/collection.md
Collection
Overview
Collection is used to define the data model in the system, such as model name, fields, indexes, associations, and other information. It is usually called through the collection method of the Database instance as a proxy entry.
const { Database } = require('@nocobase/database')
// Create database instance
const db = new Database({...});
// Define data model
db.collection({
name: 'users',
// Define model fields
fields: [
// Scalar field
{
name: 'name',
type: 'string',
},
// Association field
{
name: 'profile',
type: 'hasOne' // 'hasMany', 'belongsTo', 'belongsToMany'
}
],
});Refer to Fields for more field types.
Constructor
Signature
constructor(options: CollectionOptions, context: CollectionContext)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.name |
string |
- | Identifier of the collection |
options.tableName? |
string |
- | Database table name, the value of options.name is used if not set |
options.fields? |
FieldOptions[] |
- | Definition of fields, refer to Field for details |
options.model? |
string | ModelStatic<Model> |
- | Model type of Sequelize; in case string is used, this model name needs to be registered in the db before being called |
options.repository? |
string | RepositoryType |
- | Data repository type; in case string is used, this repository type needs to be registered in the db before being called |
options.sortable? |
string | boolean | { name?: string; scopeKey?: string } |
- | Configure which fields are sortable; not sortable by default |
options.autoGenId? |
boolean |
true |
Whether to automatically generate unique primary key; true by default |
context.database |
Database |
- | The context database in which it resides |
Example
Create a table posts:
const posts = new Collection(
{
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
{
type: 'double',
name: 'price',
},
],
},
{
// An existing database instance
database: db,
},
);Instance Members
`options`
Initial parameters for data table configuration, which are consistent with the options parameter of the constructor.
`context`
The contextual environment to which the current data table belongs, currently mainly the database instance.
`name`
Name of the data table.
`db`
The database instance to which it belongs.
`filterTargetKey`
Name of the field that is used as the primary key.
`isThrough`
Whether it is an intermediate table.
`model`
Match the Model type of Sequelize.
`repository`
Data repository instance.
Field Configuration Methods
`getField()`
Get a field object whose corresponding name has been defined in the data table.
Signature
getField(name: string): Field
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
const field = posts.getField('title');`setField()`
Set a field to the data table.
Signature
setField(name: string, options: FieldOptions): Field
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
options |
FieldOptions |
- | Configuration of the field, refer to Field for details |
Example
const posts = db.collection({ name: 'posts' });
posts.setField('title', { type: 'string' });`setFields()`
Set multiple fields to the data table.
Signature
setFields(fields: FieldOptions[], resetFields = true): Field[]
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
fields |
FieldOptions[] |
- | Configuration of the fields, refer to Field for details |
resetFields |
boolean |
true |
Whether to reset existing fields |
Example
const posts = db.collection({ name: 'posts' });
posts.setFields([
{ type: 'string', name: 'title' },
{ type: 'double', name: 'price' },
]);`removeField()`
Remove a field object whose corresponding name has been defined in the data table.
Signature
removeField(name: string): void | Field
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.removeField('title');`resetFields()`
Reset (Empty) fields of the data table.
Signature
resetFields(): void
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.resetFields();`hasField()`
Check if the data table has defined a field object with the corresponding name.
Signature
hasField(name: string): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.hasField('title'); // true`findField()`
Find field objects in the data table that match the conditions.
Signature
findField(predicate: (field: Field) => boolean): Field | undefined
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
predicate |
(field: Field) => boolean |
- | The condition |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.findField((field) => field.name === 'title');`forEachField()`
Iterate over field objects in the data table.
Signature
forEachField(callback: (field: Field) => void): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
callback |
(field: Field) => void |
- | Callback function |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.forEachField((field) => console.log(field.name));Index Configuration Methods
`addIndex()`
Add data table index.
Signature
addIndex(index: string | string[] | { fields: string[], unique?: boolean,[key: string]: any })
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
index |
string | string[] |
- | Names of fields to be indexed |
index |
{ fields: string[], unique?: boolean, [key: string]: any } |
- | Full configuration |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.addIndex({
fields: ['title'],
unique: true,
});`removeIndex()`
Remove data table index.
Signature
removeIndex(fields: string[])
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
fields |
string[] |
- | Names of fields to remove indexes |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
indexes: [
{
fields: ['title'],
unique: true,
},
],
});
posts.removeIndex(['title']);Table Configuration Methods
`remove()`
Remove data table.
Signature
remove(): void
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.remove();Database Operation Methods
`sync()`
Synchronize the definitions in data table to the database. In addition to the default Model.sync logic in Sequelize, the data tables corresponding to the relational fields will also be handled together.
Signature
sync(): Promise<void>
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
await posts.sync();`existsInDb()`
Check whether the data table exists in the database.
Signature
existsInDb(options?: Transactionable): Promise
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options?.transaction |
Transaction |
- | Transaction instance |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
const existed = await posts.existsInDb();
console.log(existed); // false`removeFromDb()`
Signature
removeFromDb(): Promise<void>
Example
const books = db.collection({
name: 'books',
});
// Synchronize the table books to the database
await db.sync();
// Remove the table books from the database
await books.removeFromDb();File: docs/en-US/api/database/field.md
Field
Overview
Data table field management class (abstract class). It is also the base class for all field types, and any other field types are implemented by inheriting from this class.
Refer to Extended Field Types to see how to customize fields.
Constructor
It is usually not called directly by the developer, but mainly through the db.collection({ fields: [] }) method as a proxy entry.
Extended field is implemented mainly by inheriting the Field abstract class and registering it to a Database instance.
Signature
constructor(options: FieldOptions, context: FieldContext)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options |
FieldOptions |
- | Field configuration object |
options.name |
string |
- | Field name |
options.type |
string |
- | Field type, corresponding to the name of the field type registered in the db |
context |
FieldContext |
- | Field context object |
context.database |
Database |
- | Database instance |
context.collection |
Collection |
- | Data table instance |
Instance Members
`name`
Field name.
`type`
Field type.
`dataType`
Data type of the field.
`options`
Configuration parameters to initialize the field.
`context`
Field context object.
Configuration Methods
`on()`
Quick definition method based on data table events. It is equivalent to db.on(this.collection.name + '.' + eventName, listener).
It is usually not necessary to override this method when inheriting.
Signature
on(eventName: string, listener: (...args: any[]) => void)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
eventName |
string |
- | Event name |
listener |
(...args: any[]) => void |
- | Event listener |
`off()`
Quick removal method based on data table events. It is equivalent to db.off(this.collection.name + '.' + eventName, listener).
It is usually not necessary to override this method when inheriting.
Signature
off(eventName: string, listener: (...args: any[]) => void)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
eventName |
string |
- | Event name |
listener |
(...args: any[]) => void |
- | Event listener |
`bind()`
The execution content that is triggered when a field is added to data table. Typically used to add data table event listeners and other processing.
The corresponding super.bind() method needs to be called first when inheriting.
Signature
bind()
`unbind()`
The execution content that is triggered when a field is removed from data table. Typically used to remove data table event listeners and other processing.
The corresponding super.unbind() method needs to be called first when inheriting.
Signature
unbind()
`get()`
Get the values of a configuration item of the field.
Signature
get(key: string): any
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
key |
string |
- | Name of the configuration item |
Example
const field = db.collection('users').getField('name');
// Get and return the values of the configuration item 'name'
console.log(field.get('name'));`merge()`
Merge the values of a configuration item of the field.
Signature
merge(options: { [key: string]: any }): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options |
{ [key: string]: any } |
- | The configuration item to merge |
Example
const field = db.collection('users').getField('name');
field.merge({
// Add an index configuration
index: true,
});`remove()`
Remove a field from data table (from memory only).
Example
const books = db.getCollections('books');
books.getField('isbn').remove();
// really remove from db
await books.sync();Database Methods
`removeFromDb()`
Remove a field from the database.
Signature
removeFromDb(options?: Transactionable): Promise<void>
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.transaction? |
Transaction |
- | Transaction instance |
`existsInDb()`
Check if a field exists in the database.
Signature
existsInDb(options?: Transactionable): Promise
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.transaction? |
Transaction |
- | Transaction instance |
Built-in Field Types
NocoBase has some built-in common field types, the corresponding type name can be used directly to specify the type of field upon definition. Fields of different types are configured differently, please refer to the list below.
The configuration items of all field types are passed through to Sequelize in addition to those described below. Therefore, all field configuration items supported by Sequelize can be used here (e.g. allowNull, defaultValue, etc.).
Moreover, server-side field types are mainly used for solving the problems of database storage and some algorithms, they are barely relevant to the field display types and the use of components in front-end. The front-end field types can be found in the corresponding tutorials.
`'boolean'`
Boolean type.
Example
db.collection({
name: 'books',
fields: [
{
type: 'boolean',
name: 'published',
},
],
});`'integer'`
Integer type (32 bits).
Example
db.collection({
name: 'books',
fields: [
{
type: 'integer',
name: 'pages',
},
],
});`'bigInt'`
Long integer type (64 bits).
Example
db.collection({
name: 'books',
fields: [
{
type: 'bigInt',
name: 'words',
},
],
});`'double'`
Double-precision floating-point format (64 bits).
Example
db.collection({
name: 'books',
fields: [
{
type: 'double',
name: 'price',
},
],
});`'real'`
Real type (PG only).
`'decimal'`
Decimal type.
`'string'`
String type. Equivalent to the VARCHAR type for most databases.
Example
db.collection({
name: 'books',
fields: [
{
type: 'string',
name: 'title',
},
],
});`'text'`
Text type. Equivalent to the TEXT type for most databases.
Example
db.collection({
name: 'books',
fields: [
{
type: 'text',
name: 'content',
},
],
});`'password'`
Password type (NocoBase extension). Password encryption based on the scrypt method of Node.js native crypto packages.
Example
db.collection({
name: 'users',
fields: [
{
type: 'password',
name: 'password',
length: 64, // Length, default is 64
randomBytesSize: 8, // Length of random bytes, default is 8
},
],
});Parameter
| Name | Type | Default | Description |
|---|---|---|---|
length |
number |
64 | Length of characters |
randomBytesSize |
number |
8 | Length of random bytes |
`'date'`
Date type.
`'time'`
Time type.
`'array'`
Array type (PG only).
`'json'`
JSON type.
`'jsonb'`
JSONB type (PG only, others will be compatible with the 'json' type).
`'uuid'`
UUID type.
`'uid'`
UID type (NocoBase extension). Short random string identifier type.
`'formula'`
Formula type (NocoBase extension). Mathematical formula calculation can be configured based on mathjs, and the formula can refer to the values of other columns in the same record to participate in the calculation.
Example
db.collection({
name: 'orders',
fields: [
{
type: 'double',
name: 'price',
},
{
type: 'integer',
name: 'quantity',
},
{
type: 'formula',
name: 'total',
expression: 'price * quantity',
},
],
});`'radio'`
Radio type (NocoBase extension). The field value is 'true' for at most one row of data for the full table, all others are 'false' or 'null'.
Example
There is only one user marked as root in the entire system, once the root value of any other user is changed to true, all other records with root of true will be changed to false:
db.collection({
name: 'users',
fields: [
{
type: 'radio',
name: 'root',
},
],
});`'sort'`
Sorting type (NocoBase extension). Sorting based on integer numbers, automatically generating new serial numbers for new records, and rearranging serial numbers when moving data.
If data table has the sortable option defined, the corresponding fields will be generated automatically.
Example
Posts are sortable based on the users they belong to.
db.collection({
name: 'posts',
fields: [
{
type: 'belongsTo',
name: 'user',
},
{
type: 'sort',
name: 'priority',
scopeKey: 'userId', // Sort data grouped by the values of userId
},
],
});`'virtual'`
Virtual type. No Data is actually stored, it is used only when special getter/setter is defined.
`'belongsTo'`
Many-to-one association type. Foreign key is stored in its own table, as opposed to 'hasOne'/'hasMany'.
Example
Any post belongs to an author:
db.collection({
name: 'posts',
fields: [
{
type: 'belongsTo',
name: 'author',
target: 'users', // Default table name is the plural form of <name>
foreignKey: 'authorId', // Default is '<name> + Id'
sourceKey: 'id', // Default is id of the <target> table
},
],
});`'hasOne'`
One-to-one association type. Foreign key is stored in the association table, as opposed to 'belongsTo'.
Example
Any user has a profile:
db.collection({
name: 'users',
fields: [
{
type: 'hasOne',
name: 'profile',
target: 'profiles', // Can be omitted
},
],
});`'hasMany'`
One-to-many association type. The foreign key is stored in the association table, as opposed to 'belongsTo'.
Example
Any user can have multiple posts:
db.collection({
name: 'users',
fields: [
{
type: 'hasMany',
name: 'posts',
foreignKey: 'authorId',
sourceKey: 'id',
},
],
});`'belongsToMany'`
Many-to-many association type. Intermediate table is used to store both foreign keys. If no existing table is specified as intermediate table, it will be created automatically.
Example
Any post can have multiple tags added to it, and any tag can be added to multiple posts:
db.collection({
name: 'posts',
fields: [
{
type: 'belongsToMany',
name: 'tags',
target: 'tags', // Can be omitted if name is the same
through: 'postsTags', // Intermediate table will be generated automatically if not specified
foreignKey: 'postId', // Foreign key in the intermediate table referring to the table itself
sourceKey: 'id', // Primary key of the table itself
otherKey: 'tagId', // Foreign key in the intermediate table referring to the association table
},
],
});
db.collection({
name: 'tags',
fields: [
{
type: 'belongsToMany',
name: 'posts',
through: 'postsTags', // Refer to the same intermediate table in the same set of relation
},
],
});File: docs/en-US/api/database/index.md
Database
Overview
Database is the database interaction tool provided by NocoBase, it provides very convenient database interaction features for no-code and low-code applications. The supported databases are:
- SQLite 3.8.8+
- MySQL 8.0.17+
- PostgreSQL 10.0+
Connect to Database
In Database constructor, database connection can be configured by passing the options parameter.
const { Database } = require('@nocobase/database');
// MySQL database configuration parameters
const database = new Database({
dialect: 'mysql',
host: 'localhost',
port: 3306,
database: 'nocobase',
username: 'root',
password: 'password'
})
// MySQL \ PostgreSQL database configuration parameters
const database = new Database({
dialect: /* 'postgres' or 'mysql' */,
database: 'database',
username: 'username',
password: 'password',
host: 'localhost',
port: 'port'
})Refer to Constructor for detailed configurations.
Define Data Structure
Database defines database structure through Collection, one Collection object represents one table in the database.
// Define Collection
const UserCollection = database.collection({
name: 'users',
fields: [
{
name: 'name',
type: 'string',
},
{
name: 'age',
type: 'integer',
},
],
});After the database structure is defined, use sync() method to synchronize the database structure.
await database.sync();Refer to Collection for detailed usage of Collection.
CRUD Data
Database operates data through Repository.
const UserRepository = UserCollection.repository();
// Create
await UserRepository.create({
name: 'Mark',
age: 18,
});
// Query
const user = await UserRepository.findOne({
filter: {
name: 'Mark',
},
});
// Update
await UserRepository.update({
values: {
age: 20,
},
});
// Delete
await UserRepository.destroy(user.id);Refer to Repository for details of data CRUD.
Constructor
Signature
constructor(options: DatabaseOptions)
Create a database instance.
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.host |
string |
'localhost' |
Database host |
options.port |
number |
- | Database service port, default port depends on the type of database used |
options.username |
string |
- | Database username |
options.password |
string |
- | Database password |
options.database |
string |
- | Database name |
options.dialect |
string |
'mysql' |
Database type |
options.storage? |
string |
':memory:' |
Storage mode for SQLite |
options.logging? |
boolean |
false |
Whether to enable logging |
options.define? |
Object |
{} |
Default table definition parameters |
options.tablePrefix? |
string |
'' |
NocoBase extension, table prefix |
options.migrator? |
UmzugOptions |
{} |
NocoBase extension, parameters for migrator, refer to Umzug for the implementation |
Migration Methods
`addMigration()`
Add single migration file.
Signature
addMigration(options: MigrationItem)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.name |
string |
- | Name of the migration file |
options.context? |
string |
- | Context of the migration file |
options.migration? |
typeof Migration |
- | Custom type of the migration file |
options.up |
Function |
- | up method of the migration file |
options.down |
Function |
- | down method of the migration file |
Example
db.addMigration({
name: '20220916120411-test-1',
async up() {
const queryInterface = this.context.db.sequelize.getQueryInterface();
await queryInterface.query(/* your migration sqls */);
},
});`addMigrations()`
Add the migration files in the specified directory.
Signature
addMigrations(options: AddMigrationsOptions): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.directory |
string |
'' |
Directory where the migration files are located |
options.extensions |
string[] |
['js', 'ts'] |
File extensions |
options.namespace? |
string |
'' |
Namespace |
options.context? |
Object |
{ db } |
Context of the migration files |
Example
db.addMigrations({
directory: path.resolve(__dirname, './migrations'),
namespace: 'test',
});Tool Methods
`inDialect()`
Check whether the current database type is the specified type.
Signature
inDialect(dialect: string[]): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
dialect |
string[] |
- | Database type, options are mysql, postgres and mariadb |
`getTablePrefix()`
Get the table name prefix in the configuration.
Signature
getTablePrefix(): string
Data Table Configurations
`collection()`
Define a data table. This is like the define method of Sequelize, which only creates table structure in memory. Call the sync method if needs to be persisted to the database.
Signature
collection(options: CollectionOptions): Collection
Parameter
All configuration parameters of options is consistent with the constructor of the Collection class, refer to Collection.
Event
'beforeDefineCollection': Trigger before defining the table.'afterDefineCollection': Trigger after defining the table.
Example
db.collection({
name: 'books',
fields: [
{
type: 'string',
name: 'title',
},
{
type: 'float',
name: 'price',
},
],
});
// sync collection as table to db
await db.sync();`getCollection()`
Get a defined data table.
Signature
getCollection(name: string): Collection
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Table name |
Example
const collection = db.getCollection('books');`hasCollection()`
Check whether a specified data table is defined.
Signature
hasCollection(name: string): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Table name |
Example
db.collection({ name: 'books' });
db.hasCollection('books'); // true
db.hasCollection('authors'); // false`removeCollection()`
Remove a defined data table. It is to remove from memory only, call the sync method if needs to be persisted to the database.
Signature
removeCollection(name: string): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Table name |
Event
'beforeRemoveCollection': Trigger before removing the table.'afterRemoveCollection': Trigger after removing the table
Example
db.collection({ name: 'books' });
db.removeCollection('books');`import()`
Load all files in the import file directory into memory as the configuration of collection.
Signature
async import(options: { directory: string; extensions?: ImportFileExtension[] }): Promise<Map<string, Collection>>
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.directory |
string |
- | Path of directory to be imported |
options.extensions |
string[] |
['ts', 'js'] |
Scan for specific suffixes |
Example
The collection defined by file ./collections/books.ts is as below:
export default {
name: 'books',
fields: [
{
type: 'string',
name: 'title',
},
],
};Import the relevant configurations when loading the plugin:
class Plugin {
async load() {
await this.app.db.import({
directory: path.resolve(__dirname, './collections'),
});
}
}Extension Registrations and Acquisitions
`registerFieldTypes()`
Register custom field type.
Signature
registerFieldTypes(fieldTypes: MapOf<typeof Field>): void
Parameter
fieldTypes is a key-value pair, where key is the field type name, and value is the field type class.
Example
import { Field } from '@nocobase/database';
class MyField extends Field {
// ...
}
db.registerFieldTypes({
myField: MyField,
});`registerModels()`
Register custom data model class.
Signature
registerModels(models: MapOf<ModelStatic<any>>): void
Parameter
models is a key-value pair, where key is the data model name, and value is the data model class.
Example
import { Model } from '@nocobase/database';
class MyModel extends Model {
// ...
}
db.registerModels({
myModel: MyModel,
});
db.collection({
name: 'myCollection',
model: 'myModel',
});`registerRepositories()`
Register custom data repository class.
Signature
registerRepositories(repositories: MapOf<RepositoryType>): void
Parameter
repositories is a key-value pair, where key is the data repository name, and value is the data repository class.
Example
import { Repository } from '@nocobase/database';
class MyRepository extends Repository {
// ...
}
db.registerRepositories({
myRepository: MyRepository,
});
db.collection({
name: 'myCollection',
repository: 'myRepository',
});`registerOperators()`
Register custom data query operator.
Signature
registerOperators(operators: MapOf<OperatorFunc>)
Parameter
operators is a key-value pair, where key is the operator name, and value is the generating function of the comparison operator statement.
Example
db.registerOperators({
$dateOn(value) {
return {
[Op.and]: [
{ [Op.gte]: stringToDate(value) },
{ [Op.lt]: getNextDay(value) },
],
};
},
});
db.getRepository('books').count({
filter: {
createdAt: {
// registered operator
$dateOn: '2020-01-01',
},
},
});`getModel()`
Get the defined data model class. If no custom model class has been registered before, the default model class of Sequelize will be returned. The default name is the same as the name defined by collection.
Signature
getModel(name: string): Model
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Registered model name |
Example
db.registerModels({
books: class MyModel extends Model {},
});
const ModelClass = db.getModel('books');
console.log(ModelClass.prototype instanceof MyModel); // trueNote: The model class retrieved from collection is not strictly equivalent to the model class at registration, but is inherited from the model class at registration. Since the properties of Sequelize's model class are modified during initialization, NocoBase automatically handles this inheritance relationship. All the definitions work fine except that the classes are not equal.
`getRepository()`
Get the defined data repository class. If no custom data repository class has been registered before, the default data repository class of NocoBase will be returned. The default name is the same as the name defined by collection.
Data repository class is mainly used for the CRUD operations based on data model, refer to Repository.
Signature
getRepository(name: string): RepositorygetRepository(name: string, relationId?: string | number): Repository
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Registered data repository name |
relationId |
string | number |
- | Foreign key value for relational data |
When the name contains relationship in the form of 'tables.relactions', the related data repository class is returned. If the second parameter is provided, the data repository will be used (query, modify, etc.) based on the foreign key values of the relational data.
Example
Suppose there are two data tables posts and authors, and there is a foreign key in the posts table points to the authors table:
const AuthorsRepo = db.getRepository('authors');
const author1 = AuthorsRepo.create({ name: 'author1' });
const PostsRepo = db.getRepository('authors.posts', author1.id);
const post1 = AuthorsRepo.create({ title: 'post1' });
asset(post1.authorId === author1.id); // trueDatabase Events
`on()`
Listen for database events.
Signature
on(event: string, listener: (...args: any[]) => void | Promise<void>): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
| event | string | - | Event name |
| listener | Function | - | Event listener |
Event name supports Model event of Sequelize by default. Global event is listened to by the name <sequelize_model_global_event>, single Model event is listened to by the name <model_name>. <sequelize_model_event>.
Refer to the Built-in Events section for parameter descriptions and detailed examples of all built-in event types.
`off()`
Remove the event listener function.
Signature
off(name: string, listener: Function)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
| name | string | - | Event name |
| listener | Function | - | Event listener |
Example
const listener = async (model, options) => {
console.log(model);
};
db.on('afterCreate', listener);
db.off('afterCreate', listener);Database Operations
`auth()`
Database connection verification. It can be used to ensure that the application has established connection to the data.
Signature
auth(options: QueryOptions & { retry?: number } = {}): Promise
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options? |
Object |
- | Verification option |
options.retry? |
number |
10 |
Number of retries in case of verification failure |
options.transaction? |
Transaction |
- | Transaction object |
options.logging? |
boolean | Function |
false |
Whether to print the log |
Example
await db.auth();`reconnect()`
Reconnect to the database.
Example
await db.reconnect();`closed()`
Check whether database has closed the connection.
Signature
closed(): boolean
`close()`
Closes database connection. Equivalent to sequelize.close().
`sync()`
Synchronizes database table structure. Equivalent to sequelize.sync(), refer to Sequelize documentation for parameters.
`clean()`
Empty the database, it will delete all data tables.
Signature
clean(options: CleanOptions): Promise<void>
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.drop |
boolean |
false |
Whether to remove all data tables |
options.skip |
string[] |
- | Names of tables to skip |
options.transaction |
Transaction |
- | Transaction object |
Example
Remove all tables except for the users table.
await db.clean({
drop: true,
skip: ['users'],
});Package-Level Export
`defineCollection()`
Create the configuration content of a data table.
Signature
defineCollection(name: string, config: CollectionOptions): CollectionOptions
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
collectionOptions |
CollectionOptions |
- | All parameters are the same with db.collection() |
Example
For the data table configuration file to be imported by db.import():
import { defineCollection } from '@nocobase/database';
export default defineCollection({
name: 'users',
fields: [
{
type: 'string',
name: 'name',
},
],
});`extendCollection()`
Extent the configuration content of a data table that is already in memory, mainly for the content of files imported by the import() method. This is the top-level package export method of @nocobase/database, and is not called through db instance. The extend alias can also be used.
Signature
extendCollection(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions): ExtendedCollectionOptions
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
collectionOptions |
CollectionOptions |
- | All the same with db.collection() |
mergeOptions? |
MergeOptions |
- | deepmerge options of npm package |
Example
Original definition of the table books (books.ts):
export default {
name: 'books',
fields: [{ name: 'title', type: 'string' }],
};Extend the definition of the table books (books.extend.ts):
import { extend } from '@nocobase/database';
// Extend again
export default extend({
name: 'books',
fields: [{ name: 'price', type: 'number' }],
});If the above two files are imported when calling import(), after being extended again by extend(), the table books will have title and price two fields.
This method is especially useful when extending the table structure that is already defined by existing plugin.
Built-in Events
The following events will be triggered in the corresponding lifecycle of database, subscribe by the on() method and perform specific processing to meet some business needs.
`'beforeSync'` / `'afterSync'`
Events triggered before or after a new table structure configuration (fields, indexes, etc.) is synchronized to the database. This is usually triggered when executing collection.sync() (internal call) for the logical processing of the extension of some special fields.
Signature
on(eventName: `${string}.beforeSync` | 'beforeSync' | `${string}.afterSync` | 'afterSync', listener: SyncListener): thisType
import type { SyncOptions, HookReturn } from 'sequelize/types';
type SyncListener = (options?: SyncOptions) => HookReturn;Example
const users = db.collection({
name: 'users',
fields: [{ type: 'string', name: 'username' }],
});
db.on('beforeSync', async (options) => {
// do something
});
db.on('users.afterSync', async (options) => {
// do something
});
await users.sync();`'beforeValidate'` / `'afterValidate'`
Before creating or updating data, there is a validation against the data based on the rules defined by the collection, and the corresponding events are triggered before and after the validation. This is triggered when repository.create() or repository.update() is called.
Signature
on(eventName: `${string}.beforeValidate` | 'beforeValidate' | `${string}.afterValidate` | 'afterValidate', listener: ValidateListener): thisType
import type { ValidationOptions } from 'sequelize/types/lib/instance-validator';
import type { HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
type ValidateListener = (
model: Model,
options?: ValidationOptions,
) => HookReturn;Example
db.collection({
name: 'tests',
fields: [
{
type: 'string',
name: 'email',
validate: {
isEmail: true,
},
},
],
});
// all models
db.on('beforeValidate', async (model, options) => {
// do something
});
// tests model
db.on('tests.beforeValidate', async (model, options) => {
// do something
});
// all models
db.on('afterValidate', async (model, options) => {
// do something
});
// tests model
db.on('tests.afterValidate', async (model, options) => {
// do something
});
const repository = db.getRepository('tests');
await repository.create({
values: {
email: 'abc', // checks for email format
},
});
// or
await repository.update({
filterByTk: 1,
values: {
email: 'abc', // checks for email format
},
});`'beforeCreate'` / `'afterCreate'`
Events triggered before or after creating one piece of data. This is triggered when repository.create() is called.
Signature
on(eventName: `${string}.beforeCreate` | 'beforeCreate' | `${string}.afterCreate` | 'afterCreate', listener: CreateListener): thisType
import type { CreateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type CreateListener = (
model: Model,
options?: CreateOptions,
) => HookReturn;Example
db.on('beforeCreate', async (model, options) => {
// do something
});
db.on('books.afterCreate', async (model, options) => {
const { transaction } = options;
const result = await model.constructor.findByPk(model.id, {
transaction,
});
console.log(result);
});`'beforeUpdate'` / `'afterUpdate'`
Events triggered before or after updating one piece of data. This is triggered when repository.update() is called.
Signature
on(eventName: `${string}.beforeUpdate` | 'beforeUpdate' | `${string}.afterUpdate` | 'afterUpdate', listener: UpdateListener): thisType
import type { UpdateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type UpdateListener = (
model: Model,
options?: UpdateOptions,
) => HookReturn;Example
db.on('beforeUpdate', async (model, options) => {
// do something
});
db.on('books.afterUpdate', async (model, options) => {
// do something
});`'beforeSave'` / `'afterSave'`
Events triggered before or after creating or updating one piece of data. This is triggered when repository.create() or repository.update() is called.
Signature
on(eventName: `${string}.beforeSave` | 'beforeSave' | `${string}.afterSave` | 'afterSave', listener: SaveListener): thisType
import type { SaveOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type SaveListener = (model: Model, options?: SaveOptions) => HookReturn;Example
db.on('beforeSave', async (model, options) => {
// do something
});
db.on('books.afterSave', async (model, options) => {
// do something
});`'beforeDestroy'` / `'afterDestroy'`
Events triggered before or after deleting one piece of data. This is triggered when repository.destroy() is called.
Signature
on(eventName: `${string}.beforeDestroy` | 'beforeDestroy' | `${string}.afterDestroy` | 'afterDestroy', listener: DestroyListener): thisType
import type { DestroyOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type DestroyListener = (
model: Model,
options?: DestroyOptions,
) => HookReturn;Example
db.on('beforeDestroy', async (model, options) => {
// do something
});
db.on('books.afterDestroy', async (model, options) => {
// do something
});`'afterCreateWithAssociations'`
Events triggered after creating one piece of data that carries hierarchical data. This is triggered when repository.create() is called.
Signature
on(eventName: `${string}.afterCreateWithAssociations` | 'afterCreateWithAssociations', listener: CreateWithAssociationsListener): thisType
import type { CreateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type CreateWithAssociationsListener = (
model: Model,
options?: CreateOptions,
) => HookReturn;Example
db.on('afterCreateWithAssociations', async (model, options) => {
// do something
});
db.on('books.afterCreateWithAssociations', async (model, options) => {
// do something
});`'afterUpdateWithAssociations'`
Events triggered after updating one piece of data that carries hierarchical data. This is triggered when repository.update() is called.
Signature
on(eventName: `${string}.afterUpdateWithAssociations` | 'afterUpdateWithAssociations', listener: CreateWithAssociationsListener): thisType
import type { UpdateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type UpdateWithAssociationsListener = (
model: Model,
options?: UpdateOptions,
) => HookReturn;Example
db.on('afterUpdateWithAssociations', async (model, options) => {
// do something
});
db.on('books.afterUpdateWithAssociations', async (model, options) => {
// do something
});`'afterSaveWithAssociations'`
Events triggered after creating or updating one piece of data that carries hierarchical data. This is triggered when repository.create() or repository.update() is called.
Signature
on(eventName: `${string}.afterSaveWithAssociations` | 'afterSaveWithAssociations', listener: SaveWithAssociationsListener): thisType
import type { SaveOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type SaveWithAssociationsListener = (
model: Model,
options?: SaveOptions,
) => HookReturn;Example
db.on('afterSaveWithAssociations', async (model, options) => {
// do something
});
db.on('books.afterSaveWithAssociations', async (model, options) => {
// do something
});`'beforeDefineCollection'`
Events triggered before defining a data table, such as when db.collection() is called.
Note: This is a synchronous event.
Signature
on(eventName: 'beforeDefineCollection', listener: BeforeDefineCollectionListener): thisType
import type { CollectionOptions } from '@nocobase/database';
export type BeforeDefineCollectionListener = (
options: CollectionOptions,
) => void;Example
db.on('beforeDefineCollection', (options) => {
// do something
});`'afterDefineCollection'`
Events triggered after defining a data table, such as when db.collection() is called.
Note: This is a synchronous event.
Signature
on(eventName: 'afterDefineCollection', listener: AfterDefineCollectionListener): thisType
import type { Collection } from '@nocobase/database';
export type AfterDefineCollectionListener = (options: Collection) => void;Example
db.on('afterDefineCollection', (collection) => {
// do something
});`'beforeRemoveCollection'` / `'afterRemoveCollection'`
Events triggered before or after removing a data table from memory, such as when db.removeCollection() is called.
Note: This is a synchronous event.
Signature
on(eventName: 'beforeRemoveCollection' | 'afterRemoveCollection', listener: RemoveCollectionListener): thisType
import type { Collection } from '@nocobase/database';
export type RemoveCollectionListener = (options: Collection) => void;Example
db.on('beforeRemoveCollection', (collection) => {
// do something
});
db.on('afterRemoveCollection', (collection) => {
// do something
});File: docs/en-US/api/database/operators.md
Filter Operators
Used in the filter parameters of the find, findOne, findAndCount, count, etc. APIs of repository:
const repository = db.getRepository('books');
repository.find({
filter: {
title: {
$eq: 'Spring and Autumn',
},
},
});To support JSON, NocoBase identifies query operators as a string prefixed with $.
Moreover, NocoBase provides API to extend operators. Refer to db.registerOperators().
General Operators
`$eq`
Check if the field value is equal to the specified value. Equivalent to = in SQL.
Example
repository.find({
filter: {
title: {
$eq: 'Spring and Autumn',
},
},
});Equal to title: 'Spring and Autumn'
`$ne`
Check if the field value is not equal to the specified value. Equivalent to != in SQL.
Example
repository.find({
filter: {
title: {
$ne: 'Spring and Autumn',
},
},
});`$is`
Check if the field value is the specified value. Equivalent to IS in SQL.
Example
repository.find({
filter: {
title: {
$is: null,
},
},
});`$not`
Check if the field value is not the specified value. Equivalent to IS NOT in SQL.
Example
repository.find({
filter: {
title: {
$not: null,
},
},
});`$col`
Check if the field value is equal to the value of another field. Equivalent to = in SQL.
Example
repository.find({
filter: {
title: {
$col: 'name',
},
},
});`$in`
Check if the field value is in the specified array. Equivalent to IN in SQL.
Example
repository.find({
filter: {
title: {
$in: ['Spring and Autumn', 'Warring States'],
},
},
});`$notIn`
Check if the field value is not in the specified array. Equivalent to NOT IN in SQL.
Example
repository.find({
filter: {
title: {
$notIn: ['Spring and Autumn', 'Warring States'],
},
},
});`$empty`
Check if the general field is empty. For string field, check if it is an empty string; for array field, check if it is an empty array.
Example
repository.find({
filter: {
title: {
$empty: true,
},
},
});`$notEmpty`
Check if the general field is not empty. For string field, check if it is not an empty string; for array field, check if it is not an empty array.
Example
repository.find({
filter: {
title: {
$notEmpty: true,
},
},
});Logical Operators
`$and`
Logical AND. Equivalent to AND in SQL.
Example
repository.find({
filter: {
$and: [{ title: 'Book of Songs' }, { isbn: '1234567890' }],
},
});`$or`
Logical OR. Equivalent to OR in SQL.
Example
repository.find({
filter: {
$or: [
{ title: 'Book of Songs' },
{ publishedAt: { $lt: '0000-00-00T00:00:00Z' } },
],
},
});Boolean Field Operators
For boolean fields: type: 'boolean'
`$isFalsy`
Check if a Boolean field value is false. Boolean field values of false, 0 and NULL are all judged to be $isFalsy: true.
Example
repository.find({
filter: {
isPublished: {
$isFalsy: true,
},
},
});`$isTruly`
Check if a Boolean field value is true. Boolean field values of true and 1 are all judged to be $isTruly: true.
Example
repository.find({
filter: {
isPublished: {
$isTruly: true,
},
},
});Numeric Type Field Operators
For numeric type fields, including:
type: 'integer'type: 'float'type: 'double'type: 'real'type: 'decimal'
`$gt`
Check if the field value is greater than the specified value. Equivalent to > in SQL.
Example
repository.find({
filter: {
price: {
$gt: 100,
},
},
});`$gte`
Check if the field value is equal to or greater than the specified value. Equivalent to >= in SQL.
Example
repository.find({
filter: {
price: {
$gte: 100,
},
},
});`$lt`
Check if the field value is less than the specified value. Equivalent to < in SQL.
Example
repository.find({
filter: {
price: {
$lt: 100,
},
},
});`$lte`
Check if the field value is equal to or less than the specified value. Equivalent to <= in SQL.
Example
repository.find({
filter: {
price: {
$lte: 100,
},
},
});`$between`
Check if the field value is between the specified two values. Equivalent to BETWEEN in SQL.
Example
repository.find({
filter: {
price: {
$between: [100, 200],
},
},
});`$notBetween`
Check if the field value is not between the specified two values. Equivalent to NOT BETWEEN in SQL.
Example
repository.find({
filter: {
price: {
$notBetween: [100, 200],
},
},
});String Type Field Operators
For string type fields, including string.
`$includes`
Check if the string field contains the specified substring.
Example
repository.find({
filter: {
title: {
$includes: 'Three Character Classic',
},
},
});`$notIncludes`
Check if the string field does not contain the specified substring.
Example
repository.find({
filter: {
title: {
$notIncludes: 'Three Character Classic',
},
},
});`$startsWith`
Check if the string field starts with the specified substring.
Example
repository.find({
filter: {
title: {
$startsWith: 'Three Character Classic',
},
},
});`$notStatsWith`
Check if the string field does not start with the specified substring.
Example
repository.find({
filter: {
title: {
$notStatsWith: 'Three Character Classic',
},
},
});`$endsWith`
Check if the string field ends with the specified substring.
Example
repository.find({
filter: {
title: {
$endsWith: 'Three Character Classic',
},
},
});`$notEndsWith`
Check if the string field does not end with the specified substring.
Example
repository.find({
filter: {
title: {
$notEndsWith: 'Three Character Classic',
},
},
});`$like`
Check if the field value contains the specified string. Equivalent to LIKE in SQL.
Example
repository.find({
filter: {
title: {
$like: 'Computer',
},
},
});`$notLike`
Check if the field value does not contain the specified string. Equivalent to NOT LIKE in SQL.
Example
repository.find({
filter: {
title: {
$notLike: 'Computer',
},
},
});`$iLike`
Check if a field value contains the specified string, case ignored. Equivalent to ILIKE in SQL (PG only).
Example
repository.find({
filter: {
title: {
$iLike: 'Computer',
},
},
});`$notILike`
Check if a field value does not contain the specified string, case ignored. Equivalent to NOT ILIKE in SQL (PG only).
Example
repository.find({
filter: {
title: {
$notILike: 'Computer',
},
},
});`$regexp`
Check if the field value matches the specified regular expression. Equivalent to REGEXP in SQL (PG only).
Example
repository.find({
filter: {
title: {
$regexp: '^Computer',
},
},
});`$notRegexp`
Check if the field value does not match the specified regular expression. Equivalent to NOT REGEXP in SQL (PG only).
Example
repository.find({
filter: {
title: {
$notRegexp: '^Computer',
},
},
});`$iRegexp`
Check if the field value matches the specified regular expression, case ignored. Equivalent to ~* in SQL (PG only).
Example
repository.find({
filter: {
title: {
$iRegexp: '^COMPUTER',
},
},
});`$notIRegexp`
Check if the field value does not match the specified regular expression, case ignored. Equivalent to !~* in SQL (PG only).
Example
repository.find({
filter: {
title: {
$notIRegexp: '^COMPUTER',
},
},
});Date Type Field Operators
For date type fields: type: 'date'
`$dateOn`
Check if the date field value is within a certain day.
Example
repository.find({
filter: {
createdAt: {
$dateOn: '2021-01-01',
},
},
});`$dateNotOn`
Check if the date field value is not within a certain day.
Example
repository.find({
filter: {
createdAt: {
$dateNotOn: '2021-01-01',
},
},
});`$dateBefore`
Check if the date field value is before a certain value, i.e., less than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateBefore: '2021-01-01T00:00:00.000Z',
},
},
});`$dateNotBefore`
Check if the date field value is not before a certain value, i.e., equal to or greater than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateNotBefore: '2021-01-01T00:00:00.000Z',
},
},
});`$dateAfter`
Check if the date field value is after a certain value, i.e., greater than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateAfter: '2021-01-01T00:00:00.000Z',
},
},
});`$dateNotAfter`
Check if the date field value is not after a certain value, i.e., equal to or greater than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateNotAfter: '2021-01-01T00:00:00.000Z',
},
},
});Array Type Field Operators
For array type fields: type: 'array'
`$match`
Check if the array field values match values of the specified array.
Example
repository.find({
filter: {
tags: {
$match: ['literature', 'history'],
},
},
});`$notMatch`
Check if the array field values do not match values of the specified array.
Example
repository.find({
filter: {
tags: {
$notMatch: ['literature', 'history'],
},
},
});`$anyOf`
Check if the array field values contain any of the values of the specified array.
Example
repository.find({
filter: {
tags: {
$anyOf: ['literature', 'history'],
},
},
});`$noneOf`
Check if the array field values contain none of the values of the specified array.
Example
repository.find({
filter: {
tags: {
$noneOf: ['literature', 'history'],
},
},
});`$arrayEmpty`
Check if the array field is empty.
Example
repository.find({
filter: {
tags: {
$arrayEmpty: true,
},
},
});`$arrayNotEmpty`
Check if the array field is not empty.
Example
repository.find({
filter: {
tags: {
$arrayNotEmpty: true,
},
},
});Relational Field Type Operators
For checking if a relationship exists, field types include:
type: 'hasOne'type: 'hasMany'type: 'belongsTo'type: 'belongsToMany'
`$exists`
There is relational data existing.
Example
repository.find({
filter: {
author: {
$exists: true,
},
},
});`$notExists`
There is no relational data existing.
Example
repository.find({
filter: {
author: {
$notExists: true,
},
},
});File: docs/en-US/api/database/repository.md
Repository
Overview
On a given Collection object, you can get its Repository object to perform read and write operations on the data table.
const { UserCollection } = require('./collections');
const UserRepository = UserCollection.repository;
const user = await UserRepository.findOne({
filter: {
id: 1,
},
});
user.name = 'new name';
await user.save();Query
Basic Query
On the Repository object, call the find* methods to perform query. The filter parameter is supported by all query methods to filter the data.
// SELECT * FROM users WHERE id = 1
userRepository.find({
filter: {
id: 1,
},
});Operator
The filter parameter in the Repository also provides a variety of operators to perform more diverse queries.
// SELECT * FROM users WHERE age > 18
userRepository.find({
filter: {
age: {
$gt: 18,
},
},
});
// SELECT * FROM users WHERE age > 18 OR name LIKE '%ๅผ %'
userRepository.find({
filter: {
$or: [{ age: { $gt: 18 } }, { name: { $like: '%ๅผ %' } }],
},
});Refer to Filter Operators for more details on operators.
Field Control
Control the output fields by the fields, except, and appends parameters when performing query.
fields: Specify output fieldsexcept: Exclude output fieldsappends: Append output associated fields
// The result contains only the id and name fields
userRepository.find({
fields: ['id', 'name'],
});
// The result does not contain only the password field
userRepository.find({
except: ['password'],
});
// The result contains data associated with the posts object
userRepository.find({
appends: ['posts'],
});Associated Field Query
The filter parameter supports filtering by associated fields, for example:
// Find the user objects whose associated posts have title of "post title"
userRepository.find({
filter: {
'posts.title': 'post title',
},
});Associated fields can also be nested:
// Find the user objects whose associated posts have comments containing "keywords"
await userRepository.find({
filter: {
'posts.comments.content': {
$like: '%keywords%',
},
},
});Sort
Sort query results by the sort parameter.
// SELECT * FROM users ORDER BY age
await userRepository.find({
sort: 'age',
});
// SELECT * FROM users ORDER BY age DESC
await userRepository.find({
sort: '-age',
});
// SELECT * FROM users ORDER BY age DESC, name ASC
await userRepository.find({
sort: ['-age', 'name'],
});Sort by the field of the associated object is also supported:
await userRepository.find({
sort: 'profile.createdAt',
});Create
Basic Create
Create new data objects via Repository.
await userRepository.create({
name: 'Mark',
age: 18,
});
// INSERT INTO users (name, age) VALUES ('Mark', 18)
// Bulk creation
await userRepository.create([
{
name: 'Mark',
age: 18,
},
{
name: 'Alex',
age: 20,
},
]);Create Association
Create associated objects at the same time of creating data. Like query, nested use of associated objects is also supported. For example:
await userRepository.create({
name: 'Mark',
age: 18,
posts: [
{
title: 'post title',
content: 'post content',
tags: [
{
name: 'tag1',
},
{
name: 'tag2',
},
],
},
],
});
// When creating a user, create a post to associate with the user, and create tags to associate with the postIf the associated object is already in the database, you can pass its ID to create an association with it.
const tag1 = await tagRepository.findOne({
filter: {
name: 'tag1',
},
});
await userRepository.create({
name: 'Mark',
age: 18,
posts: [
{
title: 'post title',
content: 'post content',
tags: [
{
id: tag1.id, // Create an association with an existing associated object
},
{
name: 'tag2',
},
],
},
],
});Update
Basic Update
After getting the data object, you can modify the properties directly on the data object (Model), and then call the save method to save the changes.
const user = await userRepository.findOne({
filter: {
name: 'Mark',
},
});
user.age = 20;
await user.save();The data object Model is inherited from Sequelize Model, refer to Sequelize Model for the operations on Model.
Or update data via Repository:
// Update the records that meet the filtering condition
await userRepository.update({
filter: {
name: 'Mark',
},
values: {
age: 20,
},
});Control which fields to update by the whitelist and blacklist parameters, for example:
await userRepository.update({
filter: {
name: 'Mark',
},
values: {
age: 20,
name: 'Alex',
},
whitelist: ['age'], // Only update the age field
});Update Associated Field
Associated objects can be set while updating, for example:
const tag1 = tagRepository.findOne({
filter: {
id: 1,
},
});
await postRepository.update({
filter: {
id: 1,
},
values: {
title: 'new post title',
tags: [
{
id: tag1.id, // Associate with tag1
},
{
name: 'tag2', // Create new tag and associate with it
},
],
},
});
await postRepository.update({
filter: {
id: 1,
},
values: {
tags: null, // Disassociate post from tags
},
});Delete
Call the destroy() method in Repository to perform the deletion operation. Filtering condition has to be specified to delete.
await userRepository.destroy({
filter: {
status: 'blocked',
},
});Constructor
It is usually not called directly by the developer, the instantiation is done mainly by specifying a corresponding repository type that is already registered in the parameter of db.colletion(). Repository type is registered through db.registerRepositories().
Signature
constructor(collection: Collection)
Example
import { Repository } from '@nocobase/database';
class MyRepository extends Repository {
async myQuery(sql) {
return this.database.sequelize.query(sql);
}
}
db.registerRepositories({
books: MyRepository,
});
db.collection({
name: 'books',
// here link to the registered repository
repository: 'books',
});
await db.sync();
const books = db.getRepository('books') as MyRepository;
await books.myQuery('SELECT * FROM books;');Instance Members
`database`
The database management instance where the context is located.
`collection`
The corresponding data table management instance.
`model`
The corresponding data model class.
Instance Methods
`find()`
Find datasets from the database with the specified filtering conditions and sorting, etc.
Signature
async find(options?: FindOptions): Promise<Model[]>
Type
type Filter = FilterWithOperator | FilterWithValue | FilterAnd | FilterOr;
type Appends = string[];
type Except = string[];
type Fields = string[];
type Sort = string[] | string;
interface SequelizeFindOptions {
limit?: number;
offset?: number;
}
interface FilterByTk {
filterByTk?: TargetKey;
}
interface CommonFindOptions extends Transactionable {
filter?: Filter;
fields?: Fields;
appends?: Appends;
except?: Except;
sort?: Sort;
}
type FindOptions = SequelizeFindOptions & CommonFindOptions & FilterByTk;Detailed Information
`filter: Filter`
Query conditions for filtering data results. In the query parameters that passed in, key is the name of the field, value is the corresponding value. Operators can be used in conjunction with other filtering conditions.
// Find records with name "foo" and age above 18
repository.find({
filter: {
name: 'foo',
age: {
$gt: 18,
},
},
});Refer to Operators for more information.
`filterByTk: TargetKey`
Query data by TargetKey, this is shortcut for the filter parameter. The field of TargetKey can be configured in Collection, the default is primaryKey.
// By default, find records with id 1
repository.find({
filterByTk: 1,
});`fields: string[]`
Query columns. It is used to control which data fields to output. With this parameter, only the specified fields will be returned.
`except: string[]`
Exclude columns. It is used to control which data fields to output. With this parameter, the specified fields will not be returned.
`appends: string[]`
Append columns. It is used to load associated data. With this parameter, the specified associated fields will be returned together.
`sort: string[] | string`
Specify the sorting method of the query results. The input parameter is the name of the field, by default is to sort in the ascending order (asc); a - symbol needs to be added before the field name to sort in the descending order (desc). For example, ['-id', 'name'] means to sort by id desc, name asc.
`limit: number`
Limit the number of results, same as limit in SQL.
`offset: number`
The offset of the query, same as offset in SQL.
Example
const posts = db.getRepository('posts');
const results = await posts.find({
filter: {
createdAt: {
$gt: '2022-01-01T00:00:00.000Z',
},
},
fields: ['title'],
appends: ['user'],
});`findOne()`
Find a single piece of data from the database for specific conditions. Equivalent to Model.findOne() in Sequelize.
Signature
async findOne(options?: FindOneOptions): Promise<Model | null>
Example
const posts = db.getRepository('posts');
const result = await posts.findOne({
filterByTk: 1,
});`count()`
Query a certain amount of data from the database for specific conditions. Equivalent to Model.count() in Sequelize.
Signature
count(options?: CountOptions): Promise<number>
Type
interface CountOptions
extends Omit<SequelizeCountOptions, 'distinct' | 'where' | 'include'>,
Transactionable {
filter?: Filter;
}Example
const books = db.getRepository('books');
const count = await books.count({
filter: {
title: 'Three character classic',
},
});`findAndCount()`
Find datasets from the database with the specified filtering conditions and return the number of results. Equivalent to Model.findAndCountAll() in Sequelize.
Signature
async findAndCount(options?: FindAndCountOptions): Promise<[Model[], number]>
Type
type FindAndCountOptions = Omit<
SequelizeAndCountOptions,
'where' | 'include' | 'order'
> &
CommonFindOptions;Detailed Information
The query parameters are the same as find(). An array is returned with the first element of the query results, and the second element of the total number of results.
`create()`
Inserts a newly created data into the data table. Equivalent to Model.create() in Sequelize. When the data object to be created carries any associated field, the corresponding associated data record is created or updated along with it.
Signature
async create<M extends Model>(options: CreateOptions): Promise<M>
Example
const posts = db.getRepository('posts');
const result = await posts.create({
values: {
title: 'NocoBase 1.0 Release Notes',
tags: [
// Update data when there is a primary key and value of the associated table
{ id: 1 },
// Create data when there is no primary key and value
{ name: 'NocoBase' },
],
},
});`createMany()`
Inserts multiple newly created data into the data table. This is equivalent to calling the create() method multiple times.
Signature
createMany(options: CreateManyOptions): Promise<Model[]>
Type
interface CreateManyOptions extends BulkCreateOptions {
records: Values[];
}Detailed Information
records: An array of data objects to be created.transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
const posts = db.getRepository('posts');
const results = await posts.createMany({
records: [
{
title: 'NocoBase 1.0 Release Notes',
tags: [
// Update data when there is a primary key and value of the associated table
{ id: 1 },
// Create data when there is no primary key and value
{ name: 'NocoBase' },
],
},
{
title: 'NocoBase 1.1 Release Notes',
tags: [{ id: 1 }],
},
],
});`update()`
Update data in the data table. Equivalent to Model.update() in Sequelize. When the data object to be updated carries any associated field, the corresponding associated data record is created or updated along with it.
Signature
async update<M extends Model>(options: UpdateOptions): Promise<M>
Example
const posts = db.getRepository('posts');
const result = await posts.update({
filterByTk: 1,
values: {
title: 'NocoBase 1.0 Release Notes',
tags: [
// Update data when there is a primary key and value of the associated table
{ id: 1 },
// Create data when there is no primary key and value
{ name: 'NocoBase' },
],
},
});`destroy()`
Delete data from the data table. Equivalent to Model.destroy() in Sequelize.
Signature
async destroy(options?: TargetKey | TargetKey[] | DestoryOptions): Promise<number>
Type
interface DestroyOptions extends SequelizeDestroyOptions {
filter?: Filter;
filterByTk?: TargetKey | TargetKey[];
truncate?: boolean;
context?: any;
}Detailed Information
filter๏ผSpecify the filtering conditions of the records to be deleted. Refer to thefind()method for the detailed usage of the filter.filterByTk๏ผSpecify the filtering conditions by TargetKey.truncate: Whether to empty the table data, this parameter is valid if nofilterorfilterByTkparameter is passed.transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared.md
Parameters
| Parameter Name | Type | Default | Description |
|---|---|---|---|
options.values |
M |
{} |
The data object to be inserted |
options.whitelist? |
string[] |
- | Whitelist for the values field; only fields in the list will be stored |
options.blacklist? |
string[] |
- | Blacklist for the values field; fields in the list will not be stored |
options.transaction? |
Transaction |
- | Transaction |
File: docs/en-US/api/database/interfaces/base-interface.md
BaseInterface
Overview
BaseInterface is the foundational class for all Interface types. Users can extend this class to implement custom Interface logic.
class CustomInterface extends BaseInterface {
async toValue(value: string, ctx?: any): Promise<any> {
// Custom toValue logic
}
toString(value: any, ctx?: any) {
// Custom toString logic
}
}
// Register Interface
db.interfaceManager.registerInterfaceType('customInterface', CustomInterface)Interfaces
toValue(value: string, ctx?: any): Promise
Converts an external string to the actual value of the interface, which can be directly passed to the Repository for write operations.
toString(value: any, ctx?: any)
Converts the actual value of the interface to a string type, which can be used for exporting or displaying purposes.
File: docs/en-US/api/database/relation-repository/belongs-to-many-repository.md
BelongsToManyRepository
BelongsToManyRepository is the Relation Repository for handling BelongsToMany relationships.
Unlike other relationship types, the BelongsToMany type of relationship needs to be recorded through an intermediate table. The intermediate table can be created automatically or explicitly specified when defining association relationships in NocoBase.
Class Methods
`find()`
Find associated objects.
Signature
async find(options?: FindOptions): Promise<M[]>
Detailed Information
Query parameters are the same as Repository.find().
`findOne()`
Find associated objects, only to return one record.
Signature
async findOne(options?: FindOneOptions): Promise<M>
`count()`
Return the number of records matching the query criteria.
Signature
async count(options?: CountOptions)
Type
interface CountOptions
extends Omit<SequelizeCountOptions, 'distinct' | 'where' | 'include'>,
Transactionable {
filter?: Filter;
}`findAndCount()`
Find datasets from the database with the specified filtering conditions and return the number of results.
Signature
async findAndCount(options?: FindAndCountOptions): Promise<[any[], number]>
Type
type FindAndCountOptions = CommonFindOptions;`create()`
Create associated objects.
Signature
async create(options?: CreateOptions): Promise<M>
`update()`
Update associated objects that match the conditions.
Signature
async update(options?: UpdateOptions): Promise<M>
`destroy()`
Delete associated objects.
Signature
async destroy(options?: TargetKey | TargetKey[] | DestroyOptions): Promise
`add()`
Add new associated objects.
Signature
async add( options: TargetKey | TargetKey[] | PrimaryKeyWithThroughValues | PrimaryKeyWithThroughValues[] | AssociatedOptions ): Promise<void>
Type
type PrimaryKeyWithThroughValues = [TargetKey, Values];
interface AssociatedOptions extends Transactionable {
tk?:
| TargetKey
| TargetKey[]
| PrimaryKeyWithThroughValues
| PrimaryKeyWithThroughValues[];
}Detailed Information
Pass the targetKey of the associated object directly, or pass the targetKey along with the field values of the intermediate table.
Example
const t1 = await Tag.repository.create({
values: { name: 't1' },
});
const t2 = await Tag.repository.create({
values: { name: 't2' },
});
const p1 = await Post.repository.create({
values: { title: 'p1' },
});
const PostTagRepository = new BelongsToManyRepository(Post, 'tags', p1.id);
// Pass in the targetKey
PostTagRepository.add([t1.id, t2.id]);
// Pass in intermediate table fields
PostTagRepository.add([
[t1.id, { tagged_at: '123' }],
[t2.id, { tagged_at: '456' }],
]);`set()`
Set the associated objects.
Signature
- async set(
options: TargetKey | TargetKey[] | PrimaryKeyWithThroughValues | PrimaryKeyWithThroughValues[] | AssociatedOptions,
): Promise
Detailed Information
Parameters are the same as add().
`remove()`
Remove the association with the given objects.
Signature
async remove(options: TargetKey | TargetKey[] | AssociatedOptions)
Type
interface AssociatedOptions extends Transactionable {
tk?: TargetKey | TargetKey[];
}`toggle()`
Toggle the associated object.
In some business scenarios, it is often needed to toggle the associated object. For example, user adds a product into collection, and the user cancels the collection and collect it again. Using the toggle method can quickly implement similar functions.
Signature
async toggle(options: TargetKey | { tk?: TargetKey; transaction?: Transaction }): Promise<void>
Detailed Information
The toggle method automatically checks whether the associated object already exists, and removes it if it does, or adds it if it does not.
File: docs/en-US/api/database/relation-repository/belongs-to-repository.md
BelongsToRepository
The interface is the same as HasOneRepository. BelongsToRepository is the Repository for handling BelongsTo relationships, and it provides some convenient methods to handle BelongsTo relationships.
File: docs/en-US/api/database/relation-repository/has-many-repository.md
HasManyRepository
HasManyRepository is the Relation Repository for handling HasMany relationships.
Class Methods
`find()`
Find associated objects.
Signature
async find(options?: FindOptions): Promise<M[]>
Detailed Information
Query parameters are the same as Repository.find().
`findOne()`
Find associated objects, only to return one record.
Signature
async findOne(options?: FindOneOptions): Promise<M>
`count()`
Return the number of records matching the query criteria.
Signature
async count(options?: CountOptions)
Type
interface CountOptions
extends Omit<SequelizeCountOptions, 'distinct' | 'where' | 'include'>,
Transactionable {
filter?: Filter;
}`findAndCount()`
Find datasets from the database with the specified filtering conditions and return the number of results.
Signature
async findAndCount(options?: FindAndCountOptions): Promise<[any[], number]>
Type
type FindAndCountOptions = CommonFindOptions;`create()`
Create associated objects.
Signature
async create(options?: CreateOptions): Promise<M>
`update()`
Update associated objects that match the conditions.
Signature
async update(options?: UpdateOptions): Promise<M>
`destroy()`
Delete associated objects.
Signature
async destroy(options?: TK | DestroyOptions): Promise<M>
`add()`
Add association relationships between objects.
Signature
async add(options: TargetKey | TargetKey[] | AssociatedOptions)
Type
interface AssociatedOptions extends Transactionable {
tk?: TargetKey | TargetKey[];
}Detailed Information
tk- The targetKey value of the associated object, either as a single value or an array.
`remove()`
Remove the association with the given objects.
Signature
async remove(options: TargetKey | TargetKey[] | AssociatedOptions)
Detailed Information
Same parameters as the add() method.
`set()`
Set the associated object of the current relationship.
Signature
async set(options: TargetKey | TargetKey[] | AssociatedOptions)
Detailed Information
Same parameters as the add() method.
File: docs/en-US/api/database/relation-repository/has-one-repository.md
HasOneRepository
Overview
HasOneRepository is the associated repository of type HasOne.
const User = db.collection({
name: 'users',
fields: [
{ type: 'hasOne', name: 'profile' },
{ type: 'string', name: 'name' },
],
});
const Profile = db.collection({
name: 'profiles',
fields: [{ type: 'string', name: 'avatar' }],
});
const user = await User.repository.create({
values: { name: 'u1' },
});
// Get the associated repository
const userProfileRepository = User.repository
.relation('profile')
.of(user.get('id'));
// Or to initialize directly
new HasOneRepository(User, 'profile', user.get('id'));Class Methods
`find()`
Find associated objects.
Signature
async find(options?: SingleRelationFindOption): Promise<Model<any> | null>
Type
interface SingleRelationFindOption extends Transactionable {
fields?: Fields;
except?: Except;
appends?: Appends;
filter?: Filter;
}Detailed Information
Query parameters are the same as Repository.find().
Example
const profile = await UserProfileRepository.find();
// Return null if the associated object does not exist`create()`
Create associated objects.
Signature
async create(options?: CreateOptions): Promise<Model>
Example
const profile = await UserProfileRepository.create({
values: { avatar: 'avatar1' },
});
console.log(profile.toJSON());
/*
{
id: 1,
avatar: 'avatar1',
userId: 1,
updatedAt: 2022-09-24T13:59:40.025Z,
createdAt: 2022-09-24T13:59:40.025Z
}
*/`update()`
Update associated objects.
Signature
async update(options: UpdateOptions): Promise<Model>
Example
const profile = await UserProfileRepository.update({
values: { avatar: 'avatar2' },
});
profile.get('avatar'); // 'avatar2'`remove()`
Remove associated objects. Only to unassociate, not to delete the associated object.
Signature
async remove(options?: Transactionable): Promise<void>
Detailed Information
transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
await UserProfileRepository.remove();
(await UserProfileRepository.find()) == null; // true
(await Profile.repository.count()) === 1; // true`destroy()`
Delete associated objects.
Signature
async destroy(options?: Transactionable): Promise
Detailed Information
transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
await UserProfileRepository.destroy();
(await UserProfileRepository.find()) == null; // true
(await Profile.repository.count()) === 0; // true`set()`
Set associated objects.
Signature
async set(options: TargetKey | SetOption): Promise<void>
Type
interface SetOption extends Transactionable {
tk?: TargetKey;
}Detailed Information
- tk: Set the targetKey of the associated object.
- transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
const newProfile = await Profile.repository.create({
values: { avatar: 'avatar2' },
});
await UserProfileRepository.set(newProfile.get('id'));
(await UserProfileRepository.find()).get('id') === newProfile.get('id'); // trueFile: docs/en-US/api/database/relation-repository/index.md
RelationRepository
RelationRepository is a Repository object for relation types, which allows operations on associated data without loading the associations. Based on RelationRepository, each association type derives its corresponding implementation, which are:
HasOneRepositoryHasManyRepositoryBelongsToRepositoryBelongsToManyRepository
Constructor
Signature
constructor(sourceCollection: Collection, association: string, sourceKeyValue: string | number)
Parameters
| Parameter Name | Type | Default Value | Description |
|---|---|---|---|
sourceCollection |
Collection |
- | The Collection corresponding to the referencing relation in the association |
association |
string |
- | The name of the association |
sourceKeyValue |
string | number |
- | The key value corresponding to the referencing relation |
Base Class Properties
`db: Database`
Database object
`sourceCollection`
The Collection corresponding to the referencing relation in the association
`targetCollection`
The Collection corresponding to the referenced relation in the association
`association`
The association object in Sequelize corresponding to the current association
`associationField`
The field in the Collection corresponding to the current association
`sourceKeyValue`
The key value corresponding to the referencing relation
File: docs/en-US/api/database/shared/create-options.md
Type
type WhiteList = string[];
type BlackList = string[];
type AssociationKeysToBeUpdate = string[];
interface CreateOptions extends SequelizeCreateOptions {
values?: Values;
whitelist?: WhiteList;
blacklist?: BlackList;
updateAssociationValues?: AssociationKeysToBeUpdate;
context?: any;
}Details
values: The data object of the record to be created.whitelist: Specifies which fields in the data object of the record to be created can be written. If this parameter is not passed, all fields are allowed to be written by default.blacklist: Specifies which fields in the data object of the record to be created are not allowed to be written. If this parameter is not passed, all fields are allowed to be written by default.transaction: The transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared/destroy-options.md
Type
interface DestroyOptions extends SequelizeDestroyOptions {
filter?: Filter;
filterByTk?: TargetKey | TargetKey[];
truncate?: boolean;
context?: any;
}Details
filter: Specifies the filtering conditions for the records to be deleted. For detailed usage of Filter, refer to thefind()method.filterByTk: Specifies the filtering conditions for the records to be deleted by TargetKey.truncate: Whether to truncate the table data, effective when nofilterorfilterByTkparameters are passed.transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared/find-one.md
Type
type FindOneOptions = Omit<FindOptions, 'limit'>;Parameters
Most parameters are the same as those in find(). The difference is that findOne() returns only a single piece of data, so the limit parameter is not needed, and the query is always set to 1.
File: docs/en-US/api/database/shared/find-options.md
[Empty file]
File: docs/en-US/api/database/shared/transaction.md
transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared/update-options.md
Type
interface UpdateOptions extends Omit<SequelizeUpdateOptions, 'where'> {
values: Values;
filter?: Filter;
filterByTk?: TargetKey;
whitelist?: WhiteList;
blacklist?: BlackList;
updateAssociationValues?: AssociationKeysToBeUpdate;
context?: any;
}Details
values: The data object of the records to be updated.filter: Specifies the filter conditions for the records to be updated. For detailed usage of Filter, refer to thefind()method.filterByTk: Specifies the filter conditions for the records to be updated by TargetKey.whitelist: A whitelist for thevaluesfields. Only fields listed will be written.blacklist: A blacklist for thevaluesfields. Fields listed will not be written.transaction: The transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
At least one of filterByTk or filter must be provided.
File: docs/en-US/api/field/markdown-vditor/index.md
markdown
Example
This is an embedded Markdown editor:
File: docs/en-US/api/handlebars-helpers/array.md
Array
{{after}}
Returns all of the items in an array after the specified index. Opposite of before.
Params
array{Array}: Collectionn{Number}: Starting index (number of items to exclude)returns{Array}: Array exludingnitems.
Example
<!-- array: ['a', 'b', 'c'] -->
{{after array 1}}
<!-- results in: '["c"]' -->{{arrayify}}
Cast the given value to an array.
Params
value{any}returns{Array}
Example
{{arrayify "foo"}}
<!-- results in: [ "foo" ] -->{{before}}
Return all of the items in the collection before the specified count. Opposite of after.
Params
array{Array}n{Number}returns{Array}: Array excluding items after the given number.
Example
<!-- array: ['a', 'b', 'c'] -->
{{before array 2}}
<!-- results in: '["a", "b"]' -->{{eachIndex}}
Params
array{Array}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] -->
{{#eachIndex array}}
{{item}} is {{index}}
{{/eachIndex}}{{filter}}
Block helper that filters the given array and renders the block for values that evaluate to true, otherwise the inverse block is returned.
Params
array{Array}value{any}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#filter array "foo"}}AAA{{else}}BBB{{/filter}}
<!-- results in: 'BBB' -->{{first}}
Returns the first item, or first n items of an array.
Params
array{Array}n{Number}: Number of items to return, starting at0.returns{Array}
Example
{{first "['a', 'b', 'c', 'd', 'e']" 2}}
<!-- results in: '["a", "b"]' -->{{forEach}}
Iterates over each item in an array and exposes the current item in the array as context to the inner block. In addition to the current array item, the helper exposes the following variables to the inner block:
indextotalisFirstisLast
Also,@indexis exposed as a private variable, and additional
private variables may be defined as hash arguments.
Params
array{Array}returns{String}
Example
<!-- accounts = [
{'name': 'John', 'email': '[email protected]'},
{'name': 'Malcolm', 'email': '[email protected]'},
{'name': 'David', 'email': '[email protected]'}
] -->
{{#forEach accounts}}
<a href="mailto:{{ email }}" title="Send an email to {{ name }}">
{{ name }}
</a>{{#unless isLast}}, {{/unless}}
{{/forEach}}{{inArray}}
Block helper that renders the block if an array has the given value. Optionally specify an inverse block to render when the array does not have the given value.
Params
array{Array}value{any}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#inArray array "d"}}
foo
{{else}}
bar
{{/inArray}}
<!-- results in: 'bar' -->{{isArray}}
Returns true if value is an es5 array.
Params
value{any}: The value to test.returns{Boolean}
Example
{{isArray "abc"}}
<!-- results in: false -->
<!-- array: [1, 2, 3] -->
{{isArray array}}
<!-- results in: true -->{{itemAt}}
Returns the item from array at index idx.
Params
array{Array}idx{Number}returns{any}value
Example
<!-- array: ['a', 'b', 'c'] -->
{{itemAt array 1}}
<!-- results in: 'b' -->{{join}}
Join all elements of array into a string, optionally using a given separator.
Params
array{Array}separator{String}: The separator to use. Defaults to,.returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{join array}}
<!-- results in: 'a, b, c' -->
{{join array '-'}}
<!-- results in: 'a-b-c' -->{{equalsLength}}
Returns true if the the length of the given value is equal
to the given length. Can be used as a block or inline helper.
Params
value{Array|String}length{Number}options{Object}returns{String}
{{last}}
Returns the last item, or last n items of an array or string. Opposite of first.
Params
value{Array|String}: Array or string.n{Number}: Number of items to return from the end of the array.returns{Array}
Example
<!-- var value = ['a', 'b', 'c', 'd', 'e'] -->
{{last value}}
<!-- results in: ['e'] -->
{{last value 2}}
<!-- results in: ['d', 'e'] -->
{{last value 3}}
<!-- results in: ['c', 'd', 'e'] -->{{length}}
Returns the length of the given string or array.
Params
value{Array|Object|String}returns{Number}: The length of the value.
Example
{{length '["a", "b", "c"]'}}
<!-- results in: 3 -->
<!-- results in: myArray = ['a', 'b', 'c', 'd', 'e']; -->
{{length myArray}}
<!-- results in: 5 -->
<!-- results in: myObject = {'a': 'a', 'b': 'b'}; -->
{{length myObject}}
<!-- results in: 2 -->{{lengthEqual}}
Alias for equalsLength
{{map}}
Returns a new array, created by calling function on each element of the given array. For example,
Params
array{Array}fn{Function}returns{String}
Example
<!-- array: ['a', 'b', 'c'], and "double" is a
fictitious function that duplicates letters -->
{{map array double}}
<!-- results in: '["aa", "bb", "cc"]' -->{{pluck}}
Map over the given object or array or objects and create an array of values from the given prop. Dot-notation may be used (as a string) to get nested properties.
Params
collection{Array|Object}prop{Function}returns{String}
Example
// {{pluck items "data.title"}}
<!-- results in: '["aa", "bb", "cc"]' -->{{reverse}}
Reverse the elements in an array, or the characters in a string.
Params
value{Array|String}returns{Array|String}: Returns the reversed string or array.
Example
<!-- value: 'abcd' -->
{{reverse value}}
<!-- results in: 'dcba' -->
<!-- value: ['a', 'b', 'c', 'd'] -->
{{reverse value}}
<!-- results in: ['d', 'c', 'b', 'a'] -->{{some}}
Block helper that returns the block if the callback returns true for some value in the given array.
Params
array{Array}iter{Function}: Iteratee- {Options}: Handlebars provided options object
returns{String}
Example
<!-- array: [1, 'b', 3] -->
{{#some array isString}}
Render me if the array has a string.
{{else}}
Render me if it doesn't.
{{/some}}
<!-- results in: 'Render me if the array has a string.' -->{{sort}}
Sort the given array. If an array of objects is passed, you may optionally pass a key to sort on as the second argument. You may alternatively pass a sorting function as the second argument.
Params
array{Array}: the array to sort.key{String|Function}: The object key to sort by, or sorting function.
Example
<!-- array: ['b', 'a', 'c'] -->
{{sort array}}
<!-- results in: '["a", "b", "c"]' -->{{sortBy}}
Sort an array. If an array of objects is passed, you may optionally pass a key to sort on as the second argument. You may alternatively pass a sorting function as the second argument.
Params
array{Array}: the array to sort.props{String|Function}: One or more properties to sort by, or sorting functions to use.
Example
<!-- array: [{a: 'zzz'}, {a: 'aaa'}] -->
{{sortBy array "a"}}
<!-- results in: '[{"a":"aaa"}, {"a":"zzz"}]' -->{{withAfter}}
Use the items in the array after the specified index as context inside a block. Opposite of withBefore.
Params
array{Array}idx{Number}options{Object}returns{Array}
Example
<!-- array: ['a', 'b', 'c', 'd', 'e'] -->
{{#withAfter array 3}}
{{this}}
{{/withAfter}}
<!-- results in: "de" -->{{withBefore}}
Use the items in the array before the specified index as context inside a block. Opposite of withAfter.
Params
array{Array}idx{Number}options{Object}returns{Array}
Example
<!-- array: ['a', 'b', 'c', 'd', 'e'] -->
{{#withBefore array 3}}
{{this}}
{{/withBefore}}
<!-- results in: 'ab' -->{{withFirst}}
Use the first item in a collection inside a handlebars block expression. Opposite of withLast.
Params
array{Array}idx{Number}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#withFirst array}}
{{this}}
{{/withFirst}}
<!-- results in: 'a' -->{{withGroup}}
Block helper that groups array elements by given group size.
Params
array{Array}: The array to iterate oversize{Number}: The desired length of each array "group"options{Object}: Handlebars optionsreturns{String}
Example
<!-- array: ['a','b','c','d','e','f','g','h'] -->
{{#withGroup array 4}}
{{#each this}}
{{.}}
{{each}}
<br>
{{/withGroup}}
<!-- results in: -->
<!-- 'a','b','c','d'<br> -->
<!-- 'e','f','g','h'<br> -->{{withLast}}
Use the last item or n items in an array as context inside a block. Opposite of withFirst.
Params
array{Array}idx{Number}: The starting index.options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#withLast array}}
{{this}}
{{/withLast}}
<!-- results in: 'c' -->{{withSort}}
Block helper that sorts a collection and exposes the sorted collection as context inside the block.
Params
array{Array}prop{String}options{Object}: Specifyreverse="true"to reverse the array.returns{String}
Example
<!-- array: ['b', 'a', 'c'] -->
{{#withSort array}}{{this}}{{/withSort}}
<!-- results in: 'abc' -->{{unique}}
Block helper that return an array with all duplicate values removed. Best used along with a each helper.
Params
array{Array}options{Object}returns{Array}
Example
<!-- array: ['a', 'a', 'c', 'b', 'e', 'e'] -->
{{#each (unique array)}}{{.}}{{/each}}
<!-- results in: 'acbe' -->File: docs/en-US/api/handlebars-helpers/comparison.md
Comparison
{{and}}
Helper that renders the block if both of the given values are truthy. If an inverse block is specified it will be rendered when falsy. Works as a block helper, inline helper or subexpression.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}
Example
<!-- {great: true, magnificent: true} -->
{{#and great magnificent}}A{{else}}B{{/and}}
<!-- results in: 'A' -->{{compare}}
Render a block when a comparison of the first and third
arguments returns true. The second argument is
the arithemetic operator to use. You may also
optionally specify an inverse block to render when falsy.
Params
a{}operator{}: The operator to use. Operators must be enclosed in quotes:">","=","<=", and so on.b{}options{Object}: Handlebars provided options objectreturns{String}: Block, or if specified the inverse block is rendered if falsey.
{{contains}}
Block helper that renders the block if collection has the given value, using strict equality (===) for comparison, otherwise the inverse block is rendered (if specified). If a startIndex is specified and is negative, it is used as the offset from the end of the collection.
Params
collection{Array|Object|String}: The collection to iterate over.value{any}: The value to check for.[startIndex=0]{Number}: Optionally define the starting index.options{Object}: Handlebars provided options object.
Example
<!-- array = ['a', 'b', 'c'] -->
{{#contains array "d"}}
This will not be rendered.
{{else}}
This will be rendered.
{{/contains}}{{default}}
Returns the first value that is not undefined, otherwise the "default" value is returned.
Params
value{any}defaultValue{any}returns{String}
{{eq}}
Block helper that renders a block if a is equal to b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{gt}}
Block helper that renders a block if a is greater than b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{gte}}
Block helper that renders a block if a is greater than or equal to b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{has}}
Block helper that renders a block if value has pattern.
If an inverse block is specified it will be rendered when falsy.
Params
val{any}: The value to check.pattern{any}: The pattern to check for.options{Object}: Handlebars provided options objectreturns{String}
{{isEmpty}}
Inline, subexpression, or block helper that returns true (or the block) if the given collection is empty, or false (or the inverse block, if supplied) if the colleciton is not empty.
Params
collection{Object}options{Object}returns{String}
Example
<!-- array: [] -->
{{#isEmpty array}}AAA{{else}}BBB{{/isEmpty}}
<!-- results in: 'AAA' -->
<!-- array: [] -->
{{isEmpty array}}
<!-- results in: true -->{{isFalsey}}
Returns true if the given value is falsey. Uses the falsey
library for comparisons. Please see that library for more information
or to report bugs with this helper.
Params
val{any}options{Options}returns{Boolean}
{{isTruthy}}
Returns true if the given value is truthy. Uses the falsey
library for comparisons. Please see that library for more information
or to report bugs with this helper.
Params
val{any}options{Options}returns{Boolean}
{{ifEven}}
Return true if the given value is an even number.
Params
number{Number}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
Example
{{#ifEven value}}
render A
{{else}}
render B
{{/ifEven}}{{ifNth}}
Conditionally renders a block if the remainder is zero whena operand is divided by b. If an inverse block is specified
it will be rendered when the remainder is not zero.
Params
- {}: {Number}
- {}: {Number}
options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{ifOdd}}
Block helper that renders a block if value is an odd number. If an inverse block is specified it will be rendered when falsy.
Params
value{Object}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
Example
{{#ifOdd value}}
render A
{{else}}
render B
{{/ifOdd}}{{is}}
Block helper that renders a block if a is equal to b.
If an inverse block is specified it will be rendered when falsy.
Similar to eq but does not do strict equality.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}
{{isnt}}
Block helper that renders a block if a is not equal to b.
If an inverse block is specified it will be rendered when falsy.
Similar to unlessEq but does not use strict equality for
comparisons.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}
{{lt}}
Block helper that renders a block if a is less than b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
context{Object}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{lte}}
Block helper that renders a block if a is less than or equal to b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{Sring}b{Sring}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{neither}}
Block helper that renders a block if neither of the given values
are truthy. If an inverse block is specified it will be rendered
when falsy.
Params
a{any}b{any}options{}: Handlebars options objectreturns{String}: Block, or inverse block if specified and falsey.
{{not}}
Returns true if val is falsey. Works as a block or inline helper.
Params
val{String}options{Object}: Handlebars provided options objectreturns{String}
{{or}}
Block helper that renders a block if any of the given values is truthy. If an inverse block is specified it will be rendered when falsy.
Params
arguments{...any}: Variable number of argumentsoptions{Object}: Handlebars options objectreturns{String}: Block, or inverse block if specified and falsey.
Example
{{#or a b c}}
If any value is true this will be rendered.
{{/or}}{{unlessEq}}
Block helper that always renders the inverse block unless a is
is equal to b.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Inverse block by default, or block if falsey.
{{unlessGt}}
Block helper that always renders the inverse block unless a is
is greater than b.
Params
a{Object}: The default valueb{Object}: The value to compareoptions{Object}: Handlebars provided options objectreturns{String}: Inverse block by default, or block if falsey.
{{unlessLt}}
Block helper that always renders the inverse block unless a is
is less than b.
Params
a{Object}: The default valueb{Object}: The value to compareoptions{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{unlessGteq}}
Block helper that always renders the inverse block unless a is
is greater than or equal to b.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{unlessLteq}}
Block helper that always renders the inverse block unless a is
is less than or equal to b.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
File: docs/en-US/api/handlebars-helpers/core.md
Built-in Helpers
https://handlebarsjs.com/guide/builtin-helpers.html
{{if}}
Renders a block if the given condition is truthy.
Params
condition{Any}: The condition to evaluate.
Returns: The content inside the block if the condition is truthy, otherwise returns nothing.
Example
{{#if condition}}
This will be displayed if the condition is true.
{{/if}}{{unless}}
Renders a block if the given condition is falsy. This is the opposite of if.
Params
condition{Any}: The condition to evaluate.
Returns: The content inside the block if the condition is falsy, otherwise returns nothing.
Example
{{#unless condition}}
This will be displayed if the condition is false.
{{/unless}}{{each}}
Iterates over an array or object and renders a block for each item.
Params
collection{Array|Object}: The array or object to iterate over.
Returns: Renders the block for each item in the collection.
Example
{{#each items}}
<li>{{this}}</li>
{{/each}}{{with}}
Renders a block with a given context. It allows you to specify a context for the block, simplifying access to deeply nested properties.
Params
context{Any}: The context to use within the block.
Returns: Renders the block with the provided context.
Example
{{#with person}}
<p>Name: {{name}}</p>
<p>Age: {{age}}</p>
{{/with}}{{lookup}}
Looks up the value of a specified key in an object. This helper is useful for accessing dynamic keys.
Params
context{Object}: The object to look up the key from.key{String|Number}: The key to look up.
Returns: The value of the specified key in the object.
Example
{{lookup person "name"}}
<!-- If person is { name: "Alice", age: 30 }, it results in: "Alice" -->File: docs/en-US/api/handlebars-helpers/date.md
Date
{{dateFormat}}
The "dateFormat" helper in Handlebars is used to format a date using the day.js library. It takes two required arguments and an optional third argument for the timezone.
Params
datetime{String}format{String}timezone{String}returns{String}
Example
{{dateFormat now "YYYY-MM-DD HH:mm:ss"}}
{{dateFormat now "YYYY-MM-DD HH:mm:ss" "Asia/Tokyo"}}
{{dateFormat now "YYYY-MM-DD HH:mm:ss" "UTC"}}File: docs/en-US/api/handlebars-helpers/html.md
HTML
{{qrcode}}
File: docs/en-US/api/handlebars-helpers/i18n.md
I18n
{{t}}
Params
key{String}ns{String}returns{String}
Example
{{t "Today"}}
{{t "Permissions" "@nocobase/plugin-acl"}}File: docs/en-US/api/handlebars-helpers/index.md
Handlebars Helpers
| Category | Description |
|---|---|
| Core | Built-in helpers |
| Array | Operations and methods related to arrays |
| Comparison | Comparison operators and related methods |
| Date | Operations and methods related to date and time handling |
| HTML | Content related to HTML documents and elements |
| I18n | Support for internationalization and multilingual handling |
| Math | Mathematical functions and calculations |
| Number | Content related to number handling and formatting |
| Object | Methods related to object operations and properties |
| Path | Path operations and content related to the file system |
| Regex | Regular expressions and their usage |
| String | Methods related to string manipulation and operations |
| URL | Content related to URL parsing and construction |
File: docs/en-US/api/handlebars-helpers/math.md
Math
{{abs}}
Return the magnitude of a.
Params
a{Number}returns{Number}
{{add}}
Return the sum of a plus b.
Params
a{Number}b{Number}returns{Number}
{{avg}}
Returns the average of all numbers in the given array.
Params
array{Array}: Array of numbers to add up.returns{Number}
Example
{{avg "[1, 2, 3, 4, 5]"}}
<!-- results in: '3' -->{{ceil}}
Get the Math.ceil() of the given value.
Params
value{Number}returns{Number}
{{divide}}
Divide a by b
Params
a{Number}: numeratorb{Number}: denominator
{{floor}}
Get the Math.floor() of the given value.
Params
value{Number}returns{Number}
{{minus}}
Return the difference of a minus b.
Params
a{Number}b{Number}
{{modulo}}
Get the remainder of a division operation.
Params
a{Number}b{Number}returns{Number}
{{multiply}}
Return the product of a times b.
Params
a{Number}: factorb{Number}: multiplierreturns{Number}
{{plus}}
Add a by b.
Params
a{Number}: factorb{Number}: multiplier
{{random}}
Generate a random number between two values
Params
min{Number}max{Number}returns{String}
{{remainder}}
Get the remainder when a is divided by b.
Params
a{Number}: ab{Number}: b
{{round}}
Round the given number.
Params
number{Number}returns{Number}
{{subtract}}
Return the product of a minus b.
Params
a{Number}b{Number}returns{Number}
{{sum}}
Returns the sum of all numbers in the given array.
Params
array{Array}: Array of numbers to add up.returns{Number}
Example
{{sum "[1, 2, 3, 4, 5]"}}
<!-- results in: '15' -->{{times}}
Multiply number a by number b.
Params
a{Number}: factorb{Number}: multiplierreturns{Number}
File: docs/en-US/api/handlebars-helpers/number.md
Number
{{bytes}}
Format a number to it's equivalent in bytes. If a string is passed, it's length will be formatted and returned.
Examples:
'foo' => 3 B13661855 => 13.66 MB825399 => 825.39 kB1396 => 1.4 kB
Params
number{Number|String}returns{String}
{{addCommas}}
Add commas to numbers
Params
num{Number}returns{Number}
{{phoneNumber}}
Convert a string or number to a formatted phone number.
Params
num{Number|String}: The phone number to format, e.g.8005551212returns{Number}: Formatted phone number:(800) 555-1212
{{toAbbr}}
Abbreviate numbers to the given number of precision. This is for
general numbers, not size in bytes.
Params
number{Number}precision{Number}returns{String}
{{toExponential}}
Returns a string representing the given number in exponential notation.
Params
number{Number}fractionDigits{Number}: Optional. An integer specifying the number of digits to use after the decimal point. Defaults to as many digits as necessary to specify the number.returns{Number}
Example
{{toExponential number digits}};{{toFixed}}
Formats the given number using fixed-point notation.
Params
number{Number}digits{Number}: (Optional) The number of digits to appear after the decimal point; this may be a value between 0 and 20. If this argument is omitted, it is treated as 0.returns{String}: A string representing the given number using fixed-point notation.
Example
{{toFixed "1.1234" 2}}
//=> '1.12'{{toFloat}}
Params
number{Number}returns{Number}
{{toInt}}
Params
number{Number}returns{Number}
{{toPrecision}}
Returns a string representing the Number object to the specified precision.
Params
number{Number}precision{Number}: (Optional) An integer specifying the number of significant digits. If precison is not between 1 and 100 (inclusive), it will be coerced to0.returns{String}: A string representing a Number object in fixed-point or exponential notation rounded to precision significant digits.
Example
{{toPrecision "1.1234" 2}}
//=> '1.1'File: docs/en-US/api/handlebars-helpers/object.md
Object
{{extend}}
Extend the context with the properties of other objects.
A shallow merge is performed to avoid mutating the context.
Params
objects{Object}: One or more objects to extend.returns{Object}
{{forIn}}
Block helper that iterates over the properties of
an object, exposing each key and value on the context.
Params
context{Object}options{Object}returns{String}
{{forOwn}}
Block helper that iterates over the own properties of
an object, exposing each key and value on the context.
Params
obj{Object}: The object to iterate over.options{Object}returns{String}
{{toPath}}
Take arguments and, if they are string or number, convert them to a dot-delineated object property path.
Params
prop{String|Number}: The property segments to assemble (can be multiple).returns{String}
{{get}}
Use property paths (a.b.c) to get a value or nested value from
the context. Works as a regular helper or block helper.
Params
prop{String}: The property to get, optionally using dot notation for nested properties.context{Object}: The context objectoptions{Object}: The handlebars options object, if used as a block helper.returns{String}
{{getObject}}
Use property paths (a.b.c) to get an object from
the context. Differs from the get helper in that this
helper will return the actual object, including the
given property key. Also, this helper does not work as a
block helper.
Params
prop{String}: The property to get, optionally using dot notation for nested properties.context{Object}: The context objectreturns{String}
{{hasOwn}}
Return true if key is an own, enumerable property of the given context object.
Params
key{String}context{Object}: The context object.returns{Boolean}
Example
{{hasOwn context key}}{{isObject}}
Return true if value is an object.
Params
value{String}returns{Boolean}
Example
{{isObject "foo"}}
//=> false{{JSONparse}}
Parses the given string using JSON.parse.
Params
string{String}: The string to parse
Example
<!-- string: '{"foo": "bar"}' -->
{{JSONparse string}}
<!-- results in: { foo: 'bar' } -->{{JSONstringify}}
Stringify an object using JSON.stringify.
Params
obj{Object}: Object to stringifyreturns{String}
Example
<!-- object: { foo: 'bar' } -->
{{JSONstringify object}}
<!-- results in: '{"foo": "bar"}' -->{{merge}}
Deeply merge the properties of the given objects with the
context object.
Params
object{Object}: The target object. Pass an empty object to shallow clone.objects{Object}returns{Object}
{{pick}}
Pick properties from the context object.
Params
properties{Array|String}: One or more properties to pick.context{Object}options{Object}: Handlebars options object.returns{Object}: Returns an object with the picked values. If used as a block helper, the values are passed as context to the inner block. If no values are found, the context is passed to the inverse block.
File: docs/en-US/api/handlebars-helpers/path.md
Path
{{absolute}}
Get the directory path segment from the given filepath.
Params
ext{String}returns{String}
Example
{{absolute "docs/toc.md"}}
<!-- results in: 'docs' -->{{dirname}}
Get the directory path segment from the given filepath.
Params
ext{String}returns{String}
Example
{{dirname "docs/toc.md"}}
<!-- results in: 'docs' -->{{relative}}
Get the relative filepath from a to b.
Params
a{String}b{String}returns{String}
Example
{{relative a b}}{{basename}}
Get the file extension from the given filepath.
Params
ext{String}returns{String}
Example
{{basename "docs/toc.md"}}
<!-- results in: 'toc.md' -->{{stem}}
Get the "stem" from the given filepath.
Params
filepath{String}returns{String}
Example
{{stem "docs/toc.md"}}
<!-- results in: 'toc' -->{{extname}}
Get the file extension from the given filepath.
Params
filepath{String}returns{String}
Example
{{extname "docs/toc.md"}}
<!-- results in: '.md' -->{{resolve}}
Resolve an absolute path from the given filepath.
Params
filepath{String}returns{String}
Example
{{resolve "docs/toc.md"}}
<!-- results in: '/User/dev/docs/toc.md' -->{{segments}}
Get specific (joined) segments of a file path by passing a range of array indices.
Params
filepath{String}: The file path to split into segments.returns{String}: Returns a single, joined file path.
Example
{{segments "a/b/c/d" "2" "3"}}
<!-- results in: 'c/d' -->
{{segments "a/b/c/d" "1" "3"}}
<!-- results in: 'b/c/d' -->
{{segments "a/b/c/d" "1" "2"}}
<!-- results in: 'b/c' -->File: docs/en-US/api/handlebars-helpers/regex.md
Regex
{{toRegex}}
Convert the given string to a regular expression.
Params
str{String}returns{RegExp}
Example
{{toRegex "foo"}}
<!-- results in: /foo/ -->{{test}}
Returns true if the given str matches the given regex. A regex can be passed on the context, or using the toRegex helper as a subexpression.
Params
str{String}returns{RegExp}
Example
{{test "bar" (toRegex "foo")}}
<!-- results in: false -->
{{test "foobar" (toRegex "foo")}}
<!-- results in: true -->
{{test "foobar" (toRegex "^foo$")}}
<!-- results in: false -->File: docs/en-US/api/handlebars-helpers/string.md
String
{{append}}
Append the specified suffix to the given string.
Params
str{String}suffix{String}returns{String}
Example
<!-- given that "item.stem" is "foo" -->
{{append item.stem ".html"}}
<!-- results in: 'foo.html' -->{{camelcase}}
camelCase the characters in the given string.
Params
string{String}: The string to camelcase.returns{String}
Example
{{camelcase "foo bar baz"}};
<!-- results in: 'fooBarBaz' -->{{capitalize}}
Capitalize the first word in a sentence.
Params
str{String}returns{String}
Example
{{capitalize "foo bar baz"}}
<!-- results in: "Foo bar baz" -->{{capitalizeAll}}
Capitalize all words in a string.
Params
str{String}returns{String}
Example
{{capitalizeAll "foo bar baz"}}
<!-- results in: "Foo Bar Baz" -->{{center}}
Center a string using non-breaking spaces
Params
str{String}spaces{String}returns{String}
{{chop}}
Like trim, but removes both extraneous whitespace and non-word characters from the beginning and end of a string.
Params
string{String}: The string to chop.returns{String}
Example
{{chop "_ABC_"}}
<!-- results in: 'ABC' -->
{{chop "-ABC-"}}
<!-- results in: 'ABC' -->
{{chop " ABC "}}
<!-- results in: 'ABC' -->{{dashcase}}
dash-case the characters in string. Replaces non-word characters and periods with hyphens.
Params
string{String}returns{String}
Example
{{dashcase "a-b-c d_e"}}
<!-- results in: 'a-b-c-d-e' -->{{dotcase}}
dot.case the characters in string.
Params
string{String}returns{String}
Example
{{dotcase "a-b-c d_e"}}
<!-- results in: 'a.b.c.d.e' -->{{downcase}}
Lowercase all of the characters in the given string. Alias for lowercase.
Params
string{String}returns{String}
Example
{{downcase "aBcDeF"}}
<!-- results in: 'abcdef' -->{{ellipsis}}
Truncates a string to the specified length, and appends it with an elipsis, โฆ.
Params
str{String}length{Number}: The desired length of the returned string.returns{String}: The truncated string.
Example
{{ellipsis (sanitize "<span>foo bar baz</span>"), 7}}
<!-- results in: 'foo barโฆ' -->
{{ellipsis "foo bar baz", 7}}
<!-- results in: 'foo barโฆ' -->{{hyphenate}}
Replace spaces in a string with hyphens.
Params
str{String}returns{String}
Example
{{hyphenate "foo bar baz qux"}}
<!-- results in: "foo-bar-baz-qux" -->{{isString}}
Return true if value is a string.
Params
value{String}returns{Boolean}
Example
{{isString "foo"}}
<!-- results in: 'true' -->{{lowercase}}
Lowercase all characters in the given string.
Params
str{String}returns{String}
Example
{{lowercase "Foo BAR baZ"}}
<!-- results in: 'foo bar baz' -->{{occurrences}}
Return the number of occurrences of substring within the given string.
Params
str{String}substring{String}returns{Number}: Number of occurrences
Example
{{occurrences "foo bar foo bar baz" "foo"}}
<!-- results in: 2 -->{{pascalcase}}
PascalCase the characters in string.
Params
string{String}returns{String}
Example
{{pascalcase "foo bar baz"}}
<!-- results in: 'FooBarBaz' -->{{pathcase}}
path/case the characters in string.
Params
string{String}returns{String}
Example
{{pathcase "a-b-c d_e"}}
<!-- results in: 'a/b/c/d/e' -->{{plusify}}
Replace spaces in the given string with pluses.
Params
str{String}: The input stringreturns{String}: Input string with spaces replaced by plus signs
Example
{{plusify "foo bar baz"}}
<!-- results in: 'foo+bar+baz' -->{{prepend}}
Prepends the given string with the specified prefix.
Params
str{String}prefix{String}returns{String}
Example
<!-- given that "val" is "bar" -->
{{prepend val "foo-"}}
<!-- results in: 'foo-bar' -->{{raw}}
Render a block without processing mustache templates inside the block.
Params
options{Object}returns{String}
Example
{{{{#raw}}}}
{{foo}}
{{{{/raw}}}}
<!-- results in: '{{foo}}' -->{{remove}}
Remove all occurrences of substring from the given str.
Params
str{String}substring{String}returns{String}
Example
{{remove "a b a b a b" "a "}}
<!-- results in: 'b b b' -->{{removeFirst}}
Remove the first occurrence of substring from the given str.
Params
str{String}substring{String}returns{String}
Example
{{remove "a b a b a b" "a"}}
<!-- results in: ' b a b a b' -->{{replace}}
Replace all occurrences of substring a with substring b.
Params
str{String}a{String}b{String}returns{String}
Example
{{replace "a b a b a b" "a" "z"}}
<!-- results in: 'z b z b z b' -->{{replaceFirst}}
Replace the first occurrence of substring a with substring b.
Params
str{String}a{String}b{String}returns{String}
Example
{{replace "a b a b a b" "a" "z"}}
<!-- results in: 'z b a b a b' -->{{reverse}}
Reverse a string.
Params
str{String}returns{String}
Example
{{reverse "abcde"}}
<!-- results in: 'edcba' -->{{sentence}}
Sentence case the given string
Params
str{String}returns{String}
Example
{{sentence "hello world. goodbye world."}}
<!-- results in: 'Hello world. Goodbye world.' -->{{snakecase}}
snake_case the characters in the given string.
Params
string{String}returns{String}
Example
{{snakecase "a-b-c d_e"}}
<!-- results in: 'a_b_c_d_e' -->{{split}}
Split string by the given character.
Params
string{String}: The string to split.returns{String}character: Default is an empty string.
Example
{{split "a,b,c" ","}}
<!-- results in: ['a', 'b', 'c'] -->{{startsWith}}
Tests whether a string begins with the given prefix.
Params
prefix{String}testString{String}options{String}returns{String}
Example
{{#startsWith "Goodbye" "Hello, world!"}}
Whoops
{{else}}
Bro, do you even hello world?
{{/startsWith}}{{titleize}}
Title case the given string.
Params
str{String}returns{String}
Example
{{titleize "this is title case"}}
<!-- results in: 'This Is Title Case' -->{{trim}}
Removes extraneous whitespace from the beginning and end of a string.
Params
string{String}: The string to trim.returns{String}
Example
{{trim " ABC "}}
<!-- results in: 'ABC' -->{{trimLeft}}
Removes extraneous whitespace from the beginning of a string.
Params
string{String}: The string to trim.returns{String}
Example
{{trim " ABC "}}
<!-- results in: 'ABC ' -->{{trimRight}}
Removes extraneous whitespace from the end of a string.
Params
string{String}: The string to trim.returns{String}
Example
{{trimRight " ABC "}}
<!-- results in: ' ABC' -->{{truncate}}
Truncate a string to the specified length. Also see ellipsis.
Params
str{String}limit{Number}: The desired length of the returned string.suffix{String}: Optionally supply a string to use as a suffix to denote when the string has been truncated. Otherwise an ellipsis (โฆ) will be used.returns{String}: The truncated string.
Example
truncate("foo bar baz", 7);
<!-- results in: 'foo bar' -->
truncate(sanitize("<span>foo bar baz</span>", 7));
<!-- results in: 'foo bar' -->{{truncateWords}}
Truncate a string to have the specified number of words. Also see truncate.
Params
str{String}limit{Number}: The desired length of the returned string.suffix{String}: Optionally supply a string to use as a suffix to denote when the string has been truncated.returns{String}: The truncated string.
Example
truncateWords("foo bar baz", 1);
<!-- results in: 'fooโฆ' -->
truncateWords("foo bar baz", 2);
<!-- results in: 'foo barโฆ' -->
truncateWords("foo bar baz", 3);
<!-- results in: 'foo bar baz' -->{{upcase}}
Uppercase all of the characters in the given string. Alias for uppercase.
Params
string{String}returns{String}
Example
{{upcase "aBcDeF"}}
<!-- results in: 'ABCDEF' -->{{uppercase}}
Uppercase all of the characters in the given string. If used as a block helper it will uppercase the entire block. This helper does not support inverse blocks.
Params
str{String}: The string to uppercaseoptions{Object}: Handlebars options objectreturns{String}
Example
{{uppercase "aBcDeF"}}
<!-- results in: 'ABCDEF' -->File: docs/en-US/api/handlebars-helpers/url.md
URL
{{encodeURI}}
Encodes a Uniform Resource Identifier (URI) component
by replacing each instance of certain characters by
one, two, three, or four escape sequences representing
the UTF-8 encoding of the character.
Params
str{String}: The un-encoded stringreturns{String}: The endcoded string
{{escape}}
Escape the given string by replacing characters with escape sequences.
Useful for allowing the string to be used in a URL, etc.
Params
str{String}returns{String}: Escaped string.
{{decodeURI}}
Decode a Uniform Resource Identifier (URI) component.
Params
str{String}returns{String}
{{url_encode}}
Alias for encodeURI.
{{url_decode}}
Alias for decodeURI.
{{urlResolve}}
Take a base URL, and a href URL, and resolve them as a
browser would for an anchor tag.
Params
base{String}href{String}returns{String}
{{urlParse}}
Parses a url string into an object.
Params
str{String}: URL stringreturns{String}: Returns stringified JSON
{{stripQuerystring}}
Strip the query string from the given url.
Params
url{String}returns{String}: the url without the queryString
{{stripProtocol}}
Strip protocol from a url. Useful for displaying media that may have an 'http' protocol on secure connections.
Params
str{String}returns{String}: the url with http protocol stripped
Example
<!-- url = 'http://foo.bar' -->
{{stripProtocol url}}
<!-- results in: '//foo.bar' -->File: docs/en-US/api/http/index.md
Overview
HTTP API of NocoBase is designed based on Resource & Action, a superset of REST API. The operation includes but not limited to create, read, update and delete. Resource Action can be extended arbitrarily in NocoBase.
Resource
In NocoBase, resource has two expressions:
<collection><collection>.<association>
- Collection is the set of all abstract data
- Association is the associated data of collection
- Resource includes both collection and collection.association
Example
postsPostposts.userPost userposts.tagsPost tags
Action
Action on resource is expressed by :<action>
<collection>:<action><collection>.<association>:<action>
Built-in global actions for collection or association:
creategetlistupdatedestroymove
Built-in association actions for association only:
setaddremovetoggle
Example
posts:createCreate postposts.user:getGet post userposts.tags:addAdd tags to post (associate existing tags with post)
Request URL
<GET|POST> /api/<collection>:<action>
<GET|POST> /api/<collection>:<action>/<collectionIndex>
<GET|POST> /api/<collection>/<collectionIndex>/<association>:<action>
<GET|POST> /api/<collection>/<collectionIndex>/<association>:<action>/<associationIndex>Example
posts resource
POST /api/posts:create
GET /api/posts:list
GET /api/posts:get/1
POST /api/posts:update/1
POST /api/posts:destroy/1posts.comments resource
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/1posts.tags resource
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:removeLocate Resource
- Collection resource locates the data to be processed by
collectionIndex,collectionIndexmust be unique. - Association resource locates the data to be processed by
collectionIndexandassociationIndexjointly,associationIndexmay not be unique, but the joint index ofcollectionIndexandassociationIndexmust be unique.
When viewing details of association resource, the requested URL needs to provide both <collectionIndex> and <associationIndex>, <collectionIndex> is necessary as <associationIndex> may not be unique.
For example, tables.fields represents the fields of a data table:
GET /api/tables/table1/fields/title
GET /api/tables/table2/fields/titleBoth table1 and table2 have the title field, title is unique in one table, but other tables may also have fields of that name.
Request Parameters
Request parameters can be placed in the headers, parameters (query string), and body (GET requests do not have a body) of the request.
Some special request parameters:
filterData filtering, used in actions related to query.filterByTkFilter by tk field, used in actions to specify details of data.sortSorting, used in actions related to query.fieldsDate to output, used in actions related to queryappendsFields of additional relationship, used in actions related to query.exceptExclude some fields (not to output), used in actions related to query.whitelistFields whitelist, used in actions related to data creation and update.blacklistFields blacklist, used in actions related to data creation and update.
filter
Data filtering.
# simple
GET /api/posts?filter[status]=publish
# json string format is recommended, 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 information about filter operators
filterByTk
Filter by tk field. In the default settings:
- collection resource: tk is the primary key of the data table.
- association resource: tk is the targetKey field of the association.
GET /api/posts:get?filterByTk=1&fields=name,title&appends=tagssort
Sorting. To sort in the descending order, put - in front of the field.
# Sort createAt field in the ascending order
GET /api/posts:get?sort=createdAt
# Sort createAt field in the descending order
GET /api/posts:get?sort=-createdAt
# Sort multiple fields jointly, createAt field descending, title A-Z ascending
GET /api/posts:get?sort=-createdAt,titlefields
Data to output.
GET /api/posts:list?fields=name,title
Response 200 (application/json)
{
"data": [
{
"name": "",
"title": ""
}
],
"meta": {}
}appends
Fields of additional relationship.
except
Exclude some fields (not to output), used in actions related to query.
whitelist
Whitelist.
POST /api/posts:create?whitelist=title
{
"title": "My first post",
"date": "2022-05-19" # The date field will be filtered out and not be written to the database
}blacklist
Blacklist.
POST /api/posts:create?blacklist=date
# The date field will be filtered out and not be written to the database
{
"title": "My first post"
}Request Response
Format of the response:
type ResponseResult = {
data?: any; // Main data
meta?: any; // Additional Data
errors?: ResponseError[]; // Errors
};
type ResponseError = {
code?: string;
message: string;
};Example
View list:
GET /api/posts:list
Response 200 (application/json)
{
data: [
{
id: 1
}
],
meta: {
count: 1
page: 1,
pageSize: 1,
totalPage: 1
},
}View details:
GET /api/posts:get/1
Response 200 (application/json)
{
data: {
id: 1
}
}Error:
POST /api/posts:create
Response 400 (application/json)
{
errors: [
{
message: 'name must be required',
},
],
}File: docs/en-US/api/http/rest-api.md
REST API
HTTP API of NocoBase is a superset of REST API, and the standard CRUD API also supports the RESTful style.
Collection Resources
Create Collection
HTTP API
POST /api/<collection>:create
{} # JSON bodyREST API
POST /api/<collection>
{} # JSON bodyView Collection List
HTTP API
GET /api/<collection>:listREST API
GET /api/<collection>View Collection Details
HTTP API
GET /api/<collection>:get?filterByTk=<collectionIndex>
GET /api/<collection>:get/<collectionIndex>REST API
GET /api/<collection>/<collectionIndex>Update Collection
HTTP API
POST /api/<collection>:update?filterByTk=<collectionIndex>
{} # JSON body
# Or
POST /api/<collection>:update/<collectionIndex>
{} # JSON bodyREST API
PUT /api/<collection>/<collectionIndex>
{} # JSON bodyDelete Collection
HTTP API
POST /api/<collection>:destroy?filterByTk=<collectionIndex>
# Or
POST /api/<collection>:destroy/<collectionIndex>REST API
DELETE /api/<collection>/<collectionIndex>Association Resources
Create Association
HTTP API
POST /api/<collection>/<collectionIndex>/<association>:create
{} # JSON bodyREST API
POST /api/<collection>/<collectionIndex>/<association>
{} # JSON bodyView Association List
HTTP API
GET /api/<collection>/<collectionIndex>/<association>:listREST API
GET /api/<collection>/<collectionIndex>/<association>View Association Details
HTTP API
GET /api/<collection>/<collectionIndex>/<association>:get?filterByTk=<associationIndex>
# Or
GET /api/<collection>/<collectionIndex>/<association>:get/<associationIndex>REST API
GET /api/<collection>/<collectionIndex>/<association>:get/<associationIndex>Update Association
HTTP API
POST /api/<collection>/<collectionIndex>/<association>:update?filterByTk=<associationIndex>
{} # JSON body
# Or
POST /api/<collection>/<collectionIndex>/<association>:update/<associationIndex>
{} # JSON bodyREST API
PUT /api/<collection>/<collectionIndex>/<association>:update/<associationIndex>
{} # JSONDelete Association
HTTP API
POST /api/<collection>/<collectionIndex>/<association>:destroy?filterByTk=<associationIndex>
# Or
POST /api/<collection>/<collectionIndex>/<association>:destroy/<associationIndex>REST API
DELETE /api/<collection>/<collectionIndex>/<association>/<associationIndex>File: docs/en-US/api/resourcer/action.md
ctx.action
Overview
After the resource operation request is parsed by resourceManager.middleware(), some important request parameters are stored in ctx.action for use by subsequent middleware.
API
resourceName
ctx.action.resourceName
The name of the resource. It can take two forms:
a- Operates on resourcea.a.b- Operates on associated objectbof resourcea.
actionName
ctx.action.actionName
The name of the action.
sourceId
ctx.action.sourceId
When the operation object is an associated object of the resource, it represents the primary key value of the corresponding resource. For example: when resourceName is a.b, sourceId represents the primary key value of a.
params
Request parameters.
- URL parameters can be directly obtained from
ctx.action.params.
const { filterByTk } = ctx.action.params;- Request body parameters can be obtained using
ctx.action.params.values.
mergeParams()
Combines parameter content with request parameters.
ctx.action.mergeParams(
{
filter: {
name: 'foo',
},
fields: ['id', 'name'],
except: ['name'],
sort: ['id'],
page: 1,
pageSize: 10,
values: {
name: 'foo',
},
},
{
filter: 'and',
fields: 'union',
except: 'union',
sort: 'overwrite',
page: 'overwrite',
pageSize: 'overwrite',
values: 'deepMerge',
},
);
ctx.action.mergeParams(
{
filter: {},
},
{
filter: (x, y) => {
// ...
},
},
);Signature
mergeParams(params: ActionParams, strategies: MergeStrategies = {})
Type
export interface ActionParams {
filterByTk?: any;
fields?: string[];
appends?: string[];
except?: string[];
whitelist?: string[];
blacklist?: string[];
filter?: FilterOptions;
sort?: string[];
page?: number;
pageSize?: number;
values?: any;
[key: string]: any;
}
type MergeStrategyType =
| 'merge'
| 'deepMerge'
| 'overwrite'
| 'andMerge'
| 'orMerge'
| 'intersect'
| 'union';
type MergeStrategyFunc = (x: any, y: any) => any;
export type MergeStrategy = MergeStrategyType | MergeStrategyFunc;
export interface MergeStrategies {
[key: string]: MergeStrategy;
}Details
| Property | Type | Description |
|---|---|---|
params |
ActionParams |
Request parameters |
strategies |
{ [key: string]: MergeStrategies } |
Merge strategies for various fields in the request parameters |
Default strategies:
{
filter: 'andMerge',
fields: 'intersect',
appends: 'union',
except: 'union',
whitelist: 'intersect',
blacklist: 'intersect',
sort: 'overwrite',
};ActionParams
| Property | Type | Description |
|---|---|---|
filterByTk |
any |
The primary key value of the operated resource |
filter |
Filter |
Filtering parameters, refer to Filter Operators |
fields |
string[] |
Fields to retrieve |
except |
string[] |
Fields to exclude |
appends |
string[] |
Related fields to append |
whitelist |
string[] |
Field whitelist |
blacklist |
string[] |
Field blacklist |
sort |
string[] |
Sorting parameters |
page |
number |
Current page |
pageSize |
number |
Number of data items per page |
values |
any |
Request body |
[key: string] |
any |
Other extended configurations |
MergeStrategies
Predefined merge strategies or custom merge functions.
Predefined merge strategies:
| Strategy Name | Description |
|---|---|
merge |
Object.assign |
deepMerge |
Deep traversal merge |
overwrite |
Overwrite |
andMerge |
Merge filter parameters using the $and operator |
orMerge |
Merge filter parameters using the $or operator |
intersect |
Intersection |
union |
Union |
File: docs/en-US/api/resourcer/middleware.md
Middleware
It is similar to the middleware of Koa, but with more enhanced features for easy extensions.
The defined middleware can be inserted for use in multiple places, such as the resourcer, and it is up to the developer for when to invoke it.
Constructor
Signature
constructor(options: Function)constructor(options: MiddlewareOptions)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options |
Function |
- | Handler function of middlware |
options |
MiddlewareOptions |
- | Configuration items of middlware |
options.only |
string[] |
- | Only the specified actions are allowed |
options.except |
string[] |
- | The specified actions are excluded |
options.handler |
Function |
- | Handler function |
Example
Simple definition:
const middleware = new Middleware((ctx, next) => {
await next();
});Definition with relevant parameters:
const middleware = new Middleware({
only: ['create', 'update'],
async handler(ctx, next) {
await next();
},
});Instance Methods
`getHandler()`
Get the orchestrated handler functions.
Example
The following middleware will output 1 and then 2 when requested.
const middleware = new Middleware((ctx, next) => {
console.log(1);
await next();
});
middleware.use(async (ctx, next) => {
console.log(2);
await next();
});
app.resourcer.use(middleware.getHandler());`use()`
Add a middleware function to the current middleware. Used to provide extension points for the middleware. See getHandler() for the examples.
Signature
use(middleware: Function)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
middleware |
Function |
- | Handler function of the middleware |
`disuse()`
Remove the middleware functions that have been added to the current middleware.
Signature
disuse(middleware: Function)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
middleware |
Function |
- | Handler function of the middleware |
Example
The following example will only output 1 when requested, the output of 2 in fn1 will not be executed.
const middleware = new Middleware((ctx, next) => {
console.log(1);
await next();
});
async function fn1(ctx, next) {
console.log(2);
await next();
}
middleware.use(fn1);
app.resourcer.use(middleware.getHandler());
middleware.disuse(fn1);`canAccess()`
Check whether the current middleware is to be invoked for a specific action, it is usually handled by the resourcer internally.
Signature
canAccess(name: string): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the action |
Other Exports
`branch()`
Create a branch middleware for branching in the middleware.
Signature
branch(map: { [key: string]: Function }, reducer: Function, options): Function
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
map |
{ [key: string]: Function } |
- | Mapping table of the branch handler function, key names are given by subsequent calculation functions when called |
reducer |
(ctx) => string |
- | Calculation function, it is used to calculate the key name of the branch based on the context |
options? |
Object |
- | Configuration items of the branch |
options.keyNotFound? |
Function |
ctx.throw(404) |
Handler function when key name is not found |
options.handlerNotSet? |
Function |
ctx.throw(404) |
The function when no handler function is defined |
Example
When authenticating user, determine what to do next according to the value of the authenticator parameter in the query section of the request URL.
app.resourcer.use(
branch(
{
password: async (ctx, next) => {
// ...
},
sms: async (ctx, next) => {
// ...
},
},
(ctx) => {
return ctx.action.params.authenticator ?? 'password';
},
),
);File: docs/en-US/api/resourcer/resource-manager.md
ResourceManager
Overview
ResourceManager is the resource management module of NocoBase, used to define resources and register operation methods for resources.
Class Methods
`define()`
Defines a resource.
app.resourceManager.define({
name: 'auth',
actions: {
check: async (ctx, next) => {
// ...
await next();
},
},
});Signature
define(options: ResourceOptions): Resource
Type
export interface ResourceOptions {
name: string;
type?: ResourceType;
actions?: {
[key: string]: ActionType;
};
only?: Array<ActionName>;
except?: Array<ActionName>;
middleware?: MiddlewareType;
middlewares?: MiddlewareType;
}
export type ResourceType =
| 'single'
| 'hasOne'
| 'hasMany'
| 'belongsTo'
| 'belongsToMany';
export type ActionType = HandlerType | ActionOptions;
export type HandlerType = (
ctx: ResourcerContext,
next: () => Promise<any>,
) => any;
export interface ActionOptions {
values?: any;
fields?: string[];
appends?: string[];
except?: string[];
whitelist?: string[];
blacklist?: string[];
filter?: FilterOptions;
sort?: string[];
page?: number;
pageSize?: number;
maxPageSize?: number;
middleware?: MiddlewareType;
middlewares?: MiddlewareType;
handler?: HandlerType;
[key: string]: any;
}Details
ResourceOptions
| Property | Type | Description | Default |
|---|---|---|---|
name |
string |
Resource name | - |
type |
ResourceType |
Resource type | single |
actions |
{ [key: string]: ActionType } |
Actions | - |
only |
ActionName[] |
Whitelist of actions |
- |
except |
ActionName[] |
Blacklist of actions |
- |
middleware |
MiddlewareType |
Middleware | - |
middlewares |
MiddlewareType |
Middlewares | - |
ActionType
There are two types of action methods:
HandlerType
This type directly defines the operation method through middleware. Example:
app.resourceManager.define({
name: 'users',
actions: {
updateProfile: async (ctx, next) => {
// ...
await next();
},
},
});ActionOptions
This type is mainly used to override the request parameters of a certain existing operation. Example:
app.resourceManager.define({
name: 'users',
actions: {
list: {
fields: [],
filter: {},
// ...
},
},
});| Property | Type | Description |
|---|---|---|
values |
any |
Default values for the action request |
filter |
Filter |
Filtering parameters, refer to Filter Operators |
fields |
string[] |
Fields to retrieve |
except |
string[] |
Fields to exclude |
appends |
string[] |
Related fields to append |
whitelist |
string[] |
Field whitelist |
blacklist |
string[] |
Field blacklist |
sort |
string[] |
Sorting parameters |
page |
number |
Current page |
pageSize |
number |
Number of data items per page |
maxPageSize |
number |
Maximum number of data items per page |
middleware |
MiddlewareType |
Middleware |
middlewares |
MiddlewareType |
Middlewares |
handler |
HandlerType |
Method executed for the action |
[key: string] |
any |
Other extended configurations |
`registerActionHandlers()`
Registers action methods.
Signature
registerActionHandler(name: ActionName, handler: HandlerType)
Type
export type DefaultActionType =
| 'list'
| 'create'
| 'get'
| 'update'
| 'destroy'
| 'set'
| 'add'
| 'remove';
export type ActionName = DefaultActionType | Omit<string, DefaultActionType>;
export type HandlerType = (
ctx: ResourcerContext,
next: () => Promise<any>,
) => any;Details
| Property | Type | Description |
|---|---|---|
name |
ActionName |
Action name.1. As a regular string, registers actions for all resources.2. In the form <resource>:<action>, registers actions for specific resources |
handler |
HandlerType |
Middleware for the action |
`isDefined()`
Checks if a resource is defined.
Signature
isDefined(name: string)
Details
| Property | Type | Description |
|---|---|---|
name |
string |
Resource name |
`import()`
Loads resource configurations from a specified directory.
// ./resources/demo.ts
export default {
name: 'demo',
actions: {
async list(ctx, next) {
// ...
await next();
},
},
};
const resourceManager = new ResourceManager();
await resourceManager.import({
directory: path.resolve(__dirname, 'resources'),
});Signature
import(options: ImportOptions): Promise<Map<string, Resource>>
Type
export interface ImportOptions {
directory: string;
extensions?: string[];
}Details
| Property | Type | Description | Default Value |
|---|---|---|---|
directory |
string |
Directory path | - |
extensions |
string[] |
Optional, file extensions | ['js', 'ts', 'json'] |
`use()`
Adds ResourceManager middleware.
resourceManager.use(async () => {
return async function (ctx, next) {
// ...
await next();
};
});Signature
use(middlewares: HandlerType | HandlerType[], options: ToposortOptions = {})
Details
Refer to Middleware.
`middleware()`
Middleware for ResourceManager, parses request parameters (refer to ctx.action) and executes operation methods.
File: docs/en-US/api/resourcer/resource.md
Resource
Resource is used to define resource instance. Resource instances managed by resourcer can be accessed through HTTP requests.
Constructor
To create resource instance. Normally it is not used directly, but replaced by the call of the define() interface of resourcer.
Signature
constructor(options: ResourceOptions, resourcer: Resourcer)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.name |
string |
- | Name of the resource, corresponding to the resource address in the route of the URL |
options.type |
string |
'single' |
Type of the resource, options are 'single', 'hasOne', 'hasMany', 'belongsTo', 'belongsToMany' |
options.actions |
Object |
- | List of actions that can be taken on the resource, see the example for details |
options.middlewares |
MiddlewareType | MiddlewareType[] |
- | List of middlewares for any operational access to the resource that is defining๏ผsee the example for details |
options.only |
ActionName[] |
[] |
Whitelist for global actions, only actions contained in the array (if length > 0) can be accessed |
options.except |
ActionName[] |
[] |
Blacklist for global actions, all actions except those contained in the array (if length > 0) can be accessed |
resourcer |
Resourcer |
- | The resourcer instance |
Example
app.resourcer.define({
name: 'books',
actions: {
// Extended action
publish(ctx, next) {
ctx.body = 'ok';
},
},
middleware: [
// Extended middleware
async (ctx, next) => {
await next();
},
],
});Instance Members
`options`
Configuration items for the current resource.
`resourcer`
The resourcer instance to which the resource belongs.
`middlewares`
The registered middlewares.
`actions`
The registered mapping table of actions.
`except`
Actions that are excluded.
Instance Methods
`getName()`
Get the name of the current resource.
Signature
getName(): string
Example
const resource = app.resourcer.define({
name: 'books',
});
resource.getName(); // 'books'`getAction()`
Get action with the corresponding name.
Signature
getAction(name: string): Action
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the action |
Example
const resource = app.resourcer.define({
name: 'books',
actions: {
publish(ctx, next) {
ctx.body = 'ok';
},
},
});
resource.getAction('publish'); // [Function: publish]File: docs/en-US/api/sdk/auth.md
Auth
Overview
The Auth class is primarily used for accessing user information on the client-side, as well as requesting user authentication-related APIs.
Instance Properties
`locale`
The language used by the current user.
`role`
The role used by the current user.
`token`
The API interface token.
`authenticator`
The authenticator used for current user authentication. Refer to User Authentication.
Class Methods
`signIn()`
User login.
Signature
async signIn(values: any, authenticator?: string): Promise<AxiosResponse<any>>
Details
| Parameter | Type | Description |
|---|---|---|
values |
any |
Login API request parameters |
authenticator |
string |
Authenticator identifier used for login |
`signUp()`
User registration.
Signature
async signUp(values: any, authenticator?: string): Promise<AxiosResponse<any>>
Details
| Parameter | Type | Description |
|---|---|---|
values |
any |
Registration API request parameters |
authenticator |
string |
Authenticator identifier used for registration |
`signOut()`
Log out.
Signature
async signOut(values: any, authenticator?: string): Promise<AxiosResponse<any>>
Details
| Parameter | Type | Description |
|---|---|---|
values |
any |
Logout API request parameters |
authenticator |
string |
Authenticator identifier used for logout |
2. Official Technical Reference & Guides (nocobase/docs)
File: README.md
NocoBase V1 Documentation (Archived)
This repository is archived and no longer maintained. V2 documentation lives in the main repository: nocobase/nocobase (under the
docs/directory). For the latest docs, visit docs.nocobase.com.
If you need to access the V1 documentation, you can run it locally:
Local Development
git clone https://github.com/nocobase/docs.git
cd docs
yarn install
# Run English docs
yarn dev:en
# Run Chinese docs
yarn dev
# Run French docs
yarn dev:fr
# Run Japanese docs
yarn dev:ja
# Run Russian docs
yarn dev:ruBuild
yarn buildNote: yarn dev and yarn dev:en cannot be run at the same time.
File: package.json
{
"name": "nocobase-docs",
"version": "0.0.1",
"description": "A static site based on dumi",
"scripts": {
"start": "npm run dev",
"dev": "dumi dev",
"dev:en": "cross-env DOC_LANG=en-US dumi dev",
"dev:fr": "cross-env DOC_LANG=fr-FR dumi dev",
"dev:ja": "cross-env DOC_LANG=ja-JP dumi dev",
"dev:ru": "cross-env DOC_LANG=ru-RU dumi dev",
"build": "dumi build",
"build:en": "cross-env DOC_LANG=en-US dumi build",
"build:fr": "cross-env DOC_LANG=fr-FR dumi build",
"build:ja": "cross-env DOC_LANG=ja-JP dumi build",
"build:ru": "cross-env DOC_LANG=ru-RU dumi build",
"prepare": "husky install && dumi setup"
},
"authors": [],
"license": "MIT",
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"lint-staged": {
"*.{md,json}": [
"prettier --write --no-error-on-unmatched-pattern"
]
},
"devDependencies": {
"@alicloud/cdn20180510": "^4.2.2",
"@commitlint/cli": "^18.2.0",
"@commitlint/config-conventional": "^18.1.0",
"ali-oss": "^6.1.0",
"cross-env": "^7.0.3",
"dumi": "^2.2.14",
"husky": "^8.0.3",
"lint-staged": "^15.0.2",
"prettier": "^3.0.3"
},
"dependencies": {
"@formulajs/formulajs": "^4.4.9",
"@nocobase/client": "^0.21.0-alpha.6",
"axios-mock-adapter": "1.22.0",
"cytoscape": "^3.23.0",
"dumi-theme-nocobase": "^0.2.31",
"moment": "^2.30.1",
"sucrase": "^3.0.0",
"vditor": "^3.10.8"
},
"volta": {
"node": "20.14.0",
"yarn": "1.22.19"
},
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
File: tsconfig.json
{
"compilerOptions": {
"jsx": "react",
"strict": true,
"skipLibCheck": true,
"noImplicitAny": false,
"esModuleInterop": true,
"baseUrl": "./",
"paths": {
"@@/": [".dumi/tmp/"]
}
},
"include": [".dumirc.ts"]
}
File: docs/en-US/components.md
Components
File: docs/en-US/index.md
Index
File: docs/en-US/_partials/commercial-installation.md
Installation
This plugin is a commercial plugin, which needs to be uploaded and activated through the plugin manager๏ผ
File: docs/en-US/api/actions.md
@nocobase/actions
Overview
The @nocobase/actions package encapsulates frequently used CRUD-related methods. By simply registering it with the ResourceManager, CRUD operation interfaces can be globally added to system resources.
Basic Usage
import * as actions from `@nocobase/actions`;
const resourceManager = new ResourceManager({
// ...options
});
resourceManager.registerActionHandlers(actions);Action Methods
create
Creates a resource. POST /api/<resource>:create.
curl "http://localhost:13000/api/users:create" \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "admin"}'Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
list
Retrieves a list of resources. GET /api/<resource>:list.
curl -X GET http://localhost:13000/api/users:listParameters
| Parameter | Type | Description | Default |
|---|---|---|---|
filter |
Filter |
Filtering parameters, see Filter Operators | - |
fields |
string[] |
Fields to retrieve | - |
except |
string[] |
Fields to exclude | - |
appends |
string[] |
Related fields to append | - |
sort |
string[] |
Sorting parameters | - |
paginate |
boolean |
Whether to use pagination | true |
page |
number |
Current page number | 1 |
pageSize |
number |
Number of items per page | 20 |
get
Retrieves a specific resource. GET /api/<resource>:get.
curl -X GET http://localhost:13000/api/users:get?filterByTk=1Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
filterByTk |
number | string |
Filter by primary key value | - |
filter |
Filter |
Filtering parameters, see Filter Operators | - |
fields |
string[] |
Fields to retrieve | - |
except |
string[] |
Fields to exclude | - |
appends |
string[] |
Related fields to append | - |
update
Updates one or more resources. PUT /api/<resource>:update.
curl "http://localhost:13000/api/users:update?filterByTk=1" \
-X PUT \
-H "Content-Type: application/json" \
-d '{"username": "admin"}'Parameters
| Parameter | Type | Description |
|---|---|---|
filter |
Filter |
Filtering parameters, see Filter Operators |
filterByTk |
number | string |
Filter by primary key value |
Note: At least one of filter or filterByTk must be provided.
Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
destroy
Deletes one or more resources. DELETE /api/<resource>:destroy.
curl -X DELETE http://localhost:13000/api/users:destroy?filterByTk=1Parameters
| Parameter | Type | Description |
|---|---|---|
filter |
Filter |
Filtering parameters, see Filter Operators |
filterByTk |
number | string |
Filter by primary key value |
Note: At least one of filter or filterByTk must be provided.
firstOrCreate
Retrieves or creates a resource. POST /api/<resource>:firstOrCreate.
curl "http://localhost:13000/api/users:firstOrCreate?filterKeys[]=username" \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "admin", "nickname": "Admin"}'Parameters
| Parameter | Type | Description |
|---|---|---|
filterKeys |
string[] |
Fields in the request body used to find existing resources |
Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
updateOrCreate
Updates or creates a resource. POST /api/<resource>:updateOrCreate.
curl "http://localhost:13000/api/users:updateOrCreate?filterKeys[]=username" \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "admin", "nickname": "Admin"}'Parameters
| Parameter | Type | Description |
|---|---|---|
filterKeys |
string[] |
Fields in the request body used to find existing resources |
Request Body
| Parameter Name | Type | Description |
|---|---|---|
[key: string] |
any |
Key-value pairs representing resource fields |
move
Moves resources, adjusting the order. Typically used for drag-and-drop sorting in pages. POST /api/<resource>:move.
curl -X POST "http://localhost:13000/api/users:move?sourceId=1&targetId=2"Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
sourceId |
targetKey |
ID of the element to move | - |
targetId |
targetKey |
ID of the element to swap positions with | - |
sortField |
string |
Name of the field where sorting is stored | sort |
targetScope |
string |
Sorting scope, a resource can be sorted by different scopes | - |
sticky |
boolean |
Whether to stick the moved element | - |
method |
insertAfter | prepend |
Insertion method: whether to insert before |
set
Sets associated objects for a resource. POST /api/<resource>/<resourceKey>/<association>:set.
curl "http://localhost:13000/api/users/1/roles:set" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin", "member"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
add
Adds associated objects to a resource. POST /api/<resource>/<resourceKey>/<association>:add.
curl "http://localhost:13000/api/users/1/roles:add" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
remove
Removes associated objects from a resource. POST /api/<resource>/<resourceKey>/<association>:remove.
curl "http://localhost:13000/api/users/1/roles:remove" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
toggle
Toggles associated objects for a resource, adding them if they don't exist, or removing them if they do. POST /api/<resource>/<resourceKey>/<association>:toggle.
curl "http://localhost:13000/api/users/1/roles:toggle" \
-X POST \
-H "Content-Type: application/json" \
-d '["admin", "member"]'Request Body
TargetKey | TargetKey[]- Array of primary key values for associated objects.
File: docs/en-US/api/cli.md
@nocobase/cli
The NocoBase CLI is designed to help you develop, build, and deploy NocoBase applications.
NocoBase CLI supports ts-node and node two operation modes.
- ts-node mode (Default): Used for development environment, support real-time compilation, with relatively slow response
- node mode๏ผUsed for production environment, with quick response, but you need to execute
yarn nocobase buildto compile the entire source code first
Instructions For Use
$ yarn nocobase -h
Usage: nocobase [command] [options]
Options:
-h, --help
Commands:
console
db:auth Verify if the database is successfully connected
db:sync Generate relevant data tables and fields through the configuration of collections
install Install
start Start application in production environment
build Compile and package
clean Delete the compiled files
dev Start application for development environment with real-time compilation
doc Documentation development
test Testing
umi
upgrade Upgrade
migrator Data migration
pm Plugin manager
helpApplication in Scaffolding
scripts in the application scaffolding package.json is as below:
{
"scripts": {
"dev": "nocobase dev",
"start": "nocobase start",
"clean": "nocobase clean",
"build": "nocobase build",
"test": "nocobase test",
"pm": "nocobase pm",
"postinstall": "nocobase postinstall"
}
}Command Line Extensions
NocoBase CLI is built based on commander. You can write the extended commands freely in app/server/index.ts:
const app = new Application(config);
app.command('hello').action(() => {});or in the plugin:
class MyPlugin extends Plugin {
beforeLoad() {
this.app.command('hello').action(() => {});
}
}Run in the terminal:
$ yarn nocobase helloBuilt-in Commands
Sorted by frequency of use.
`dev`
Start application and compile code in real time in development environment.
Usage: nocobase dev [options]
Options:
-p, --port [port]
--client
--server
-h, --helpExample:
# Launch application for development environment, with real-time compilation
yarn nocobase dev
# Start the server side only
yarn nocobase dev --server
# Start the client side only
yarn nocobase dev --client`start`
Start application in production environment, the code needs yarn build.
- NocoBase is installed automatically if it is not installed (Refer to the
installcommand). - The source code needs to be re-packaged if it has any modification (Refer to the
buildcommand).
$ yarn nocobase start -h
Usage: nocobase start [options]
Options:
-p, --port
-s, --silent
-h, --helpExample:
# Launch application for production environment
yarn nocobase start`install`
Install.
$ yarn nocobase install -h
Usage: nocobase install [options]
Options:
-f, --force
-c, --clean
-s, --silent
-l, --lang [lang]
-e, --root-email <rootEmail>
-p, --root-password <rootPassword>
-n, --root-nickname [rootNickname]
-h, --helpExample:
# Initial installation
yarn nocobase install -l zh-CN -e [email protected] -p admin123
# Delete all data tables from NocoBase and reinstall
yarn nocobase install -f -l zh-CN -e [email protected] -p admin123
# Clear database and reinstall
yarn nocobase install -c -l zh-CN -e [email protected] -p admin123Difference between -f/--force and -c/--clean:
-f/--forceDelete data tables of NocoBase-c/--cleanClear database, all data tables are deleted
`upgrade`
Upgrade.
yarn nocobase upgrade`test`
jest test, which supports all jest-cli options, also supports -c, --db-clean.
$ yarn nocobase test -h
Usage: nocobase test [options]
Options:
-c, --db-clean Clear database before running all tests
-h, --helpExample:
# 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
# Clear database before running all tests
yarn nocobase test -c
yarn nocobase test packages/core/server -c`build`
The source code needs to be compiled and packaged before the code is deployed to the production environment; and you need to re-build the code if it has any modification.
# All packages
yarn nocobase build
# Specified packages
yarn nocobase build app/server app/client`clean`
Delete the compiled files.
yarn clean
# Equivalent to
yarn rimraf -rf packages/*/*/{lib,esm,es,dist}`doc`
Documentation development.
# Start the documentation
yarn doc --lang=zh-CN # 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 output documentation of dist
yarn doc serve --lang=zh-CN`db:auth`
Verify if the database is successfully connected.
$ yarn nocobase db:auth -h
Usage: nocobase db:auth [options]
Options:
-r, --retry [retry] Number of retries
-h, --help`db:sync`
Generate relevant data tables and fields through the configuration of collections.
$ yarn nocobase db:sync -h
Usage: nocobase db:sync [options]
Options:
-f, --force
-h, --help display help for command`migrator`
Data migration.
$ yarn nocobase migrator
Positional arguments:
<command>
up Applies pending migrations
down Revert migrations
pending Lists pending migrations
executed Lists executed migrations
create Create a migration file`pm`
Plugin manager.
# Create plugin
yarn pm create hello
# Register plugin
yarn pm add hello
# Enable plugin
yarn pm enable hello
# Disable plugin
yarn pm disable hello
# Remove plugin
yarn pm remove helloNot achieved yet:
# Upgrade plugin
yarn pm upgrade hello
# Publish plugin
yarn pm publish hello`umi`
app/client is built based on umi, you can run other relevant commands through nocobase umi.
# Generate the .umi cache needed for the development environment
yarn nocobase umi generate tmp`help`
The help command, you can also use the option parameter, -h and --help.
# View all cli
yarn nocobase help
# Use -h instead
yarn nocobase -h
# Or --help
yarn nocobase --help
# View options of command db:sync
yarn nocobase db:sync -hFile: docs/en-US/api/index.md
Overview
| Module | Package | Description |
|---|---|---|
| Server | @nocobase/server |
Server-side application |
| Database | @nocobase/database |
Database access layer |
| Resourcer | @nocobase/resourcer |
Resource and route mapping |
| ACL | @nocobase/acl |
Access Control |
| Auth | @nocobase/auth |
User Authentication |
| Client | @nocobase/client |
Client-side application |
| Cache | @nocobase/cache |
Server-side cache |
| Logger | @nocobase/logger |
Server-side logging |
| Telemetry | @nocobase/telemetry |
Server-side telemetry |
| CLI | @nocobase/cli |
NocoBase Command Line Interface |
| SDK | @nocobase/sdk |
NocoBase SDK |
| Actions | @nocobase/actions |
Built-in resource operations |
| Test | @nocobase/test |
Automated testing |
File: docs/en-US/api/logger.md
@nocobase/logger
Create Logger
createLogger()
Creates a custom logger.
Signature
createLogger(options: LoggerOptions)
Type
interface LoggerOptions
extends Omit<winston.LoggerOptions, 'transports' | 'format'> {
dirname?: string;
filename?: string;
format?: 'logfmt' | 'json' | 'delimiter' | 'console' | winston.Logform.Format;
transports?: ('console' | 'file' | 'dailyRotateFile' | winston.transport)[];
}Details
dirname: Log directoryfilename: Log file nameformat: Log formattransports: Log transports
createSystemLogger()
Creates system runtime logs printed in a specified method. Refer to Logger plugin - System log.
Signature
createSystemLogger(options: SystemLoggerOptions)
Type
export interface SystemLoggerOptions extends LoggerOptions {
seperateError?: boolean; // print error seperately, default true
}Details
seperateError: Whether to printerrorlevel logs separately
app.createLogger()
Definition
class Application {
createLogger(options: LoggerOptions) {
const { dirname } = options;
return createLogger({
...options,
dirname: getLoggerFilePath(this.name || 'main', dirname || ''),
});
}
}When dirname is a relative path, the log files will be output to the directory named after the current application.
plugin.createLogger()
Usage is the same as app.createLogger().
Definition
class Plugin {
createLogger(options: LoggerOptions) {
return this.app.createLogger(options);
}
}Configuration
getLoggerLevel()
getLoggerLevel(): 'debug' | 'info' | 'warn' | 'error'
Gets the log level currently configured in the system.
getLoggerFilePath()
getLoggerFilePath(...paths: string[]): string
Concatenates directory paths based on the log directory currently configured in the system.
getLoggerTransports()
getLoggerTransports(): ('console' | 'file' | 'dailyRotateFile')[]
Gets the log output methods currently configured in the system.
getLoggerFormat()
getLoggerFormat(): 'logfmt' | 'json' | 'delimiter' | 'console'
Gets the log format currently configured in the system.
Logger Transports
Transports
Predefined output methods.
Transports.consoleTransports.fileTransports.dailyRotateFile
import { Transports } from '@nocobase/logger';
const transport = Transports.console({
//...
});References
File: docs/en-US/api/acl/acl.md
ACL
Overview
ACL is the permission management module used in NocoBase, responsible for user role management, permission registration and authorization, as well as permission policy evaluation and access control.
Concepts
- Resource: Collections, or custom resources can be registered. Refer to
@nocobase/resourcer. - Action: An operation interface for a resource, such as create, read, update, delete, or other custom actions. Refer to
@nocobase/actions. - Strategy: Configures global permissions for roles, such as permissions for resource operations like create, read, update, delete, import, export, and system permissions like configuring the user interface.
- Snippet: Defines a collection of operations, enabling unified management of operation permissions. Snippet identifiers can be matched using the minimatch rules.
Class Methods
`define()`
Defines a role.
Signature
define(options: DefineOptions): ACLRole
Type Definitions
export interface DefineOptions {
role: string;
strategy?: string | AvailableStrategyOptions;
actions?: ResourceActionsOptions;
snippets?: string[];
}
export interface AvailableStrategyOptions {
displayName?: string;
actions?: false | string | string[];
allowConfigure?: boolean;
resource?: '*';
}
export interface ResourceActionsOptions {
[actionName: string]: RoleActionParams;
}
export interface RoleActionParams {
fields?: string[];
filter?: any;
own?: boolean;
whitelist?: string[];
blacklist?: string[];
}Details
DefineOptions
| Property | Type | Description |
|---|---|---|
role |
string |
Unique identifier for the role |
strategy |
string | AvailableStrategyOptions |
Optional, global access strategy for the role |
actions |
{ [actionName: string]: RoleActionParams; } |
Optional, permission configuration for actions |
snippets |
string[] |
Optional, defines snippets that the role has permission to access |
AvailableStrategyOptions
| Property | Type | Description |
|---|---|---|
displayName |
string |
Optional, display name for the strategy |
action |
false | string | string[] |
Optional, operation interfaces |
allowConfigure |
boolean |
Optional, whether to allow configuring the user interface |
resource |
* |
Applies to all resources |
RoleActionParams
| Property | Type | Description |
|---|---|---|
fields |
string[] |
Optional, fields of the data table to operate on |
filter |
any |
Optional, filter parameters that must be met, only records that meet the conditions can be operated on |
own |
boolean |
Optional, whether to operate only on records created by oneself |
whitelist |
string[] |
Optional, whitelist of fields that can be accessed, only fields in the whitelist can be accessed |
blacklist |
string[] |
Optional, blacklist of fields that cannot be accessed, fields in the blacklist cannot be accessed |
`can()`
Determines the permission to execute an action and returns the final action parameters. Returns null if no permission.
Signature
can(options: CanArgs): CanResult | null
Type Definitions
interface CanArgs {
role: string;
resource: string;
action: string;
ctx?: any;
}
interface CanResult {
role: string;
resource: string;
action: string;
params?: any;
}Details
CanArgs
| Property | Type | Description |
|---|---|---|
role |
string |
Role identifier |
resource |
string |
Resource identifier |
action |
string |
Action identifier |
ctx |
any |
Optional, request context |
CanResult
| Property | Type | Description |
|---|---|---|
role |
string |
Role identifier |
resource |
string |
Resource identifier |
action |
string |
Action identifier |
params |
any |
Optional, action parameters |
`registerSnippet()`
Registers a snippet.
Signature
registerSnippet(snippet: SnippetOptions)
Type Definitions
export type SnippetOptions = {
name: string;
actions: string[];
};Details
| Property | Type | Description |
|---|---|---|
name |
string |
Snippet identifier, can be matched using the minimatch rules. E.g., auth.auth matches auth.*. |
actions |
string[] |
Resource operations included in the snippet, in the format resource:action. E.g., users:list. |
`setAvailableAction()`
Sets allowed actions.
Signature
setAvailableAction(name: string, options: AvailableActionOptions = {})
export interface AvailableActionOptions {
displayName?: string;
aliases?: string[] | string;
resource?: string;
// Perform operations on new data
onNewRecord?: boolean;
// Allow configuring fields
allowConfigureFields?: boolean;
}Details
| Property | Type | Description |
|---|---|---|
displayName |
string |
Optional, display name for the action |
aliases |
string | string[] |
Optional, action aliases. E.g., aliases for get, list operations are both view. |
resource |
string |
Optional, resource |
onNewRecord |
boolean |
Optional, whether the operation applies to new data, such as create operation |
allowConfigureFields |
boolean |
Optional, whether to allow configuring fields |
`setAvailableStrategy()`
Sets allowed strategies for actions.
Signature
setAvailableStrategy(name: string, options: AvailableStrategyOptions)
Refer to AvailableStrategyOptions.
`allow()`
Defines the conditions under which operations are allowed.
acl.allow('plugins', '*', 'public');Signature
allow(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc)
Type
export type ConditionFunc = (ctx: any) => Promise<boolean> | boolean;Details
| Parameter | Type | Description | Default |
|---|---|---|---|
resourceName |
string |
Resource | - |
actionNames |
string | string[] |
Action | - |
condition |
string | ConditionFunc |
Optional, predefined condition identifier, or condition evaluation function | public |
Predefined condition identifiers:
public: Public interface.loggedIn: Allowed when the user is logged in.allowConfigure: Allowed when the current user role has permission to configure the user interface.
`addFixedParams()`
Adds fixed parameters to operations, merging them with current request parameters.
acl.addFixedParams('users', 'list', () => {
return {
filter: {
id: {
$eq: 1,
},
},
};
});Signature
addFixedParams(resource: string, action: string, merger: Merger)
Type Definitions
export type Merger = () => object;Details
| Parameter | Type | Description |
|---|---|---|
resource |
string |
Resource |
action |
string |
Action |
merger |
Merger |
Function returning the fixed parameter object to be added |
`use()`
Adds the ACL middleware.
acl.use(async () => {
return async function (ctx, next) {
// ...
await next();
};
});Signature
use(fn: any, options?: ToposortOptions)
Details
Refer to Middleware.
`middleware()`
NocoBase access control middleware.
File: docs/en-US/api/auth/auth-manager.md
AuthManager
Overview
AuthManager is the user authentication management module in NocoBase, used for registering different types of user authentication.
Basic Usage
const authManager = new AuthManager({
// Key to retrieve the current authenticator identifier from the request header
authKey: 'X-Authenticator',
});
// Set methods for storing and retrieving authenticators in AuthManager
authManager.setStorer({
get: async (name: string) => {
return db.getRepository('authenticators').find({ filter: { name } });
},
});
// Register an authentication type
authManager.registerTypes('basic', {
auth: BasicAuth,
title: 'Password',
});
// Use authentication middleware
app.resourceManager.use(authManager.middleware());Concepts
- Authentication type (
AuthType): Different types of authentication, such as Password, SMS, OIDC, SAML, etc. - Authenticator: An authenticator is a database-stored entity linked to a configuration record for a specific authentication type (
AuthType). Multiple authenticators can exist for one authentication type, each offering diffrent authentications. - Authenticator name: Unique identifier for an authenticator, used to determine the current authentication employed by the current request.
Class Methods
`constructor()`
Constructor, creates an instance of AuthManager.
Signature
constructor(options: AuthManagerOptions)
Types
export interface JwtOptions {
secret: string;
expiresIn?: string;
}
export type AuthManagerOptions = {
authKey: string;
default?: string;
jwt?: JwtOptions;
};Details
AuthManagerOptions
| Attribute | Type | Description | Default |
|---|---|---|---|
authKey |
string |
Optional key to save the current authenticator identifier in the request header | X-Authenticator |
default |
string |
Optional, default authenticator identifier | basic |
jwt |
JwtOptions |
Optional, configure if using JWT for authentication | - |
JwtOptions
| Attribute | Type | Description | Default |
|---|---|---|---|
secret |
string |
Token secret key | X-Authenticator |
expiresIn |
string |
Optional, token expiration period | 7d |
`setStorer()`
Set methods for storing and retrieving authenticator data.
Signature
setStorer(storer: Storer)
Types
export interface Authenticator = {
authType: string;
options: Record<string, any>;
[key: string]: any;
};
export interface Storer {
get: (name: string) => Promise<Authenticator>;
}Details
Authenticator
| Attribute | Type | Description |
|---|---|---|
authType |
string |
Authentication type |
options |
Record<string, any> |
Authenticator-related configurations |
Storer
Storer is the interface for authenticator storage, containing one method.
get(name: string): Promise<Authenticator>- Get authenticator by identifier. In NocoBase, the actual returned type is AuthModel.
`registerTypes()`
Register authentication types.
Signature
registerTypes(authType: string, authConfig: AuthConfig)
Types
export type AuthExtend<T extends Auth> = new (config: Config) => T;
type AuthConfig = {
auth: AuthExtend<Auth>; // The authentication class.
title?: string; // The display name of the authentication type.
};Details
| Attribute | Type | Description |
|---|---|---|
auth |
AuthExtend<Auth> |
Authentication type implementation, refer to Auth |
title |
string |
Optional. Title of the authentication type displayed on the frontend |
`listTypes()`
Get a list of registered authentication types.
Signature
listTypes(): { name: string; title: string }[]
Details
| Attribute | Type | Description |
|---|---|---|
name |
string |
Authentication type identifier |
title |
string |
Title of the authentication type |
`get()`
Get authenticator.
Signature
get(name: string, ctx: Context)
Details
| Attribute | Type | Description |
|---|---|---|
name |
string |
Authenticator identifier |
ctx |
Context |
Request context |
`middleware()`
Authentication middleware. Get the current authenticator and perform user authentication.
File: docs/en-US/api/auth/auth.md
Auth
Overview
Auth is an abstract class for user authentication types, defining the interfaces required to complete user authentication. To extend new user authentication types, you need to inherit from the Auth class and implement its methods. The basic implementation can be referred to as BaseAuth.
interface IAuth {
user: Model;
// Check the authentication status and return the current user.
check(): Promise<Model>;
signIn(): Promise<any>;
signUp(): Promise<any>;
signOut(): Promise<any>;
}
export abstract class Auth implements IAuth {
abstract user: Model;
abstract check(): Promise<Model>;
// ...
}
class CustomAuth extends Auth {
// check: Authentication
async check() {
// ...
}
}Instance Properties
`user`
Information of the authenticated user.
Signature
abstract user: Model
Class Methods
`constructor()`
Constructor, creates an instance of Auth.
Signature
constructor(config: AuthConfig)
Types
export type AuthConfig = {
authenticator: Authenticator;
options: {
[key: string]: any;
};
ctx: Context;
};Details
AuthConfig
| Attribute | Type | Description |
|---|---|---|
authenticator |
Authenticator |
Authenticator data model, the actual type in NocoBase applications is AuthModel |
options |
Record<string, any> |
Authenticator-related configurations |
ctx |
Context |
Request context |
`check()`
User authentication, returns user information. This is an abstract method that all authentication types must implement.
Signature
abstract check(): Promise<Model>
`signIn()`
User login.
Signature
signIn(): Promise<any>
`signUp()`
User registration.
Signature
signUp(): Promise<any>
`signOut()`
User logout.
Signature
signOut(): Promise<any>
File: docs/en-US/api/auth/base-auth.md
BaseAuth
Overview
BaseAuth inherits from the abstract class Auth and serves as the basic implementation for user authentication types, using JWT as the authentication method. In most cases, extending user authentication types can be achieved by inheriting from BaseAuth instead of directly inheriting from the Auth abstract class.
class BasicAuth extends BaseAuth {
constructor(config: AuthConfig) {
// Set user collection
const userCollection = config.ctx.db.getCollection('users');
super({ ...config, userCollection });
}
// User authentication logic, called by `auth.signIn`
// Returns user data
async validate() {
const ctx = this.ctx;
const { values } = ctx.action.params;
// ...
return user;
}
}Class Methods
`constructor()`
Constructor, creates an instance of BaseAuth.
Signature
constructor(config: AuthConfig & { userCollection: Collection })
Details
| Parameter | Type | Description |
|---|---|---|
config |
AuthConfig |
Refer to Auth - AuthConfig |
userCollection |
Collection |
User collection, e.g., db.getCollection('users'), refer to DataBase - Collection |
`user()`
Accessor for setting and getting user information, defaulting to using the ctx.state.currentUser object.
Signature
set user()get user()
`check()`
Authenticates through the request token and returns user information.
`signIn()`
User login, generates a token.
`signUp()`
User registration.
`signOut()`
User logout, token expiration.
`validate()` \*
Core authentication logic, called by the signIn interface, to determine whether the user can successfully log in.
File: docs/en-US/api/cache/cache-manager.md
CacheManager
Overview
CacheManager is based on node-cache-manager and provides caching module management for NocoBase. The built-in cache types are:
- memory: Provided by the default lru-cache of node-cache-manager.
- redis: Supported by node-cache-manager-redis-yet for Redis caching.
More types can be extended and registered through the API.
Concepts
Store: Defines a caching method, including a factory method for creating caches and other related configurations. Each caching method has a unique identifier provided during registration. The two built-in caching methods correspond to the unique identifiers
memoryandredis.Store Factory Method: Provided by
node-cache-managerand related extension packages, used to create caches. Examples includememoryprovided bynode-cache-managerby default, andredisStoreprovided bynode-cache-manager-redis-yet. In this context, the object to be provided corresponds toStoreOptions, which is the first parameter of thecachingmethod innode-cache-manager.Cache: A class encapsulated by NocoBase, providing methods related to cache usage. When actually using caching, operations are performed on instances of
Cache. EachCacheinstance has a unique identifier, which serves as a namespace for distinguishing different modules.
Class Methods
`constructor()`
Signature
constructor(options?: CacheManagerOptions)
Type
export type CacheManagerOptions = Partial<{
defaultStore: string;
stores: {
[storeType: string]: StoreOptions;
};
}>;
type StoreOptions = {
store?: 'memory' | FactoryStore<Store, any>;
close?: (store: Store) => Promise<void>;
// global config
[key: string]: any;
};Details
CacheManagerOptions
| Property | Type | Description |
|---|---|---|
defaultStore |
string |
Unique identifier for the default cache type. |
stores |
Record<string, StoreOptions> |
Registers cache types. The key is the unique identifier for the cache type, and the value is an object containing the registration method and global configurations. |
StoreOptions
| Property | Type | Description |
|---|---|---|
store |
memory | FactoryStore<Store, any> |
The store factory method, corresponding to the first parameter of the caching method. |
close |
(store: Store) => Promise<void> |
Optional. For middleware that requires establishing a connection, such as Redis, provide a callback method for closing the connection. The parameter is the object returned by the store factory method. |
[key: string] |
any |
Other global configurations for the store, corresponding to the second parameter of the caching method. |
Default `options`
import { redisStore, RedisStore } from 'cache-manager-redis-yet';
const defaultOptions: CacheManagerOptions = {
defaultStore: 'memory',
stores: {
memory: {
store: 'memory',
// global config
max: 2000,
},
redis: {
store: redisStore,
close: async (redis: RedisStore) => {
await redis.client.quit();
},
},
},
};The options parameter will be merged with the default options. Existing default options can be omitted. For example:
const cacheManager = new CacheManager({
stores: {
defaultStore: 'redis',
redis: {
// redisStore is already provided in the default options, so only need to provide redisStore configuration.
url: 'redis://localhost:6379',
},
},
});`registerStore()`
Register a new caching method. Example:
import { redisStore } from 'cache-manager-redis-yet';
cacheManager.registerStore({
// Unique identifier for the store
name: 'redis',
// Factory method for creating the store
store: redisStore,
// Callback method for closing the store connection
close: async (redis: RedisStore) => {
await redis.client.quit();
},
// Global configurations
url: 'xxx',
});Signature
registerStore(options: { name: string } & StoreOptions)
`createCache()`
Create a cache. Example:
await cacheManager.createCache({
name: 'default', // Unique identifier for the cache
store: 'memory', // Unique identifier for the store
prefix: 'mycache', // Automatically adds the 'mycache:' prefix to cache keys, optional
// Other store configurations, custom configurations that will be merged with global store configurations
max: 2000,
});Signature
createCache(options: { name: string; prefix?: string; store?: string; [key: string]: any }): Promise<Cache>
Details
options
| Property | Type | Description |
|---|---|---|
name |
string |
Unique identifier for the cache |
store |
string |
Unique identifier for the store |
prefix |
string |
Optional. Prefix automatically added to cache keys |
[key: string] |
any |
Other custom store configurations |
When store is omitted, the defaultStore will be used. In this case, the caching
File: docs/en-US/api/cache/cache.md
Cache
Basic Methods
You can refer to the documentation of node-cache-manager.
get()set()del()reset()wrap()mset()mget()mdel()keys()ttl()
Other Methods
`wrapWithCondition()`
Similar to wrap(), but can decide whether to use caching based on conditions.
async wrapWithCondition<T>(
key: string,
fn: () => T | Promise<T>,
options?: {
// External parameter to control whether to use cache results
useCache?: boolean;
// Determine whether to cache based on data results
isCacheable?: (val: unknown) => boolean | Promise<boolean>;
ttl?: Milliseconds;
},
): Promise<T> {`setValueInObject()`
When the cached content is an object, changes the value of a specific key.
async setValueInObject(key: string, objectKey: string, value: unknown)`getValueInObject()`
When the cached content is an object, retrieves the value of a specific key.
async getValueInObject(key: string, objectKey: string)`delValueInObject()`
When the cached content is an object, deletes a specific key.
async delValueInObject(key: string, objectKey: string)File: docs/en-US/api/client/application.md
Application
Constructor
`constructor()`
Create an application instance.
Signature
constructor(options: ApplicationOptions)
Example
const app = new Application({
apiClient: {
baseURL: process.env.API_BASE_URL,
},
dynamicImport: (name: string) => {
return import(`../plugins/${name}`);
},
});Methods
use()
Add Providers, build-in Providers are:
- APIClientProvider
- I18nextProvider
- AntdConfigProvider
- SystemSettingsProvider
- PluginManagerProvider
- SchemaComponentProvider
- SchemaInitializerProvider
- BlockSchemaComponentProvider
- AntdSchemaComponentProvider
- ACLProvider
- RemoteDocumentTitleProvider
render()
Component to render the App.
import { Application } from '@nocobase/client';
export const app = new Application({
apiClient: {
baseURL: process.env.API_BASE_URL,
},
dynamicImport: (name: string) => {
return import(`../plugins/${name}`);
},
});
export default app.render();File: docs/en-US/api/client/index.md
Overview
test
File: docs/en-US/api/client/router.md
Router
API
Initial
const app = new Application({
router: {
type: 'browser', // type default value is `browser`
},
});
// or
const app = new Application({
router: {
type: 'memory',
initialEntries: ['/'],
},
});add Route
basic
import { RouteObject } from 'react-router-dom';
const app = new Application();
const Hello = () => {
return <div>Hello</div>;
};
// first argument is `name` of route, second argument is `RouteObject`
app.router.add('root', {
path: '/',
element: <Hello />,
});
app.router.add('root', {
path: '/',
Component: Hello,
});Component is String
app.addComponents({
Hello,
});
app.router.add('root', {
path: '/',
Component: 'Hello',
});nested
import { Outlet } from 'react-router-dom';
const Layout = () => {
return (
<div>
<Link to="/home">Home</Link>
<Link to="/about">about</Link>
<Outlet />
</div>
);
};
const Home = () => {
return <div>Home</div>;
};
const About = () => {
return <div>About</div>;
};
app.router.add('root', {
element: <Layout />,
});
app.router.add('root.home', {
path: '/home',
element: <Home />,
});
app.router.add('root.about', {
path: '/about',
element: <About />,
});It will generate the following routes:
{
element: <Layout />,
children: [
{
path: '/home',
element: <Home />
},
{
path: '/about',
element: <About />
}
]
}remove Route
// remove route by name
app.router.remove('root.home');
app.router.remove('hello');Router in plugin
class MyPlugin extends Plugin {
async load() {
// add route
this.app.router.add('hello', {
path: '/hello',
element: <div>hello</div>,
});
// remove route
this.app.router.remove('world');
}
}Example
/**
* defaultShowCode: true
*/
import React from 'react';
import { Link, Outlet } from 'react-router-dom';
import { Application } from '@nocobase/client';
const Home = () => <h1>Home</h1>;
const About = () => <h1>About</h1>;
const Layout = () => {
return (
<div>
<div>
<Link to={'/'}>Home</Link>, <Link to={'/about'}>About</Link>
</div>
<Outlet />
</div>
);
};
const app = new Application({
router: {
type: 'memory',
initialEntries: ['/'],
},
});
app.router.add('root', {
element: <Layout />,
});
app.router.add('root.home', {
path: '/',
element: <Home />,
});
app.router.add('root.about', {
path: '/about',
element: <About />,
});
export default app.getRootComponent();File: docs/en-US/api/client/extensions/acl.md
ACL
Components
` `
` `
` `
` `
` `
` `
Hooks
`useACLContext()`
`useACLRoleContext()`
`useRoleRecheck()`
File: docs/en-US/api/client/extensions/block-provider.md
BlockProvider
Kernel Methods
``
`useBlockRequestContext()`
Build-in BlockProvider Components
` `
``
``
``
` `
` `
``
` `
File: docs/en-US/api/client/extensions/collection-manager.md
CollectionManager
Components
CollectionManagerProvider
<CollectionManagerProvider
interfaces={{}}
collections={[]}
></CollectionManagerProvider>CollectionProvider
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}></CollectionProvider>;If there is no collection parameter passed in, get the collection from CollectionManagerProvider with the corresponding name.
const collections = [
{
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
},
];
<CollectionManagerProvider collections={collections}>
<CollectionProvider name={'tests'}></CollectionProvider>
</CollectionManagerProvider>;CollectionFieldProvider
const field = {
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
};
<CollectionFieldProvider field={field}></CollectionFieldProvider>;If there is no field parameter passed in, get the field from CollectionProvider with the corresponding name.
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}>
<CollectionFieldProvider name={'title'}></CollectionFieldProvider>
</CollectionProvider>;CollectionField
Universal field component that needs to be used with <CollectionProvider/>, but only in schema scenarios. Get the field schema from CollectionProvider with the corresponding name. Extend the configuration via the schema where the CollectionField is located.
{
name: 'title',
'x-decorator': 'FormItem',
'x-decorator-props': {},
'x-component': 'CollectionField',
'x-component-props': {},
properties: {},
}Hooks
useCollectionManager()
Use with <CollectionManagerProvider/>.
const { collections, get } = useCollectionManager();useCollection()
Use with <CollectionProvider/>.
const { name, fields, getField, findField, resource } = useCollection();useCollectionField()
Use with <CollectionFieldProvider/>.
const { name, uiSchema, resource } = useCollectionField();The resource needs to be used with <RecordProvider/> to provide context of the record of the current data table row.
CollectionManager
Components
CollectionManagerProvider
<CollectionManagerProvider
interfaces={{}}
collections={[]}
></CollectionManagerProvider>CollectionProvider
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}></CollectionProvider>;If there is no collection parameter passed in, get the collection from CollectionManagerProvider with the corresponding name.
const collections = [
{
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
},
];
<CollectionManagerProvider collections={collections}>
<CollectionProvider name={'tests'}></CollectionProvider>
</CollectionManagerProvider>;CollectionFieldProvider
const field = {
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
};
<CollectionFieldProvider field={field}></CollectionFieldProvider>;If there is no field parameter passed in, get the field from CollectionProvider with the corresponding name.
const collection = {
name: 'tests',
fields: [
{
type: 'string',
name: 'title',
interface: 'input',
uiSchema: {
type: 'string',
'x-component': 'Input',
},
},
],
};
<CollectionProvider collection={collection}>
<CollectionFieldProvider name={'title'}></CollectionFieldProvider>
</CollectionProvider>;CollectionField
Universal field component that needs to be used with <CollectionProvider/>, but only in schema scenarios. Get the field schema from CollectionProvider with the corresponding name. Extend the configuration via the schema where the CollectionField is located.
{
name: 'title',
'x-decorator': 'FormItem',
'x-decorator-props': {},
'x-component': 'CollectionField',
'x-component-props': {},
properties: {},
}Hooks
useCollectionManager()
Use with <CollectionManagerProvider/>.
const { collections, get } = useCollectionManager();useCollection()
Use with <CollectionProvider/>.
const { name, fields, getField, findField, resource } = useCollection();useCollectionField()
Use with <CollectionFieldProvider/>.
const { name, uiSchema, resource } = useCollectionField();The resource needs to be used with <RecordProvider/> to provide context of the record of the current data table row.
File: docs/en-US/api/client/extensions/schema-component.md
้้ ็ Schema ็ปไปถ
Common
- DndContext
- SortableItem
And Design
- Action
- BlockItem
- Calendar
- CardItem
- Cascader
File: docs/en-US/api/client/schema-designer/schema-component.md
SchemaComponent
Core Components
` `
``
``
Core Methods
`createDesignable()`
`useDesignable()`
`useCompile()`
File: docs/en-US/api/client/schema-designer/schema-initializer.md
SchemaInitializer
Used for the initialization of various schemas. Newly added schema can be inserted anywhere in an existing schema node, including:
{
properties: {
// beforeBegin - Insert in front of the current node
node1: {
properties: {
// afterBegin - Insert in front of the first child node of the current node
// ...
// beforeEnd - After the last child node of the current node
},
},
// afterEnd - After the current node
},
}The core of SchemaInitializer includes <SchemaInitializer.Button /> and <SchemaInitializer.Item /> the two components. <SchemaInitializer.Button /> is used to create the dropdown menu button of schema, and the options of the dropdown menu is <SchemaInitializer.Item/>.
` `
` `
` `
File: docs/en-US/api/client/schema-designer/schema-settings.md
SchemaSettings
` `
` `
` `
` `
` `
` `
` `
` `
` `
` `
` `
` `
File: docs/en-US/api/data-source-manager/data-source.md
DataSource (abstract)
The DataSource abstract class is used to represent a type of data source, which can be a database, API, etc.
Members
collectionManager
The CollectionManager instance of the data source, which needs to implement the ICollectionManager interface.
resourceManager
The resourceManager instance of the data source, see: resourceManager
acl
The ACL instance of the data source, see: ACL
API
constructor()
Constructor, creates a DataSource instance.
Signature
constructor(options: DataSourceOptions)
init()
Initialization function, called immediately after constructor.
Signature
init(options: DataSourceOptions)
name
Signature
get name()
Returns the instance name of the data source.
middleware()
Gets the middleware of the DataSource, used to mount to the Server to receive requests.
testConnection()
Static method, called during the test connection operation, can be used for parameter validation, specific logic is implemented by subclasses.
Signature
static testConnection(options?: any): Promise
load()
Signature
async load(options: any = {})
The loading operation of the data source, logic is implemented by subclasses.
createCollectionManager()
Signature
abstract createCollectionManager(options?: any): ICollectionManager
Creates a CollectionManager instance for the data source, logic is implemented by subclasses.
createResourceManager()
Creates a ResourceManager instance for the data source, subclasses can override the implementation, by default creates ResourceManager from @nocobase/resourcer.
createACL()
- Creates an ACL instance for the DataSource, subclasses can override the implementation, by default creates
ACLfrom@nocobase/acl.
File: docs/en-US/api/data-source-manager/i-collection-manager.md
ICollectionManager
The ICollectionManager interface is used to manage Collection instances of data sources.
API
registerFieldTypes()
Registers the field types in a Collection.
Signature
registerFieldTypes(types: Record<string, any>): void
registerFieldInterfaces()
Registers the Interface for a Collection.
Signature
registerFieldInterfaces(interfaces: Record<string, any>): void
registerCollectionTemplates()
Registers Collection Templates.
Signature
registerCollectionTemplates(templates: Record<string, any>): void
registerModels()
Registers Models.
Signature
registerModels(models: Record<string, any>): void
registerRepositories()
Registers Repositories.
Signature
registerRepositories(repositories: Record<string, any>): void
getRegisteredRepository()
Retrieves an instance of a registered repository.
Signature
getRegisteredRepository(key: string): IRepository
defineCollection()
Defines a Collection.
Signature
defineCollection(options: CollectionOptions): ICollection
extendCollection()
Modifies an existing Collection property.
Signature
extendCollection(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions): ICollection
hasCollection()
Determines if a Collection exists.
Signature
hasCollection(name: string): boolean
getCollection()
Retrieves an instance of a Collection.
Signature
getCollection(name: string): ICollection
getCollections()
Retrieves all instances of Collection.
Signature
getCollections(): Array
getRepository()
Retrieves an instance of a Repository.
Signature
getRepository(name: string, sourceId?: string | number): IRepository
sync()
Synchronizes the data source, with the logic implemented by subclasses.
Signature
sync(): Promise<void>
File: docs/en-US/api/data-source-manager/i-collection.md
ICollection
ICollection is an interface for data models, which includes information such as the model's name, fields, associations, etc.
export interface ICollection {
repository: IRepository;
updateOptions(options: any): void;
setField(name: string, options: any): IField;
removeField(name: string): void;
getFields(): Array<IField>;
getField(name: string): IField;
[key: string]: any;
}Members
repository
The Repository instance to which ICollection belongs.
API
updateOptions()
Updates the properties of the Collection.
Signature
updateOptions(options: any): void
setField()
Sets a field of the Collection.
Signature
setField(name: string, options: any): IField
removeField()
Removes a field from the Collection.
Signature
removeField(name: string): void
getFields()
Retrieves all fields of the Collection.
Signature
getFields(): Array
getField()
Retrieves a field of the Collection by name.
Signature
getField(name: string): IField
File: docs/en-US/api/data-source-manager/i-field.md
IField
IField defines the interface that fields need to implement.
export type FieldOptions = {
name: string;
field: string;
rawType: string;
type: string;
description?: string;
interface?: string;
uiSchema?: any;
possibleTypes?: string[];
defaultValue?: any;
primaryKey: boolean;
unique: boolean;
allowNull?: boolean;
autoIncrement?: boolean;
[key: string]: any;
};
export interface IField {
options: FieldOptions;
}Properties
options
- Type:
FieldOptions
File: docs/en-US/api/data-source-manager/i-model.md
IModel
The IModel interface defines the basic properties and methods of a model object.
export interface IModel {
toJSON: () => any;
}API
toJSON()
Converts the model object to JSON format.
File: docs/en-US/api/data-source-manager/i-repository.md
IRepository
The Repository interface defines a series of model operation methods for adapting CRUD (Create, Read, Update, Delete) operations on data sources.
API
find()
Returns a list of models that match the query parameters.
Signature
find(options?: any): Promise
findOne()
Returns the first model that matches the query parameters. If multiple models match, only the first one is returned.
Signature
findOne(options?: any): Promise
count()
Returns the number of models that match the query parameters.
Signature
count(options?: any): Promise<Number>
findAndCount()
Returns both the list of models and the count of models that match the query parameters.
Signature
findAndCount(options?: any): Promise<[IModel[], Number]>
create()
Creates a model data object.
Signature
create(options: any): void
update()
Updates the model data object based on the query conditions.
Signature
update(options: any): void
destroy()
Deletes the model data object based on the query conditions.
Signature
destroy(options: any): void
File: docs/en-US/api/data-source-manager/index.md
DataSourceManager
DataSourceManager is a management class for multiple dataSource instances.
API
add()
Adds a dataSource instance.
Signature
add(dataSource: DataSource, options: any = {}): Promise<void>
use()
Adds a global middleware to the dataSource instance.
middleware()
Retrieves the middleware of the current dataSourceManager instance, which can be used to respond to HTTP requests.
afterAddDataSource()
A hook function that is triggered after a new dataSource is added.
Signature
afterAddDataSource(hook: DataSourceHook)
type DataSourceHook = (dataSource: DataSource) => void;registerDataSourceType()
Registers the data source type and its class.
Signature
registerDataSourceType(type: string, dataSourceClass: typeof DataSource)
getDataSourceType()
Retrieves the data source class.
Signature
getDataSourceType(type: string): typeof DataSource
buildDataSourceByType()
Creates a data source instance based on the registered data source type and instance parameters.
Signature
buildDataSourceByType(type: string, options: any): DataSource
File: docs/en-US/api/database/collection.md
Collection
Overview
Collection is used to define the data model in the system, such as model name, fields, indexes, associations, and other information. It is usually called through the collection method of the Database instance as a proxy entry.
const { Database } = require('@nocobase/database')
// Create database instance
const db = new Database({...});
// Define data model
db.collection({
name: 'users',
// Define model fields
fields: [
// Scalar field
{
name: 'name',
type: 'string',
},
// Association field
{
name: 'profile',
type: 'hasOne' // 'hasMany', 'belongsTo', 'belongsToMany'
}
],
});Refer to Fields for more field types.
Constructor
Signature
constructor(options: CollectionOptions, context: CollectionContext)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.name |
string |
- | Identifier of the collection |
options.tableName? |
string |
- | Database table name, the value of options.name is used if not set |
options.fields? |
FieldOptions[] |
- | Definition of fields, refer to Field for details |
options.model? |
string | ModelStatic<Model> |
- | Model type of Sequelize; in case string is used, this model name needs to be registered in the db before being called |
options.repository? |
string | RepositoryType |
- | Data repository type; in case string is used, this repository type needs to be registered in the db before being called |
options.sortable? |
string | boolean | { name?: string; scopeKey?: string } |
- | Configure which fields are sortable; not sortable by default |
options.autoGenId? |
boolean |
true |
Whether to automatically generate unique primary key; true by default |
context.database |
Database |
- | The context database in which it resides |
Example
Create a table posts:
const posts = new Collection(
{
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
{
type: 'double',
name: 'price',
},
],
},
{
// An existing database instance
database: db,
},
);Instance Members
`options`
Initial parameters for data table configuration, which are consistent with the options parameter of the constructor.
`context`
The contextual environment to which the current data table belongs, currently mainly the database instance.
`name`
Name of the data table.
`db`
The database instance to which it belongs.
`filterTargetKey`
Name of the field that is used as the primary key.
`isThrough`
Whether it is an intermediate table.
`model`
Match the Model type of Sequelize.
`repository`
Data repository instance.
Field Configuration Methods
`getField()`
Get a field object whose corresponding name has been defined in the data table.
Signature
getField(name: string): Field
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
const field = posts.getField('title');`setField()`
Set a field to the data table.
Signature
setField(name: string, options: FieldOptions): Field
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
options |
FieldOptions |
- | Configuration of the field, refer to Field for details |
Example
const posts = db.collection({ name: 'posts' });
posts.setField('title', { type: 'string' });`setFields()`
Set multiple fields to the data table.
Signature
setFields(fields: FieldOptions[], resetFields = true): Field[]
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
fields |
FieldOptions[] |
- | Configuration of the fields, refer to Field for details |
resetFields |
boolean |
true |
Whether to reset existing fields |
Example
const posts = db.collection({ name: 'posts' });
posts.setFields([
{ type: 'string', name: 'title' },
{ type: 'double', name: 'price' },
]);`removeField()`
Remove a field object whose corresponding name has been defined in the data table.
Signature
removeField(name: string): void | Field
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.removeField('title');`resetFields()`
Reset (Empty) fields of the data table.
Signature
resetFields(): void
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.resetFields();`hasField()`
Check if the data table has defined a field object with the corresponding name.
Signature
hasField(name: string): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the field |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.hasField('title'); // true`findField()`
Find field objects in the data table that match the conditions.
Signature
findField(predicate: (field: Field) => boolean): Field | undefined
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
predicate |
(field: Field) => boolean |
- | The condition |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.findField((field) => field.name === 'title');`forEachField()`
Iterate over field objects in the data table.
Signature
forEachField(callback: (field: Field) => void): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
callback |
(field: Field) => void |
- | Callback function |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.forEachField((field) => console.log(field.name));Index Configuration Methods
`addIndex()`
Add data table index.
Signature
addIndex(index: string | string[] | { fields: string[], unique?: boolean,[key: string]: any })
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
index |
string | string[] |
- | Names of fields to be indexed |
index |
{ fields: string[], unique?: boolean, [key: string]: any } |
- | Full configuration |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.addIndex({
fields: ['title'],
unique: true,
});`removeIndex()`
Remove data table index.
Signature
removeIndex(fields: string[])
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
fields |
string[] |
- | Names of fields to remove indexes |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
indexes: [
{
fields: ['title'],
unique: true,
},
],
});
posts.removeIndex(['title']);Table Configuration Methods
`remove()`
Remove data table.
Signature
remove(): void
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
posts.remove();Database Operation Methods
`sync()`
Synchronize the definitions in data table to the database. In addition to the default Model.sync logic in Sequelize, the data tables corresponding to the relational fields will also be handled together.
Signature
sync(): Promise<void>
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
await posts.sync();`existsInDb()`
Check whether the data table exists in the database.
Signature
existsInDb(options?: Transactionable): Promise
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options?.transaction |
Transaction |
- | Transaction instance |
Example
const posts = db.collection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
],
});
const existed = await posts.existsInDb();
console.log(existed); // false`removeFromDb()`
Signature
removeFromDb(): Promise<void>
Example
const books = db.collection({
name: 'books',
});
// Synchronize the table books to the database
await db.sync();
// Remove the table books from the database
await books.removeFromDb();File: docs/en-US/api/database/field.md
Field
Overview
Data table field management class (abstract class). It is also the base class for all field types, and any other field types are implemented by inheriting from this class.
Refer to Extended Field Types to see how to customize fields.
Constructor
It is usually not called directly by the developer, but mainly through the db.collection({ fields: [] }) method as a proxy entry.
Extended field is implemented mainly by inheriting the Field abstract class and registering it to a Database instance.
Signature
constructor(options: FieldOptions, context: FieldContext)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options |
FieldOptions |
- | Field configuration object |
options.name |
string |
- | Field name |
options.type |
string |
- | Field type, corresponding to the name of the field type registered in the db |
context |
FieldContext |
- | Field context object |
context.database |
Database |
- | Database instance |
context.collection |
Collection |
- | Data table instance |
Instance Members
`name`
Field name.
`type`
Field type.
`dataType`
Data type of the field.
`options`
Configuration parameters to initialize the field.
`context`
Field context object.
Configuration Methods
`on()`
Quick definition method based on data table events. It is equivalent to db.on(this.collection.name + '.' + eventName, listener).
It is usually not necessary to override this method when inheriting.
Signature
on(eventName: string, listener: (...args: any[]) => void)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
eventName |
string |
- | Event name |
listener |
(...args: any[]) => void |
- | Event listener |
`off()`
Quick removal method based on data table events. It is equivalent to db.off(this.collection.name + '.' + eventName, listener).
It is usually not necessary to override this method when inheriting.
Signature
off(eventName: string, listener: (...args: any[]) => void)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
eventName |
string |
- | Event name |
listener |
(...args: any[]) => void |
- | Event listener |
`bind()`
The execution content that is triggered when a field is added to data table. Typically used to add data table event listeners and other processing.
The corresponding super.bind() method needs to be called first when inheriting.
Signature
bind()
`unbind()`
The execution content that is triggered when a field is removed from data table. Typically used to remove data table event listeners and other processing.
The corresponding super.unbind() method needs to be called first when inheriting.
Signature
unbind()
`get()`
Get the values of a configuration item of the field.
Signature
get(key: string): any
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
key |
string |
- | Name of the configuration item |
Example
const field = db.collection('users').getField('name');
// Get and return the values of the configuration item 'name'
console.log(field.get('name'));`merge()`
Merge the values of a configuration item of the field.
Signature
merge(options: { [key: string]: any }): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options |
{ [key: string]: any } |
- | The configuration item to merge |
Example
const field = db.collection('users').getField('name');
field.merge({
// Add an index configuration
index: true,
});`remove()`
Remove a field from data table (from memory only).
Example
const books = db.getCollections('books');
books.getField('isbn').remove();
// really remove from db
await books.sync();Database Methods
`removeFromDb()`
Remove a field from the database.
Signature
removeFromDb(options?: Transactionable): Promise<void>
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.transaction? |
Transaction |
- | Transaction instance |
`existsInDb()`
Check if a field exists in the database.
Signature
existsInDb(options?: Transactionable): Promise
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.transaction? |
Transaction |
- | Transaction instance |
Built-in Field Types
NocoBase has some built-in common field types, the corresponding type name can be used directly to specify the type of field upon definition. Fields of different types are configured differently, please refer to the list below.
The configuration items of all field types are passed through to Sequelize in addition to those described below. Therefore, all field configuration items supported by Sequelize can be used here (e.g. allowNull, defaultValue, etc.).
Moreover, server-side field types are mainly used for solving the problems of database storage and some algorithms, they are barely relevant to the field display types and the use of components in front-end. The front-end field types can be found in the corresponding tutorials.
`'boolean'`
Boolean type.
Example
db.collection({
name: 'books',
fields: [
{
type: 'boolean',
name: 'published',
},
],
});`'integer'`
Integer type (32 bits).
Example
db.collection({
name: 'books',
fields: [
{
type: 'integer',
name: 'pages',
},
],
});`'bigInt'`
Long integer type (64 bits).
Example
db.collection({
name: 'books',
fields: [
{
type: 'bigInt',
name: 'words',
},
],
});`'double'`
Double-precision floating-point format (64 bits).
Example
db.collection({
name: 'books',
fields: [
{
type: 'double',
name: 'price',
},
],
});`'real'`
Real type (PG only).
`'decimal'`
Decimal type.
`'string'`
String type. Equivalent to the VARCHAR type for most databases.
Example
db.collection({
name: 'books',
fields: [
{
type: 'string',
name: 'title',
},
],
});`'text'`
Text type. Equivalent to the TEXT type for most databases.
Example
db.collection({
name: 'books',
fields: [
{
type: 'text',
name: 'content',
},
],
});`'password'`
Password type (NocoBase extension). Password encryption based on the scrypt method of Node.js native crypto packages.
Example
db.collection({
name: 'users',
fields: [
{
type: 'password',
name: 'password',
length: 64, // Length, default is 64
randomBytesSize: 8, // Length of random bytes, default is 8
},
],
});Parameter
| Name | Type | Default | Description |
|---|---|---|---|
length |
number |
64 | Length of characters |
randomBytesSize |
number |
8 | Length of random bytes |
`'date'`
Date type.
`'time'`
Time type.
`'array'`
Array type (PG only).
`'json'`
JSON type.
`'jsonb'`
JSONB type (PG only, others will be compatible with the 'json' type).
`'uuid'`
UUID type.
`'uid'`
UID type (NocoBase extension). Short random string identifier type.
`'formula'`
Formula type (NocoBase extension). Mathematical formula calculation can be configured based on mathjs, and the formula can refer to the values of other columns in the same record to participate in the calculation.
Example
db.collection({
name: 'orders',
fields: [
{
type: 'double',
name: 'price',
},
{
type: 'integer',
name: 'quantity',
},
{
type: 'formula',
name: 'total',
expression: 'price * quantity',
},
],
});`'radio'`
Radio type (NocoBase extension). The field value is 'true' for at most one row of data for the full table, all others are 'false' or 'null'.
Example
There is only one user marked as root in the entire system, once the root value of any other user is changed to true, all other records with root of true will be changed to false:
db.collection({
name: 'users',
fields: [
{
type: 'radio',
name: 'root',
},
],
});`'sort'`
Sorting type (NocoBase extension). Sorting based on integer numbers, automatically generating new serial numbers for new records, and rearranging serial numbers when moving data.
If data table has the sortable option defined, the corresponding fields will be generated automatically.
Example
Posts are sortable based on the users they belong to.
db.collection({
name: 'posts',
fields: [
{
type: 'belongsTo',
name: 'user',
},
{
type: 'sort',
name: 'priority',
scopeKey: 'userId', // Sort data grouped by the values of userId
},
],
});`'virtual'`
Virtual type. No Data is actually stored, it is used only when special getter/setter is defined.
`'belongsTo'`
Many-to-one association type. Foreign key is stored in its own table, as opposed to 'hasOne'/'hasMany'.
Example
Any post belongs to an author:
db.collection({
name: 'posts',
fields: [
{
type: 'belongsTo',
name: 'author',
target: 'users', // Default table name is the plural form of <name>
foreignKey: 'authorId', // Default is '<name> + Id'
sourceKey: 'id', // Default is id of the <target> table
},
],
});`'hasOne'`
One-to-one association type. Foreign key is stored in the association table, as opposed to 'belongsTo'.
Example
Any user has a profile:
db.collection({
name: 'users',
fields: [
{
type: 'hasOne',
name: 'profile',
target: 'profiles', // Can be omitted
},
],
});`'hasMany'`
One-to-many association type. The foreign key is stored in the association table, as opposed to 'belongsTo'.
Example
Any user can have multiple posts:
db.collection({
name: 'users',
fields: [
{
type: 'hasMany',
name: 'posts',
foreignKey: 'authorId',
sourceKey: 'id',
},
],
});`'belongsToMany'`
Many-to-many association type. Intermediate table is used to store both foreign keys. If no existing table is specified as intermediate table, it will be created automatically.
Example
Any post can have multiple tags added to it, and any tag can be added to multiple posts:
db.collection({
name: 'posts',
fields: [
{
type: 'belongsToMany',
name: 'tags',
target: 'tags', // Can be omitted if name is the same
through: 'postsTags', // Intermediate table will be generated automatically if not specified
foreignKey: 'postId', // Foreign key in the intermediate table referring to the table itself
sourceKey: 'id', // Primary key of the table itself
otherKey: 'tagId', // Foreign key in the intermediate table referring to the association table
},
],
});
db.collection({
name: 'tags',
fields: [
{
type: 'belongsToMany',
name: 'posts',
through: 'postsTags', // Refer to the same intermediate table in the same set of relation
},
],
});File: docs/en-US/api/database/index.md
Database
Overview
Database is the database interaction tool provided by NocoBase, it provides very convenient database interaction features for no-code and low-code applications. The supported databases are:
- SQLite 3.8.8+
- MySQL 8.0.17+
- PostgreSQL 10.0+
Connect to Database
In Database constructor, database connection can be configured by passing the options parameter.
const { Database } = require('@nocobase/database');
// MySQL database configuration parameters
const database = new Database({
dialect: 'mysql',
host: 'localhost',
port: 3306,
database: 'nocobase',
username: 'root',
password: 'password'
})
// MySQL \ PostgreSQL database configuration parameters
const database = new Database({
dialect: /* 'postgres' or 'mysql' */,
database: 'database',
username: 'username',
password: 'password',
host: 'localhost',
port: 'port'
})Refer to Constructor for detailed configurations.
Define Data Structure
Database defines database structure through Collection, one Collection object represents one table in the database.
// Define Collection
const UserCollection = database.collection({
name: 'users',
fields: [
{
name: 'name',
type: 'string',
},
{
name: 'age',
type: 'integer',
},
],
});After the database structure is defined, use sync() method to synchronize the database structure.
await database.sync();Refer to Collection for detailed usage of Collection.
CRUD Data
Database operates data through Repository.
const UserRepository = UserCollection.repository();
// Create
await UserRepository.create({
name: 'Mark',
age: 18,
});
// Query
const user = await UserRepository.findOne({
filter: {
name: 'Mark',
},
});
// Update
await UserRepository.update({
values: {
age: 20,
},
});
// Delete
await UserRepository.destroy(user.id);Refer to Repository for details of data CRUD.
Constructor
Signature
constructor(options: DatabaseOptions)
Create a database instance.
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.host |
string |
'localhost' |
Database host |
options.port |
number |
- | Database service port, default port depends on the type of database used |
options.username |
string |
- | Database username |
options.password |
string |
- | Database password |
options.database |
string |
- | Database name |
options.dialect |
string |
'mysql' |
Database type |
options.storage? |
string |
':memory:' |
Storage mode for SQLite |
options.logging? |
boolean |
false |
Whether to enable logging |
options.define? |
Object |
{} |
Default table definition parameters |
options.tablePrefix? |
string |
'' |
NocoBase extension, table prefix |
options.migrator? |
UmzugOptions |
{} |
NocoBase extension, parameters for migrator, refer to Umzug for the implementation |
Migration Methods
`addMigration()`
Add single migration file.
Signature
addMigration(options: MigrationItem)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.name |
string |
- | Name of the migration file |
options.context? |
string |
- | Context of the migration file |
options.migration? |
typeof Migration |
- | Custom type of the migration file |
options.up |
Function |
- | up method of the migration file |
options.down |
Function |
- | down method of the migration file |
Example
db.addMigration({
name: '20220916120411-test-1',
async up() {
const queryInterface = this.context.db.sequelize.getQueryInterface();
await queryInterface.query(/* your migration sqls */);
},
});`addMigrations()`
Add the migration files in the specified directory.
Signature
addMigrations(options: AddMigrationsOptions): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.directory |
string |
'' |
Directory where the migration files are located |
options.extensions |
string[] |
['js', 'ts'] |
File extensions |
options.namespace? |
string |
'' |
Namespace |
options.context? |
Object |
{ db } |
Context of the migration files |
Example
db.addMigrations({
directory: path.resolve(__dirname, './migrations'),
namespace: 'test',
});Tool Methods
`inDialect()`
Check whether the current database type is the specified type.
Signature
inDialect(dialect: string[]): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
dialect |
string[] |
- | Database type, options are mysql, postgres and mariadb |
`getTablePrefix()`
Get the table name prefix in the configuration.
Signature
getTablePrefix(): string
Data Table Configurations
`collection()`
Define a data table. This is like the define method of Sequelize, which only creates table structure in memory. Call the sync method if needs to be persisted to the database.
Signature
collection(options: CollectionOptions): Collection
Parameter
All configuration parameters of options is consistent with the constructor of the Collection class, refer to Collection.
Event
'beforeDefineCollection': Trigger before defining the table.'afterDefineCollection': Trigger after defining the table.
Example
db.collection({
name: 'books',
fields: [
{
type: 'string',
name: 'title',
},
{
type: 'float',
name: 'price',
},
],
});
// sync collection as table to db
await db.sync();`getCollection()`
Get a defined data table.
Signature
getCollection(name: string): Collection
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Table name |
Example
const collection = db.getCollection('books');`hasCollection()`
Check whether a specified data table is defined.
Signature
hasCollection(name: string): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Table name |
Example
db.collection({ name: 'books' });
db.hasCollection('books'); // true
db.hasCollection('authors'); // false`removeCollection()`
Remove a defined data table. It is to remove from memory only, call the sync method if needs to be persisted to the database.
Signature
removeCollection(name: string): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Table name |
Event
'beforeRemoveCollection': Trigger before removing the table.'afterRemoveCollection': Trigger after removing the table
Example
db.collection({ name: 'books' });
db.removeCollection('books');`import()`
Load all files in the import file directory into memory as the configuration of collection.
Signature
async import(options: { directory: string; extensions?: ImportFileExtension[] }): Promise<Map<string, Collection>>
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.directory |
string |
- | Path of directory to be imported |
options.extensions |
string[] |
['ts', 'js'] |
Scan for specific suffixes |
Example
The collection defined by file ./collections/books.ts is as below:
export default {
name: 'books',
fields: [
{
type: 'string',
name: 'title',
},
],
};Import the relevant configurations when loading the plugin:
class Plugin {
async load() {
await this.app.db.import({
directory: path.resolve(__dirname, './collections'),
});
}
}Extension Registrations and Acquisitions
`registerFieldTypes()`
Register custom field type.
Signature
registerFieldTypes(fieldTypes: MapOf<typeof Field>): void
Parameter
fieldTypes is a key-value pair, where key is the field type name, and value is the field type class.
Example
import { Field } from '@nocobase/database';
class MyField extends Field {
// ...
}
db.registerFieldTypes({
myField: MyField,
});`registerModels()`
Register custom data model class.
Signature
registerModels(models: MapOf<ModelStatic<any>>): void
Parameter
models is a key-value pair, where key is the data model name, and value is the data model class.
Example
import { Model } from '@nocobase/database';
class MyModel extends Model {
// ...
}
db.registerModels({
myModel: MyModel,
});
db.collection({
name: 'myCollection',
model: 'myModel',
});`registerRepositories()`
Register custom data repository class.
Signature
registerRepositories(repositories: MapOf<RepositoryType>): void
Parameter
repositories is a key-value pair, where key is the data repository name, and value is the data repository class.
Example
import { Repository } from '@nocobase/database';
class MyRepository extends Repository {
// ...
}
db.registerRepositories({
myRepository: MyRepository,
});
db.collection({
name: 'myCollection',
repository: 'myRepository',
});`registerOperators()`
Register custom data query operator.
Signature
registerOperators(operators: MapOf<OperatorFunc>)
Parameter
operators is a key-value pair, where key is the operator name, and value is the generating function of the comparison operator statement.
Example
db.registerOperators({
$dateOn(value) {
return {
[Op.and]: [
{ [Op.gte]: stringToDate(value) },
{ [Op.lt]: getNextDay(value) },
],
};
},
});
db.getRepository('books').count({
filter: {
createdAt: {
// registered operator
$dateOn: '2020-01-01',
},
},
});`getModel()`
Get the defined data model class. If no custom model class has been registered before, the default model class of Sequelize will be returned. The default name is the same as the name defined by collection.
Signature
getModel(name: string): Model
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Registered model name |
Example
db.registerModels({
books: class MyModel extends Model {},
});
const ModelClass = db.getModel('books');
console.log(ModelClass.prototype instanceof MyModel); // trueNote: The model class retrieved from collection is not strictly equivalent to the model class at registration, but is inherited from the model class at registration. Since the properties of Sequelize's model class are modified during initialization, NocoBase automatically handles this inheritance relationship. All the definitions work fine except that the classes are not equal.
`getRepository()`
Get the defined data repository class. If no custom data repository class has been registered before, the default data repository class of NocoBase will be returned. The default name is the same as the name defined by collection.
Data repository class is mainly used for the CRUD operations based on data model, refer to Repository.
Signature
getRepository(name: string): RepositorygetRepository(name: string, relationId?: string | number): Repository
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Registered data repository name |
relationId |
string | number |
- | Foreign key value for relational data |
When the name contains relationship in the form of 'tables.relactions', the related data repository class is returned. If the second parameter is provided, the data repository will be used (query, modify, etc.) based on the foreign key values of the relational data.
Example
Suppose there are two data tables posts and authors, and there is a foreign key in the posts table points to the authors table:
const AuthorsRepo = db.getRepository('authors');
const author1 = AuthorsRepo.create({ name: 'author1' });
const PostsRepo = db.getRepository('authors.posts', author1.id);
const post1 = AuthorsRepo.create({ title: 'post1' });
asset(post1.authorId === author1.id); // trueDatabase Events
`on()`
Listen for database events.
Signature
on(event: string, listener: (...args: any[]) => void | Promise<void>): void
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
| event | string | - | Event name |
| listener | Function | - | Event listener |
Event name supports Model event of Sequelize by default. Global event is listened to by the name <sequelize_model_global_event>, single Model event is listened to by the name <model_name>. <sequelize_model_event>.
Refer to the Built-in Events section for parameter descriptions and detailed examples of all built-in event types.
`off()`
Remove the event listener function.
Signature
off(name: string, listener: Function)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
| name | string | - | Event name |
| listener | Function | - | Event listener |
Example
const listener = async (model, options) => {
console.log(model);
};
db.on('afterCreate', listener);
db.off('afterCreate', listener);Database Operations
`auth()`
Database connection verification. It can be used to ensure that the application has established connection to the data.
Signature
auth(options: QueryOptions & { retry?: number } = {}): Promise
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options? |
Object |
- | Verification option |
options.retry? |
number |
10 |
Number of retries in case of verification failure |
options.transaction? |
Transaction |
- | Transaction object |
options.logging? |
boolean | Function |
false |
Whether to print the log |
Example
await db.auth();`reconnect()`
Reconnect to the database.
Example
await db.reconnect();`closed()`
Check whether database has closed the connection.
Signature
closed(): boolean
`close()`
Closes database connection. Equivalent to sequelize.close().
`sync()`
Synchronizes database table structure. Equivalent to sequelize.sync(), refer to Sequelize documentation for parameters.
`clean()`
Empty the database, it will delete all data tables.
Signature
clean(options: CleanOptions): Promise<void>
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options.drop |
boolean |
false |
Whether to remove all data tables |
options.skip |
string[] |
- | Names of tables to skip |
options.transaction |
Transaction |
- | Transaction object |
Example
Remove all tables except for the users table.
await db.clean({
drop: true,
skip: ['users'],
});Package-Level Export
`defineCollection()`
Create the configuration content of a data table.
Signature
defineCollection(name: string, config: CollectionOptions): CollectionOptions
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
collectionOptions |
CollectionOptions |
- | All parameters are the same with db.collection() |
Example
For the data table configuration file to be imported by db.import():
import { defineCollection } from '@nocobase/database';
export default defineCollection({
name: 'users',
fields: [
{
type: 'string',
name: 'name',
},
],
});`extendCollection()`
Extent the configuration content of a data table that is already in memory, mainly for the content of files imported by the import() method. This is the top-level package export method of @nocobase/database, and is not called through db instance. The extend alias can also be used.
Signature
extendCollection(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions): ExtendedCollectionOptions
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
collectionOptions |
CollectionOptions |
- | All the same with db.collection() |
mergeOptions? |
MergeOptions |
- | deepmerge options of npm package |
Example
Original definition of the table books (books.ts):
export default {
name: 'books',
fields: [{ name: 'title', type: 'string' }],
};Extend the definition of the table books (books.extend.ts):
import { extend } from '@nocobase/database';
// Extend again
export default extend({
name: 'books',
fields: [{ name: 'price', type: 'number' }],
});If the above two files are imported when calling import(), after being extended again by extend(), the table books will have title and price two fields.
This method is especially useful when extending the table structure that is already defined by existing plugin.
Built-in Events
The following events will be triggered in the corresponding lifecycle of database, subscribe by the on() method and perform specific processing to meet some business needs.
`'beforeSync'` / `'afterSync'`
Events triggered before or after a new table structure configuration (fields, indexes, etc.) is synchronized to the database. This is usually triggered when executing collection.sync() (internal call) for the logical processing of the extension of some special fields.
Signature
on(eventName: `${string}.beforeSync` | 'beforeSync' | `${string}.afterSync` | 'afterSync', listener: SyncListener): thisType
import type { SyncOptions, HookReturn } from 'sequelize/types';
type SyncListener = (options?: SyncOptions) => HookReturn;Example
const users = db.collection({
name: 'users',
fields: [{ type: 'string', name: 'username' }],
});
db.on('beforeSync', async (options) => {
// do something
});
db.on('users.afterSync', async (options) => {
// do something
});
await users.sync();`'beforeValidate'` / `'afterValidate'`
Before creating or updating data, there is a validation against the data based on the rules defined by the collection, and the corresponding events are triggered before and after the validation. This is triggered when repository.create() or repository.update() is called.
Signature
on(eventName: `${string}.beforeValidate` | 'beforeValidate' | `${string}.afterValidate` | 'afterValidate', listener: ValidateListener): thisType
import type { ValidationOptions } from 'sequelize/types/lib/instance-validator';
import type { HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
type ValidateListener = (
model: Model,
options?: ValidationOptions,
) => HookReturn;Example
db.collection({
name: 'tests',
fields: [
{
type: 'string',
name: 'email',
validate: {
isEmail: true,
},
},
],
});
// all models
db.on('beforeValidate', async (model, options) => {
// do something
});
// tests model
db.on('tests.beforeValidate', async (model, options) => {
// do something
});
// all models
db.on('afterValidate', async (model, options) => {
// do something
});
// tests model
db.on('tests.afterValidate', async (model, options) => {
// do something
});
const repository = db.getRepository('tests');
await repository.create({
values: {
email: 'abc', // checks for email format
},
});
// or
await repository.update({
filterByTk: 1,
values: {
email: 'abc', // checks for email format
},
});`'beforeCreate'` / `'afterCreate'`
Events triggered before or after creating one piece of data. This is triggered when repository.create() is called.
Signature
on(eventName: `${string}.beforeCreate` | 'beforeCreate' | `${string}.afterCreate` | 'afterCreate', listener: CreateListener): thisType
import type { CreateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type CreateListener = (
model: Model,
options?: CreateOptions,
) => HookReturn;Example
db.on('beforeCreate', async (model, options) => {
// do something
});
db.on('books.afterCreate', async (model, options) => {
const { transaction } = options;
const result = await model.constructor.findByPk(model.id, {
transaction,
});
console.log(result);
});`'beforeUpdate'` / `'afterUpdate'`
Events triggered before or after updating one piece of data. This is triggered when repository.update() is called.
Signature
on(eventName: `${string}.beforeUpdate` | 'beforeUpdate' | `${string}.afterUpdate` | 'afterUpdate', listener: UpdateListener): thisType
import type { UpdateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type UpdateListener = (
model: Model,
options?: UpdateOptions,
) => HookReturn;Example
db.on('beforeUpdate', async (model, options) => {
// do something
});
db.on('books.afterUpdate', async (model, options) => {
// do something
});`'beforeSave'` / `'afterSave'`
Events triggered before or after creating or updating one piece of data. This is triggered when repository.create() or repository.update() is called.
Signature
on(eventName: `${string}.beforeSave` | 'beforeSave' | `${string}.afterSave` | 'afterSave', listener: SaveListener): thisType
import type { SaveOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type SaveListener = (model: Model, options?: SaveOptions) => HookReturn;Example
db.on('beforeSave', async (model, options) => {
// do something
});
db.on('books.afterSave', async (model, options) => {
// do something
});`'beforeDestroy'` / `'afterDestroy'`
Events triggered before or after deleting one piece of data. This is triggered when repository.destroy() is called.
Signature
on(eventName: `${string}.beforeDestroy` | 'beforeDestroy' | `${string}.afterDestroy` | 'afterDestroy', listener: DestroyListener): thisType
import type { DestroyOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type DestroyListener = (
model: Model,
options?: DestroyOptions,
) => HookReturn;Example
db.on('beforeDestroy', async (model, options) => {
// do something
});
db.on('books.afterDestroy', async (model, options) => {
// do something
});`'afterCreateWithAssociations'`
Events triggered after creating one piece of data that carries hierarchical data. This is triggered when repository.create() is called.
Signature
on(eventName: `${string}.afterCreateWithAssociations` | 'afterCreateWithAssociations', listener: CreateWithAssociationsListener): thisType
import type { CreateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type CreateWithAssociationsListener = (
model: Model,
options?: CreateOptions,
) => HookReturn;Example
db.on('afterCreateWithAssociations', async (model, options) => {
// do something
});
db.on('books.afterCreateWithAssociations', async (model, options) => {
// do something
});`'afterUpdateWithAssociations'`
Events triggered after updating one piece of data that carries hierarchical data. This is triggered when repository.update() is called.
Signature
on(eventName: `${string}.afterUpdateWithAssociations` | 'afterUpdateWithAssociations', listener: CreateWithAssociationsListener): thisType
import type { UpdateOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type UpdateWithAssociationsListener = (
model: Model,
options?: UpdateOptions,
) => HookReturn;Example
db.on('afterUpdateWithAssociations', async (model, options) => {
// do something
});
db.on('books.afterUpdateWithAssociations', async (model, options) => {
// do something
});`'afterSaveWithAssociations'`
Events triggered after creating or updating one piece of data that carries hierarchical data. This is triggered when repository.create() or repository.update() is called.
Signature
on(eventName: `${string}.afterSaveWithAssociations` | 'afterSaveWithAssociations', listener: SaveWithAssociationsListener): thisType
import type { SaveOptions, HookReturn } from 'sequelize/types';
import type { Model } from '@nocobase/database';
export type SaveWithAssociationsListener = (
model: Model,
options?: SaveOptions,
) => HookReturn;Example
db.on('afterSaveWithAssociations', async (model, options) => {
// do something
});
db.on('books.afterSaveWithAssociations', async (model, options) => {
// do something
});`'beforeDefineCollection'`
Events triggered before defining a data table, such as when db.collection() is called.
Note: This is a synchronous event.
Signature
on(eventName: 'beforeDefineCollection', listener: BeforeDefineCollectionListener): thisType
import type { CollectionOptions } from '@nocobase/database';
export type BeforeDefineCollectionListener = (
options: CollectionOptions,
) => void;Example
db.on('beforeDefineCollection', (options) => {
// do something
});`'afterDefineCollection'`
Events triggered after defining a data table, such as when db.collection() is called.
Note: This is a synchronous event.
Signature
on(eventName: 'afterDefineCollection', listener: AfterDefineCollectionListener): thisType
import type { Collection } from '@nocobase/database';
export type AfterDefineCollectionListener = (options: Collection) => void;Example
db.on('afterDefineCollection', (collection) => {
// do something
});`'beforeRemoveCollection'` / `'afterRemoveCollection'`
Events triggered before or after removing a data table from memory, such as when db.removeCollection() is called.
Note: This is a synchronous event.
Signature
on(eventName: 'beforeRemoveCollection' | 'afterRemoveCollection', listener: RemoveCollectionListener): thisType
import type { Collection } from '@nocobase/database';
export type RemoveCollectionListener = (options: Collection) => void;Example
db.on('beforeRemoveCollection', (collection) => {
// do something
});
db.on('afterRemoveCollection', (collection) => {
// do something
});File: docs/en-US/api/database/operators.md
Filter Operators
Used in the filter parameters of the find, findOne, findAndCount, count, etc. APIs of repository:
const repository = db.getRepository('books');
repository.find({
filter: {
title: {
$eq: 'Spring and Autumn',
},
},
});To support JSON, NocoBase identifies query operators as a string prefixed with $.
Moreover, NocoBase provides API to extend operators. Refer to db.registerOperators().
General Operators
`$eq`
Check if the field value is equal to the specified value. Equivalent to = in SQL.
Example
repository.find({
filter: {
title: {
$eq: 'Spring and Autumn',
},
},
});Equal to title: 'Spring and Autumn'
`$ne`
Check if the field value is not equal to the specified value. Equivalent to != in SQL.
Example
repository.find({
filter: {
title: {
$ne: 'Spring and Autumn',
},
},
});`$is`
Check if the field value is the specified value. Equivalent to IS in SQL.
Example
repository.find({
filter: {
title: {
$is: null,
},
},
});`$not`
Check if the field value is not the specified value. Equivalent to IS NOT in SQL.
Example
repository.find({
filter: {
title: {
$not: null,
},
},
});`$col`
Check if the field value is equal to the value of another field. Equivalent to = in SQL.
Example
repository.find({
filter: {
title: {
$col: 'name',
},
},
});`$in`
Check if the field value is in the specified array. Equivalent to IN in SQL.
Example
repository.find({
filter: {
title: {
$in: ['Spring and Autumn', 'Warring States'],
},
},
});`$notIn`
Check if the field value is not in the specified array. Equivalent to NOT IN in SQL.
Example
repository.find({
filter: {
title: {
$notIn: ['Spring and Autumn', 'Warring States'],
},
},
});`$empty`
Check if the general field is empty. For string field, check if it is an empty string; for array field, check if it is an empty array.
Example
repository.find({
filter: {
title: {
$empty: true,
},
},
});`$notEmpty`
Check if the general field is not empty. For string field, check if it is not an empty string; for array field, check if it is not an empty array.
Example
repository.find({
filter: {
title: {
$notEmpty: true,
},
},
});Logical Operators
`$and`
Logical AND. Equivalent to AND in SQL.
Example
repository.find({
filter: {
$and: [{ title: 'Book of Songs' }, { isbn: '1234567890' }],
},
});`$or`
Logical OR. Equivalent to OR in SQL.
Example
repository.find({
filter: {
$or: [
{ title: 'Book of Songs' },
{ publishedAt: { $lt: '0000-00-00T00:00:00Z' } },
],
},
});Boolean Field Operators
For boolean fields: type: 'boolean'
`$isFalsy`
Check if a Boolean field value is false. Boolean field values of false, 0 and NULL are all judged to be $isFalsy: true.
Example
repository.find({
filter: {
isPublished: {
$isFalsy: true,
},
},
});`$isTruly`
Check if a Boolean field value is true. Boolean field values of true and 1 are all judged to be $isTruly: true.
Example
repository.find({
filter: {
isPublished: {
$isTruly: true,
},
},
});Numeric Type Field Operators
For numeric type fields, including:
type: 'integer'type: 'float'type: 'double'type: 'real'type: 'decimal'
`$gt`
Check if the field value is greater than the specified value. Equivalent to > in SQL.
Example
repository.find({
filter: {
price: {
$gt: 100,
},
},
});`$gte`
Check if the field value is equal to or greater than the specified value. Equivalent to >= in SQL.
Example
repository.find({
filter: {
price: {
$gte: 100,
},
},
});`$lt`
Check if the field value is less than the specified value. Equivalent to < in SQL.
Example
repository.find({
filter: {
price: {
$lt: 100,
},
},
});`$lte`
Check if the field value is equal to or less than the specified value. Equivalent to <= in SQL.
Example
repository.find({
filter: {
price: {
$lte: 100,
},
},
});`$between`
Check if the field value is between the specified two values. Equivalent to BETWEEN in SQL.
Example
repository.find({
filter: {
price: {
$between: [100, 200],
},
},
});`$notBetween`
Check if the field value is not between the specified two values. Equivalent to NOT BETWEEN in SQL.
Example
repository.find({
filter: {
price: {
$notBetween: [100, 200],
},
},
});String Type Field Operators
For string type fields, including string.
`$includes`
Check if the string field contains the specified substring.
Example
repository.find({
filter: {
title: {
$includes: 'Three Character Classic',
},
},
});`$notIncludes`
Check if the string field does not contain the specified substring.
Example
repository.find({
filter: {
title: {
$notIncludes: 'Three Character Classic',
},
},
});`$startsWith`
Check if the string field starts with the specified substring.
Example
repository.find({
filter: {
title: {
$startsWith: 'Three Character Classic',
},
},
});`$notStatsWith`
Check if the string field does not start with the specified substring.
Example
repository.find({
filter: {
title: {
$notStatsWith: 'Three Character Classic',
},
},
});`$endsWith`
Check if the string field ends with the specified substring.
Example
repository.find({
filter: {
title: {
$endsWith: 'Three Character Classic',
},
},
});`$notEndsWith`
Check if the string field does not end with the specified substring.
Example
repository.find({
filter: {
title: {
$notEndsWith: 'Three Character Classic',
},
},
});`$like`
Check if the field value contains the specified string. Equivalent to LIKE in SQL.
Example
repository.find({
filter: {
title: {
$like: 'Computer',
},
},
});`$notLike`
Check if the field value does not contain the specified string. Equivalent to NOT LIKE in SQL.
Example
repository.find({
filter: {
title: {
$notLike: 'Computer',
},
},
});`$iLike`
Check if a field value contains the specified string, case ignored. Equivalent to ILIKE in SQL (PG only).
Example
repository.find({
filter: {
title: {
$iLike: 'Computer',
},
},
});`$notILike`
Check if a field value does not contain the specified string, case ignored. Equivalent to NOT ILIKE in SQL (PG only).
Example
repository.find({
filter: {
title: {
$notILike: 'Computer',
},
},
});`$regexp`
Check if the field value matches the specified regular expression. Equivalent to REGEXP in SQL (PG only).
Example
repository.find({
filter: {
title: {
$regexp: '^Computer',
},
},
});`$notRegexp`
Check if the field value does not match the specified regular expression. Equivalent to NOT REGEXP in SQL (PG only).
Example
repository.find({
filter: {
title: {
$notRegexp: '^Computer',
},
},
});`$iRegexp`
Check if the field value matches the specified regular expression, case ignored. Equivalent to ~* in SQL (PG only).
Example
repository.find({
filter: {
title: {
$iRegexp: '^COMPUTER',
},
},
});`$notIRegexp`
Check if the field value does not match the specified regular expression, case ignored. Equivalent to !~* in SQL (PG only).
Example
repository.find({
filter: {
title: {
$notIRegexp: '^COMPUTER',
},
},
});Date Type Field Operators
For date type fields: type: 'date'
`$dateOn`
Check if the date field value is within a certain day.
Example
repository.find({
filter: {
createdAt: {
$dateOn: '2021-01-01',
},
},
});`$dateNotOn`
Check if the date field value is not within a certain day.
Example
repository.find({
filter: {
createdAt: {
$dateNotOn: '2021-01-01',
},
},
});`$dateBefore`
Check if the date field value is before a certain value, i.e., less than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateBefore: '2021-01-01T00:00:00.000Z',
},
},
});`$dateNotBefore`
Check if the date field value is not before a certain value, i.e., equal to or greater than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateNotBefore: '2021-01-01T00:00:00.000Z',
},
},
});`$dateAfter`
Check if the date field value is after a certain value, i.e., greater than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateAfter: '2021-01-01T00:00:00.000Z',
},
},
});`$dateNotAfter`
Check if the date field value is not after a certain value, i.e., equal to or greater than the one passed in.
Example
repository.find({
filter: {
createdAt: {
$dateNotAfter: '2021-01-01T00:00:00.000Z',
},
},
});Array Type Field Operators
For array type fields: type: 'array'
`$match`
Check if the array field values match values of the specified array.
Example
repository.find({
filter: {
tags: {
$match: ['literature', 'history'],
},
},
});`$notMatch`
Check if the array field values do not match values of the specified array.
Example
repository.find({
filter: {
tags: {
$notMatch: ['literature', 'history'],
},
},
});`$anyOf`
Check if the array field values contain any of the values of the specified array.
Example
repository.find({
filter: {
tags: {
$anyOf: ['literature', 'history'],
},
},
});`$noneOf`
Check if the array field values contain none of the values of the specified array.
Example
repository.find({
filter: {
tags: {
$noneOf: ['literature', 'history'],
},
},
});`$arrayEmpty`
Check if the array field is empty.
Example
repository.find({
filter: {
tags: {
$arrayEmpty: true,
},
},
});`$arrayNotEmpty`
Check if the array field is not empty.
Example
repository.find({
filter: {
tags: {
$arrayNotEmpty: true,
},
},
});Relational Field Type Operators
For checking if a relationship exists, field types include:
type: 'hasOne'type: 'hasMany'type: 'belongsTo'type: 'belongsToMany'
`$exists`
There is relational data existing.
Example
repository.find({
filter: {
author: {
$exists: true,
},
},
});`$notExists`
There is no relational data existing.
Example
repository.find({
filter: {
author: {
$notExists: true,
},
},
});File: docs/en-US/api/database/repository.md
Repository
Overview
On a given Collection object, you can get its Repository object to perform read and write operations on the data table.
const { UserCollection } = require('./collections');
const UserRepository = UserCollection.repository;
const user = await UserRepository.findOne({
filter: {
id: 1,
},
});
user.name = 'new name';
await user.save();Query
Basic Query
On the Repository object, call the find* methods to perform query. The filter parameter is supported by all query methods to filter the data.
// SELECT * FROM users WHERE id = 1
userRepository.find({
filter: {
id: 1,
},
});Operator
The filter parameter in the Repository also provides a variety of operators to perform more diverse queries.
// SELECT * FROM users WHERE age > 18
userRepository.find({
filter: {
age: {
$gt: 18,
},
},
});
// SELECT * FROM users WHERE age > 18 OR name LIKE '%ๅผ %'
userRepository.find({
filter: {
$or: [{ age: { $gt: 18 } }, { name: { $like: '%ๅผ %' } }],
},
});Refer to Filter Operators for more details on operators.
Field Control
Control the output fields by the fields, except, and appends parameters when performing query.
fields: Specify output fieldsexcept: Exclude output fieldsappends: Append output associated fields
// The result contains only the id and name fields
userRepository.find({
fields: ['id', 'name'],
});
// The result does not contain only the password field
userRepository.find({
except: ['password'],
});
// The result contains data associated with the posts object
userRepository.find({
appends: ['posts'],
});Associated Field Query
The filter parameter supports filtering by associated fields, for example:
// Find the user objects whose associated posts have title of "post title"
userRepository.find({
filter: {
'posts.title': 'post title',
},
});Associated fields can also be nested:
// Find the user objects whose associated posts have comments containing "keywords"
await userRepository.find({
filter: {
'posts.comments.content': {
$like: '%keywords%',
},
},
});Sort
Sort query results by the sort parameter.
// SELECT * FROM users ORDER BY age
await userRepository.find({
sort: 'age',
});
// SELECT * FROM users ORDER BY age DESC
await userRepository.find({
sort: '-age',
});
// SELECT * FROM users ORDER BY age DESC, name ASC
await userRepository.find({
sort: ['-age', 'name'],
});Sort by the field of the associated object is also supported:
await userRepository.find({
sort: 'profile.createdAt',
});Create
Basic Create
Create new data objects via Repository.
await userRepository.create({
name: 'Mark',
age: 18,
});
// INSERT INTO users (name, age) VALUES ('Mark', 18)
// Bulk creation
await userRepository.create([
{
name: 'Mark',
age: 18,
},
{
name: 'Alex',
age: 20,
},
]);Create Association
Create associated objects at the same time of creating data. Like query, nested use of associated objects is also supported. For example:
await userRepository.create({
name: 'Mark',
age: 18,
posts: [
{
title: 'post title',
content: 'post content',
tags: [
{
name: 'tag1',
},
{
name: 'tag2',
},
],
},
],
});
// When creating a user, create a post to associate with the user, and create tags to associate with the postIf the associated object is already in the database, you can pass its ID to create an association with it.
const tag1 = await tagRepository.findOne({
filter: {
name: 'tag1',
},
});
await userRepository.create({
name: 'Mark',
age: 18,
posts: [
{
title: 'post title',
content: 'post content',
tags: [
{
id: tag1.id, // Create an association with an existing associated object
},
{
name: 'tag2',
},
],
},
],
});Update
Basic Update
After getting the data object, you can modify the properties directly on the data object (Model), and then call the save method to save the changes.
const user = await userRepository.findOne({
filter: {
name: 'Mark',
},
});
user.age = 20;
await user.save();The data object Model is inherited from Sequelize Model, refer to Sequelize Model for the operations on Model.
Or update data via Repository:
// Update the records that meet the filtering condition
await userRepository.update({
filter: {
name: 'Mark',
},
values: {
age: 20,
},
});Control which fields to update by the whitelist and blacklist parameters, for example:
await userRepository.update({
filter: {
name: 'Mark',
},
values: {
age: 20,
name: 'Alex',
},
whitelist: ['age'], // Only update the age field
});Update Associated Field
Associated objects can be set while updating, for example:
const tag1 = tagRepository.findOne({
filter: {
id: 1,
},
});
await postRepository.update({
filter: {
id: 1,
},
values: {
title: 'new post title',
tags: [
{
id: tag1.id, // Associate with tag1
},
{
name: 'tag2', // Create new tag and associate with it
},
],
},
});
await postRepository.update({
filter: {
id: 1,
},
values: {
tags: null, // Disassociate post from tags
},
});Delete
Call the destroy() method in Repository to perform the deletion operation. Filtering condition has to be specified to delete.
await userRepository.destroy({
filter: {
status: 'blocked',
},
});Constructor
It is usually not called directly by the developer, the instantiation is done mainly by specifying a corresponding repository type that is already registered in the parameter of db.colletion(). Repository type is registered through db.registerRepositories().
Signature
constructor(collection: Collection)
Example
import { Repository } from '@nocobase/database';
class MyRepository extends Repository {
async myQuery(sql) {
return this.database.sequelize.query(sql);
}
}
db.registerRepositories({
books: MyRepository,
});
db.collection({
name: 'books',
// here link to the registered repository
repository: 'books',
});
await db.sync();
const books = db.getRepository('books') as MyRepository;
await books.myQuery('SELECT * FROM books;');Instance Members
`database`
The database management instance where the context is located.
`collection`
The corresponding data table management instance.
`model`
The corresponding data model class.
Instance Methods
`find()`
Find datasets from the database with the specified filtering conditions and sorting, etc.
Signature
async find(options?: FindOptions): Promise<Model[]>
Type
type Filter = FilterWithOperator | FilterWithValue | FilterAnd | FilterOr;
type Appends = string[];
type Except = string[];
type Fields = string[];
type Sort = string[] | string;
interface SequelizeFindOptions {
limit?: number;
offset?: number;
}
interface FilterByTk {
filterByTk?: TargetKey;
}
interface CommonFindOptions extends Transactionable {
filter?: Filter;
fields?: Fields;
appends?: Appends;
except?: Except;
sort?: Sort;
}
type FindOptions = SequelizeFindOptions & CommonFindOptions & FilterByTk;Detailed Information
`filter: Filter`
Query conditions for filtering data results. In the query parameters that passed in, key is the name of the field, value is the corresponding value. Operators can be used in conjunction with other filtering conditions.
// Find records with name "foo" and age above 18
repository.find({
filter: {
name: 'foo',
age: {
$gt: 18,
},
},
});Refer to Operators for more information.
`filterByTk: TargetKey`
Query data by TargetKey, this is shortcut for the filter parameter. The field of TargetKey can be configured in Collection, the default is primaryKey.
// By default, find records with id 1
repository.find({
filterByTk: 1,
});`fields: string[]`
Query columns. It is used to control which data fields to output. With this parameter, only the specified fields will be returned.
`except: string[]`
Exclude columns. It is used to control which data fields to output. With this parameter, the specified fields will not be returned.
`appends: string[]`
Append columns. It is used to load associated data. With this parameter, the specified associated fields will be returned together.
`sort: string[] | string`
Specify the sorting method of the query results. The input parameter is the name of the field, by default is to sort in the ascending order (asc); a - symbol needs to be added before the field name to sort in the descending order (desc). For example, ['-id', 'name'] means to sort by id desc, name asc.
`limit: number`
Limit the number of results, same as limit in SQL.
`offset: number`
The offset of the query, same as offset in SQL.
Example
const posts = db.getRepository('posts');
const results = await posts.find({
filter: {
createdAt: {
$gt: '2022-01-01T00:00:00.000Z',
},
},
fields: ['title'],
appends: ['user'],
});`findOne()`
Find a single piece of data from the database for specific conditions. Equivalent to Model.findOne() in Sequelize.
Signature
async findOne(options?: FindOneOptions): Promise<Model | null>
Example
const posts = db.getRepository('posts');
const result = await posts.findOne({
filterByTk: 1,
});`count()`
Query a certain amount of data from the database for specific conditions. Equivalent to Model.count() in Sequelize.
Signature
count(options?: CountOptions): Promise<number>
Type
interface CountOptions
extends Omit<SequelizeCountOptions, 'distinct' | 'where' | 'include'>,
Transactionable {
filter?: Filter;
}Example
const books = db.getRepository('books');
const count = await books.count({
filter: {
title: 'Three character classic',
},
});`findAndCount()`
Find datasets from the database with the specified filtering conditions and return the number of results. Equivalent to Model.findAndCountAll() in Sequelize.
Signature
async findAndCount(options?: FindAndCountOptions): Promise<[Model[], number]>
Type
type FindAndCountOptions = Omit<
SequelizeAndCountOptions,
'where' | 'include' | 'order'
> &
CommonFindOptions;Detailed Information
The query parameters are the same as find(). An array is returned with the first element of the query results, and the second element of the total number of results.
`create()`
Inserts a newly created data into the data table. Equivalent to Model.create() in Sequelize. When the data object to be created carries any associated field, the corresponding associated data record is created or updated along with it.
Signature
async create<M extends Model>(options: CreateOptions): Promise<M>
Example
const posts = db.getRepository('posts');
const result = await posts.create({
values: {
title: 'NocoBase 1.0 Release Notes',
tags: [
// Update data when there is a primary key and value of the associated table
{ id: 1 },
// Create data when there is no primary key and value
{ name: 'NocoBase' },
],
},
});`createMany()`
Inserts multiple newly created data into the data table. This is equivalent to calling the create() method multiple times.
Signature
createMany(options: CreateManyOptions): Promise<Model[]>
Type
interface CreateManyOptions extends BulkCreateOptions {
records: Values[];
}Detailed Information
records: An array of data objects to be created.transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
const posts = db.getRepository('posts');
const results = await posts.createMany({
records: [
{
title: 'NocoBase 1.0 Release Notes',
tags: [
// Update data when there is a primary key and value of the associated table
{ id: 1 },
// Create data when there is no primary key and value
{ name: 'NocoBase' },
],
},
{
title: 'NocoBase 1.1 Release Notes',
tags: [{ id: 1 }],
},
],
});`update()`
Update data in the data table. Equivalent to Model.update() in Sequelize. When the data object to be updated carries any associated field, the corresponding associated data record is created or updated along with it.
Signature
async update<M extends Model>(options: UpdateOptions): Promise<M>
Example
const posts = db.getRepository('posts');
const result = await posts.update({
filterByTk: 1,
values: {
title: 'NocoBase 1.0 Release Notes',
tags: [
// Update data when there is a primary key and value of the associated table
{ id: 1 },
// Create data when there is no primary key and value
{ name: 'NocoBase' },
],
},
});`destroy()`
Delete data from the data table. Equivalent to Model.destroy() in Sequelize.
Signature
async destroy(options?: TargetKey | TargetKey[] | DestoryOptions): Promise<number>
Type
interface DestroyOptions extends SequelizeDestroyOptions {
filter?: Filter;
filterByTk?: TargetKey | TargetKey[];
truncate?: boolean;
context?: any;
}Detailed Information
filter๏ผSpecify the filtering conditions of the records to be deleted. Refer to thefind()method for the detailed usage of the filter.filterByTk๏ผSpecify the filtering conditions by TargetKey.truncate: Whether to empty the table data, this parameter is valid if nofilterorfilterByTkparameter is passed.transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared.md
Parameters
| Parameter Name | Type | Default | Description |
|---|---|---|---|
options.values |
M |
{} |
The data object to be inserted |
options.whitelist? |
string[] |
- | Whitelist for the values field; only fields in the list will be stored |
options.blacklist? |
string[] |
- | Blacklist for the values field; fields in the list will not be stored |
options.transaction? |
Transaction |
- | Transaction |
File: docs/en-US/api/database/interfaces/base-interface.md
BaseInterface
Overview
BaseInterface is the foundational class for all Interface types. Users can extend this class to implement custom Interface logic.
class CustomInterface extends BaseInterface {
async toValue(value: string, ctx?: any): Promise<any> {
// Custom toValue logic
}
toString(value: any, ctx?: any) {
// Custom toString logic
}
}
// Register Interface
db.interfaceManager.registerInterfaceType('customInterface', CustomInterface)Interfaces
toValue(value: string, ctx?: any): Promise
Converts an external string to the actual value of the interface, which can be directly passed to the Repository for write operations.
toString(value: any, ctx?: any)
Converts the actual value of the interface to a string type, which can be used for exporting or displaying purposes.
File: docs/en-US/api/database/relation-repository/belongs-to-many-repository.md
BelongsToManyRepository
BelongsToManyRepository is the Relation Repository for handling BelongsToMany relationships.
Unlike other relationship types, the BelongsToMany type of relationship needs to be recorded through an intermediate table. The intermediate table can be created automatically or explicitly specified when defining association relationships in NocoBase.
Class Methods
`find()`
Find associated objects.
Signature
async find(options?: FindOptions): Promise<M[]>
Detailed Information
Query parameters are the same as Repository.find().
`findOne()`
Find associated objects, only to return one record.
Signature
async findOne(options?: FindOneOptions): Promise<M>
`count()`
Return the number of records matching the query criteria.
Signature
async count(options?: CountOptions)
Type
interface CountOptions
extends Omit<SequelizeCountOptions, 'distinct' | 'where' | 'include'>,
Transactionable {
filter?: Filter;
}`findAndCount()`
Find datasets from the database with the specified filtering conditions and return the number of results.
Signature
async findAndCount(options?: FindAndCountOptions): Promise<[any[], number]>
Type
type FindAndCountOptions = CommonFindOptions;`create()`
Create associated objects.
Signature
async create(options?: CreateOptions): Promise<M>
`update()`
Update associated objects that match the conditions.
Signature
async update(options?: UpdateOptions): Promise<M>
`destroy()`
Delete associated objects.
Signature
async destroy(options?: TargetKey | TargetKey[] | DestroyOptions): Promise
`add()`
Add new associated objects.
Signature
async add( options: TargetKey | TargetKey[] | PrimaryKeyWithThroughValues | PrimaryKeyWithThroughValues[] | AssociatedOptions ): Promise<void>
Type
type PrimaryKeyWithThroughValues = [TargetKey, Values];
interface AssociatedOptions extends Transactionable {
tk?:
| TargetKey
| TargetKey[]
| PrimaryKeyWithThroughValues
| PrimaryKeyWithThroughValues[];
}Detailed Information
Pass the targetKey of the associated object directly, or pass the targetKey along with the field values of the intermediate table.
Example
const t1 = await Tag.repository.create({
values: { name: 't1' },
});
const t2 = await Tag.repository.create({
values: { name: 't2' },
});
const p1 = await Post.repository.create({
values: { title: 'p1' },
});
const PostTagRepository = new BelongsToManyRepository(Post, 'tags', p1.id);
// Pass in the targetKey
PostTagRepository.add([t1.id, t2.id]);
// Pass in intermediate table fields
PostTagRepository.add([
[t1.id, { tagged_at: '123' }],
[t2.id, { tagged_at: '456' }],
]);`set()`
Set the associated objects.
Signature
- async set(
options: TargetKey | TargetKey[] | PrimaryKeyWithThroughValues | PrimaryKeyWithThroughValues[] | AssociatedOptions,
): Promise
Detailed Information
Parameters are the same as add().
`remove()`
Remove the association with the given objects.
Signature
async remove(options: TargetKey | TargetKey[] | AssociatedOptions)
Type
interface AssociatedOptions extends Transactionable {
tk?: TargetKey | TargetKey[];
}`toggle()`
Toggle the associated object.
In some business scenarios, it is often needed to toggle the associated object. For example, user adds a product into collection, and the user cancels the collection and collect it again. Using the toggle method can quickly implement similar functions.
Signature
async toggle(options: TargetKey | { tk?: TargetKey; transaction?: Transaction }): Promise<void>
Detailed Information
The toggle method automatically checks whether the associated object already exists, and removes it if it does, or adds it if it does not.
File: docs/en-US/api/database/relation-repository/belongs-to-repository.md
BelongsToRepository
The interface is the same as HasOneRepository. BelongsToRepository is the Repository for handling BelongsTo relationships, and it provides some convenient methods to handle BelongsTo relationships.
File: docs/en-US/api/database/relation-repository/has-many-repository.md
HasManyRepository
HasManyRepository is the Relation Repository for handling HasMany relationships.
Class Methods
`find()`
Find associated objects.
Signature
async find(options?: FindOptions): Promise<M[]>
Detailed Information
Query parameters are the same as Repository.find().
`findOne()`
Find associated objects, only to return one record.
Signature
async findOne(options?: FindOneOptions): Promise<M>
`count()`
Return the number of records matching the query criteria.
Signature
async count(options?: CountOptions)
Type
interface CountOptions
extends Omit<SequelizeCountOptions, 'distinct' | 'where' | 'include'>,
Transactionable {
filter?: Filter;
}`findAndCount()`
Find datasets from the database with the specified filtering conditions and return the number of results.
Signature
async findAndCount(options?: FindAndCountOptions): Promise<[any[], number]>
Type
type FindAndCountOptions = CommonFindOptions;`create()`
Create associated objects.
Signature
async create(options?: CreateOptions): Promise<M>
`update()`
Update associated objects that match the conditions.
Signature
async update(options?: UpdateOptions): Promise<M>
`destroy()`
Delete associated objects.
Signature
async destroy(options?: TK | DestroyOptions): Promise<M>
`add()`
Add association relationships between objects.
Signature
async add(options: TargetKey | TargetKey[] | AssociatedOptions)
Type
interface AssociatedOptions extends Transactionable {
tk?: TargetKey | TargetKey[];
}Detailed Information
tk- The targetKey value of the associated object, either as a single value or an array.
`remove()`
Remove the association with the given objects.
Signature
async remove(options: TargetKey | TargetKey[] | AssociatedOptions)
Detailed Information
Same parameters as the add() method.
`set()`
Set the associated object of the current relationship.
Signature
async set(options: TargetKey | TargetKey[] | AssociatedOptions)
Detailed Information
Same parameters as the add() method.
File: docs/en-US/api/database/relation-repository/has-one-repository.md
HasOneRepository
Overview
HasOneRepository is the associated repository of type HasOne.
const User = db.collection({
name: 'users',
fields: [
{ type: 'hasOne', name: 'profile' },
{ type: 'string', name: 'name' },
],
});
const Profile = db.collection({
name: 'profiles',
fields: [{ type: 'string', name: 'avatar' }],
});
const user = await User.repository.create({
values: { name: 'u1' },
});
// Get the associated repository
const userProfileRepository = User.repository
.relation('profile')
.of(user.get('id'));
// Or to initialize directly
new HasOneRepository(User, 'profile', user.get('id'));Class Methods
`find()`
Find associated objects.
Signature
async find(options?: SingleRelationFindOption): Promise<Model<any> | null>
Type
interface SingleRelationFindOption extends Transactionable {
fields?: Fields;
except?: Except;
appends?: Appends;
filter?: Filter;
}Detailed Information
Query parameters are the same as Repository.find().
Example
const profile = await UserProfileRepository.find();
// Return null if the associated object does not exist`create()`
Create associated objects.
Signature
async create(options?: CreateOptions): Promise<Model>
Example
const profile = await UserProfileRepository.create({
values: { avatar: 'avatar1' },
});
console.log(profile.toJSON());
/*
{
id: 1,
avatar: 'avatar1',
userId: 1,
updatedAt: 2022-09-24T13:59:40.025Z,
createdAt: 2022-09-24T13:59:40.025Z
}
*/`update()`
Update associated objects.
Signature
async update(options: UpdateOptions): Promise<Model>
Example
const profile = await UserProfileRepository.update({
values: { avatar: 'avatar2' },
});
profile.get('avatar'); // 'avatar2'`remove()`
Remove associated objects. Only to unassociate, not to delete the associated object.
Signature
async remove(options?: Transactionable): Promise<void>
Detailed Information
transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
await UserProfileRepository.remove();
(await UserProfileRepository.find()) == null; // true
(await Profile.repository.count()) === 1; // true`destroy()`
Delete associated objects.
Signature
async destroy(options?: Transactionable): Promise
Detailed Information
transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
await UserProfileRepository.destroy();
(await UserProfileRepository.find()) == null; // true
(await Profile.repository.count()) === 0; // true`set()`
Set associated objects.
Signature
async set(options: TargetKey | SetOption): Promise<void>
Type
interface SetOption extends Transactionable {
tk?: TargetKey;
}Detailed Information
- tk: Set the targetKey of the associated object.
- transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
Example
const newProfile = await Profile.repository.create({
values: { avatar: 'avatar2' },
});
await UserProfileRepository.set(newProfile.get('id'));
(await UserProfileRepository.find()).get('id') === newProfile.get('id'); // trueFile: docs/en-US/api/database/relation-repository/index.md
RelationRepository
RelationRepository is a Repository object for relation types, which allows operations on associated data without loading the associations. Based on RelationRepository, each association type derives its corresponding implementation, which are:
HasOneRepositoryHasManyRepositoryBelongsToRepositoryBelongsToManyRepository
Constructor
Signature
constructor(sourceCollection: Collection, association: string, sourceKeyValue: string | number)
Parameters
| Parameter Name | Type | Default Value | Description |
|---|---|---|---|
sourceCollection |
Collection |
- | The Collection corresponding to the referencing relation in the association |
association |
string |
- | The name of the association |
sourceKeyValue |
string | number |
- | The key value corresponding to the referencing relation |
Base Class Properties
`db: Database`
Database object
`sourceCollection`
The Collection corresponding to the referencing relation in the association
`targetCollection`
The Collection corresponding to the referenced relation in the association
`association`
The association object in Sequelize corresponding to the current association
`associationField`
The field in the Collection corresponding to the current association
`sourceKeyValue`
The key value corresponding to the referencing relation
File: docs/en-US/api/database/shared/create-options.md
Type
type WhiteList = string[];
type BlackList = string[];
type AssociationKeysToBeUpdate = string[];
interface CreateOptions extends SequelizeCreateOptions {
values?: Values;
whitelist?: WhiteList;
blacklist?: BlackList;
updateAssociationValues?: AssociationKeysToBeUpdate;
context?: any;
}Details
values: The data object of the record to be created.whitelist: Specifies which fields in the data object of the record to be created can be written. If this parameter is not passed, all fields are allowed to be written by default.blacklist: Specifies which fields in the data object of the record to be created are not allowed to be written. If this parameter is not passed, all fields are allowed to be written by default.transaction: The transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared/destroy-options.md
Type
interface DestroyOptions extends SequelizeDestroyOptions {
filter?: Filter;
filterByTk?: TargetKey | TargetKey[];
truncate?: boolean;
context?: any;
}Details
filter: Specifies the filtering conditions for the records to be deleted. For detailed usage of Filter, refer to thefind()method.filterByTk: Specifies the filtering conditions for the records to be deleted by TargetKey.truncate: Whether to truncate the table data, effective when nofilterorfilterByTkparameters are passed.transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared/find-one.md
Type
type FindOneOptions = Omit<FindOptions, 'limit'>;Parameters
Most parameters are the same as those in find(). The difference is that findOne() returns only a single piece of data, so the limit parameter is not needed, and the query is always set to 1.
File: docs/en-US/api/database/shared/find-options.md
[Empty file]
File: docs/en-US/api/database/shared/transaction.md
transaction: Transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
File: docs/en-US/api/database/shared/update-options.md
Type
interface UpdateOptions extends Omit<SequelizeUpdateOptions, 'where'> {
values: Values;
filter?: Filter;
filterByTk?: TargetKey;
whitelist?: WhiteList;
blacklist?: BlackList;
updateAssociationValues?: AssociationKeysToBeUpdate;
context?: any;
}Details
values: The data object of the records to be updated.filter: Specifies the filter conditions for the records to be updated. For detailed usage of Filter, refer to thefind()method.filterByTk: Specifies the filter conditions for the records to be updated by TargetKey.whitelist: A whitelist for thevaluesfields. Only fields listed will be written.blacklist: A blacklist for thevaluesfields. Fields listed will not be written.transaction: The transaction object. If no transaction parameter is passed, the method will automatically create an internal transaction.
At least one of filterByTk or filter must be provided.
File: docs/en-US/api/field/markdown-vditor/index.md
markdown
Example
This is an embedded Markdown editor:
File: docs/en-US/api/handlebars-helpers/array.md
Array
{{after}}
Returns all of the items in an array after the specified index. Opposite of before.
Params
array{Array}: Collectionn{Number}: Starting index (number of items to exclude)returns{Array}: Array exludingnitems.
Example
<!-- array: ['a', 'b', 'c'] -->
{{after array 1}}
<!-- results in: '["c"]' -->{{arrayify}}
Cast the given value to an array.
Params
value{any}returns{Array}
Example
{{arrayify "foo"}}
<!-- results in: [ "foo" ] -->{{before}}
Return all of the items in the collection before the specified count. Opposite of after.
Params
array{Array}n{Number}returns{Array}: Array excluding items after the given number.
Example
<!-- array: ['a', 'b', 'c'] -->
{{before array 2}}
<!-- results in: '["a", "b"]' -->{{eachIndex}}
Params
array{Array}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] -->
{{#eachIndex array}}
{{item}} is {{index}}
{{/eachIndex}}{{filter}}
Block helper that filters the given array and renders the block for values that evaluate to true, otherwise the inverse block is returned.
Params
array{Array}value{any}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#filter array "foo"}}AAA{{else}}BBB{{/filter}}
<!-- results in: 'BBB' -->{{first}}
Returns the first item, or first n items of an array.
Params
array{Array}n{Number}: Number of items to return, starting at0.returns{Array}
Example
{{first "['a', 'b', 'c', 'd', 'e']" 2}}
<!-- results in: '["a", "b"]' -->{{forEach}}
Iterates over each item in an array and exposes the current item in the array as context to the inner block. In addition to the current array item, the helper exposes the following variables to the inner block:
indextotalisFirstisLast
Also,@indexis exposed as a private variable, and additional
private variables may be defined as hash arguments.
Params
array{Array}returns{String}
Example
<!-- accounts = [
{'name': 'John', 'email': '[email protected]'},
{'name': 'Malcolm', 'email': '[email protected]'},
{'name': 'David', 'email': '[email protected]'}
] -->
{{#forEach accounts}}
<a href="mailto:{{ email }}" title="Send an email to {{ name }}">
{{ name }}
</a>{{#unless isLast}}, {{/unless}}
{{/forEach}}{{inArray}}
Block helper that renders the block if an array has the given value. Optionally specify an inverse block to render when the array does not have the given value.
Params
array{Array}value{any}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#inArray array "d"}}
foo
{{else}}
bar
{{/inArray}}
<!-- results in: 'bar' -->{{isArray}}
Returns true if value is an es5 array.
Params
value{any}: The value to test.returns{Boolean}
Example
{{isArray "abc"}}
<!-- results in: false -->
<!-- array: [1, 2, 3] -->
{{isArray array}}
<!-- results in: true -->{{itemAt}}
Returns the item from array at index idx.
Params
array{Array}idx{Number}returns{any}value
Example
<!-- array: ['a', 'b', 'c'] -->
{{itemAt array 1}}
<!-- results in: 'b' -->{{join}}
Join all elements of array into a string, optionally using a given separator.
Params
array{Array}separator{String}: The separator to use. Defaults to,.returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{join array}}
<!-- results in: 'a, b, c' -->
{{join array '-'}}
<!-- results in: 'a-b-c' -->{{equalsLength}}
Returns true if the the length of the given value is equal
to the given length. Can be used as a block or inline helper.
Params
value{Array|String}length{Number}options{Object}returns{String}
{{last}}
Returns the last item, or last n items of an array or string. Opposite of first.
Params
value{Array|String}: Array or string.n{Number}: Number of items to return from the end of the array.returns{Array}
Example
<!-- var value = ['a', 'b', 'c', 'd', 'e'] -->
{{last value}}
<!-- results in: ['e'] -->
{{last value 2}}
<!-- results in: ['d', 'e'] -->
{{last value 3}}
<!-- results in: ['c', 'd', 'e'] -->{{length}}
Returns the length of the given string or array.
Params
value{Array|Object|String}returns{Number}: The length of the value.
Example
{{length '["a", "b", "c"]'}}
<!-- results in: 3 -->
<!-- results in: myArray = ['a', 'b', 'c', 'd', 'e']; -->
{{length myArray}}
<!-- results in: 5 -->
<!-- results in: myObject = {'a': 'a', 'b': 'b'}; -->
{{length myObject}}
<!-- results in: 2 -->{{lengthEqual}}
Alias for equalsLength
{{map}}
Returns a new array, created by calling function on each element of the given array. For example,
Params
array{Array}fn{Function}returns{String}
Example
<!-- array: ['a', 'b', 'c'], and "double" is a
fictitious function that duplicates letters -->
{{map array double}}
<!-- results in: '["aa", "bb", "cc"]' -->{{pluck}}
Map over the given object or array or objects and create an array of values from the given prop. Dot-notation may be used (as a string) to get nested properties.
Params
collection{Array|Object}prop{Function}returns{String}
Example
// {{pluck items "data.title"}}
<!-- results in: '["aa", "bb", "cc"]' -->{{reverse}}
Reverse the elements in an array, or the characters in a string.
Params
value{Array|String}returns{Array|String}: Returns the reversed string or array.
Example
<!-- value: 'abcd' -->
{{reverse value}}
<!-- results in: 'dcba' -->
<!-- value: ['a', 'b', 'c', 'd'] -->
{{reverse value}}
<!-- results in: ['d', 'c', 'b', 'a'] -->{{some}}
Block helper that returns the block if the callback returns true for some value in the given array.
Params
array{Array}iter{Function}: Iteratee- {Options}: Handlebars provided options object
returns{String}
Example
<!-- array: [1, 'b', 3] -->
{{#some array isString}}
Render me if the array has a string.
{{else}}
Render me if it doesn't.
{{/some}}
<!-- results in: 'Render me if the array has a string.' -->{{sort}}
Sort the given array. If an array of objects is passed, you may optionally pass a key to sort on as the second argument. You may alternatively pass a sorting function as the second argument.
Params
array{Array}: the array to sort.key{String|Function}: The object key to sort by, or sorting function.
Example
<!-- array: ['b', 'a', 'c'] -->
{{sort array}}
<!-- results in: '["a", "b", "c"]' -->{{sortBy}}
Sort an array. If an array of objects is passed, you may optionally pass a key to sort on as the second argument. You may alternatively pass a sorting function as the second argument.
Params
array{Array}: the array to sort.props{String|Function}: One or more properties to sort by, or sorting functions to use.
Example
<!-- array: [{a: 'zzz'}, {a: 'aaa'}] -->
{{sortBy array "a"}}
<!-- results in: '[{"a":"aaa"}, {"a":"zzz"}]' -->{{withAfter}}
Use the items in the array after the specified index as context inside a block. Opposite of withBefore.
Params
array{Array}idx{Number}options{Object}returns{Array}
Example
<!-- array: ['a', 'b', 'c', 'd', 'e'] -->
{{#withAfter array 3}}
{{this}}
{{/withAfter}}
<!-- results in: "de" -->{{withBefore}}
Use the items in the array before the specified index as context inside a block. Opposite of withAfter.
Params
array{Array}idx{Number}options{Object}returns{Array}
Example
<!-- array: ['a', 'b', 'c', 'd', 'e'] -->
{{#withBefore array 3}}
{{this}}
{{/withBefore}}
<!-- results in: 'ab' -->{{withFirst}}
Use the first item in a collection inside a handlebars block expression. Opposite of withLast.
Params
array{Array}idx{Number}options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#withFirst array}}
{{this}}
{{/withFirst}}
<!-- results in: 'a' -->{{withGroup}}
Block helper that groups array elements by given group size.
Params
array{Array}: The array to iterate oversize{Number}: The desired length of each array "group"options{Object}: Handlebars optionsreturns{String}
Example
<!-- array: ['a','b','c','d','e','f','g','h'] -->
{{#withGroup array 4}}
{{#each this}}
{{.}}
{{each}}
<br>
{{/withGroup}}
<!-- results in: -->
<!-- 'a','b','c','d'<br> -->
<!-- 'e','f','g','h'<br> -->{{withLast}}
Use the last item or n items in an array as context inside a block. Opposite of withFirst.
Params
array{Array}idx{Number}: The starting index.options{Object}returns{String}
Example
<!-- array: ['a', 'b', 'c'] -->
{{#withLast array}}
{{this}}
{{/withLast}}
<!-- results in: 'c' -->{{withSort}}
Block helper that sorts a collection and exposes the sorted collection as context inside the block.
Params
array{Array}prop{String}options{Object}: Specifyreverse="true"to reverse the array.returns{String}
Example
<!-- array: ['b', 'a', 'c'] -->
{{#withSort array}}{{this}}{{/withSort}}
<!-- results in: 'abc' -->{{unique}}
Block helper that return an array with all duplicate values removed. Best used along with a each helper.
Params
array{Array}options{Object}returns{Array}
Example
<!-- array: ['a', 'a', 'c', 'b', 'e', 'e'] -->
{{#each (unique array)}}{{.}}{{/each}}
<!-- results in: 'acbe' -->File: docs/en-US/api/handlebars-helpers/comparison.md
Comparison
{{and}}
Helper that renders the block if both of the given values are truthy. If an inverse block is specified it will be rendered when falsy. Works as a block helper, inline helper or subexpression.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}
Example
<!-- {great: true, magnificent: true} -->
{{#and great magnificent}}A{{else}}B{{/and}}
<!-- results in: 'A' -->{{compare}}
Render a block when a comparison of the first and third
arguments returns true. The second argument is
the arithemetic operator to use. You may also
optionally specify an inverse block to render when falsy.
Params
a{}operator{}: The operator to use. Operators must be enclosed in quotes:">","=","<=", and so on.b{}options{Object}: Handlebars provided options objectreturns{String}: Block, or if specified the inverse block is rendered if falsey.
{{contains}}
Block helper that renders the block if collection has the given value, using strict equality (===) for comparison, otherwise the inverse block is rendered (if specified). If a startIndex is specified and is negative, it is used as the offset from the end of the collection.
Params
collection{Array|Object|String}: The collection to iterate over.value{any}: The value to check for.[startIndex=0]{Number}: Optionally define the starting index.options{Object}: Handlebars provided options object.
Example
<!-- array = ['a', 'b', 'c'] -->
{{#contains array "d"}}
This will not be rendered.
{{else}}
This will be rendered.
{{/contains}}{{default}}
Returns the first value that is not undefined, otherwise the "default" value is returned.
Params
value{any}defaultValue{any}returns{String}
{{eq}}
Block helper that renders a block if a is equal to b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{gt}}
Block helper that renders a block if a is greater than b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{gte}}
Block helper that renders a block if a is greater than or equal to b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{has}}
Block helper that renders a block if value has pattern.
If an inverse block is specified it will be rendered when falsy.
Params
val{any}: The value to check.pattern{any}: The pattern to check for.options{Object}: Handlebars provided options objectreturns{String}
{{isEmpty}}
Inline, subexpression, or block helper that returns true (or the block) if the given collection is empty, or false (or the inverse block, if supplied) if the colleciton is not empty.
Params
collection{Object}options{Object}returns{String}
Example
<!-- array: [] -->
{{#isEmpty array}}AAA{{else}}BBB{{/isEmpty}}
<!-- results in: 'AAA' -->
<!-- array: [] -->
{{isEmpty array}}
<!-- results in: true -->{{isFalsey}}
Returns true if the given value is falsey. Uses the falsey
library for comparisons. Please see that library for more information
or to report bugs with this helper.
Params
val{any}options{Options}returns{Boolean}
{{isTruthy}}
Returns true if the given value is truthy. Uses the falsey
library for comparisons. Please see that library for more information
or to report bugs with this helper.
Params
val{any}options{Options}returns{Boolean}
{{ifEven}}
Return true if the given value is an even number.
Params
number{Number}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
Example
{{#ifEven value}}
render A
{{else}}
render B
{{/ifEven}}{{ifNth}}
Conditionally renders a block if the remainder is zero whena operand is divided by b. If an inverse block is specified
it will be rendered when the remainder is not zero.
Params
- {}: {Number}
- {}: {Number}
options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{ifOdd}}
Block helper that renders a block if value is an odd number. If an inverse block is specified it will be rendered when falsy.
Params
value{Object}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
Example
{{#ifOdd value}}
render A
{{else}}
render B
{{/ifOdd}}{{is}}
Block helper that renders a block if a is equal to b.
If an inverse block is specified it will be rendered when falsy.
Similar to eq but does not do strict equality.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}
{{isnt}}
Block helper that renders a block if a is not equal to b.
If an inverse block is specified it will be rendered when falsy.
Similar to unlessEq but does not use strict equality for
comparisons.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}
{{lt}}
Block helper that renders a block if a is less than b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
context{Object}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{lte}}
Block helper that renders a block if a is less than or equal to b.
If an inverse block is specified it will be rendered when falsy.
You may optionally use the compare="" hash argument for the
second value.
Params
a{Sring}b{Sring}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{neither}}
Block helper that renders a block if neither of the given values
are truthy. If an inverse block is specified it will be rendered
when falsy.
Params
a{any}b{any}options{}: Handlebars options objectreturns{String}: Block, or inverse block if specified and falsey.
{{not}}
Returns true if val is falsey. Works as a block or inline helper.
Params
val{String}options{Object}: Handlebars provided options objectreturns{String}
{{or}}
Block helper that renders a block if any of the given values is truthy. If an inverse block is specified it will be rendered when falsy.
Params
arguments{...any}: Variable number of argumentsoptions{Object}: Handlebars options objectreturns{String}: Block, or inverse block if specified and falsey.
Example
{{#or a b c}}
If any value is true this will be rendered.
{{/or}}{{unlessEq}}
Block helper that always renders the inverse block unless a is
is equal to b.
Params
a{String}b{String}options{Object}: Handlebars provided options objectreturns{String}: Inverse block by default, or block if falsey.
{{unlessGt}}
Block helper that always renders the inverse block unless a is
is greater than b.
Params
a{Object}: The default valueb{Object}: The value to compareoptions{Object}: Handlebars provided options objectreturns{String}: Inverse block by default, or block if falsey.
{{unlessLt}}
Block helper that always renders the inverse block unless a is
is less than b.
Params
a{Object}: The default valueb{Object}: The value to compareoptions{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{unlessGteq}}
Block helper that always renders the inverse block unless a is
is greater than or equal to b.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
{{unlessLteq}}
Block helper that always renders the inverse block unless a is
is less than or equal to b.
Params
a{any}b{any}options{Object}: Handlebars provided options objectreturns{String}: Block, or inverse block if specified and falsey.
File: docs/en-US/api/handlebars-helpers/core.md
Built-in Helpers
https://handlebarsjs.com/guide/builtin-helpers.html
{{if}}
Renders a block if the given condition is truthy.
Params
condition{Any}: The condition to evaluate.
Returns: The content inside the block if the condition is truthy, otherwise returns nothing.
Example
{{#if condition}}
This will be displayed if the condition is true.
{{/if}}{{unless}}
Renders a block if the given condition is falsy. This is the opposite of if.
Params
condition{Any}: The condition to evaluate.
Returns: The content inside the block if the condition is falsy, otherwise returns nothing.
Example
{{#unless condition}}
This will be displayed if the condition is false.
{{/unless}}{{each}}
Iterates over an array or object and renders a block for each item.
Params
collection{Array|Object}: The array or object to iterate over.
Returns: Renders the block for each item in the collection.
Example
{{#each items}}
<li>{{this}}</li>
{{/each}}{{with}}
Renders a block with a given context. It allows you to specify a context for the block, simplifying access to deeply nested properties.
Params
context{Any}: The context to use within the block.
Returns: Renders the block with the provided context.
Example
{{#with person}}
<p>Name: {{name}}</p>
<p>Age: {{age}}</p>
{{/with}}{{lookup}}
Looks up the value of a specified key in an object. This helper is useful for accessing dynamic keys.
Params
context{Object}: The object to look up the key from.key{String|Number}: The key to look up.
Returns: The value of the specified key in the object.
Example
{{lookup person "name"}}
<!-- If person is { name: "Alice", age: 30 }, it results in: "Alice" -->File: docs/en-US/api/handlebars-helpers/date.md
Date
{{dateFormat}}
The "dateFormat" helper in Handlebars is used to format a date using the day.js library. It takes two required arguments and an optional third argument for the timezone.
Params
datetime{String}format{String}timezone{String}returns{String}
Example
{{dateFormat now "YYYY-MM-DD HH:mm:ss"}}
{{dateFormat now "YYYY-MM-DD HH:mm:ss" "Asia/Tokyo"}}
{{dateFormat now "YYYY-MM-DD HH:mm:ss" "UTC"}}File: docs/en-US/api/handlebars-helpers/html.md
HTML
{{qrcode}}
File: docs/en-US/api/handlebars-helpers/i18n.md
I18n
{{t}}
Params
key{String}ns{String}returns{String}
Example
{{t "Today"}}
{{t "Permissions" "@nocobase/plugin-acl"}}File: docs/en-US/api/handlebars-helpers/index.md
Handlebars Helpers
| Category | Description |
|---|---|
| Core | Built-in helpers |
| Array | Operations and methods related to arrays |
| Comparison | Comparison operators and related methods |
| Date | Operations and methods related to date and time handling |
| HTML | Content related to HTML documents and elements |
| I18n | Support for internationalization and multilingual handling |
| Math | Mathematical functions and calculations |
| Number | Content related to number handling and formatting |
| Object | Methods related to object operations and properties |
| Path | Path operations and content related to the file system |
| Regex | Regular expressions and their usage |
| String | Methods related to string manipulation and operations |
| URL | Content related to URL parsing and construction |
File: docs/en-US/api/handlebars-helpers/math.md
Math
{{abs}}
Return the magnitude of a.
Params
a{Number}returns{Number}
{{add}}
Return the sum of a plus b.
Params
a{Number}b{Number}returns{Number}
{{avg}}
Returns the average of all numbers in the given array.
Params
array{Array}: Array of numbers to add up.returns{Number}
Example
{{avg "[1, 2, 3, 4, 5]"}}
<!-- results in: '3' -->{{ceil}}
Get the Math.ceil() of the given value.
Params
value{Number}returns{Number}
{{divide}}
Divide a by b
Params
a{Number}: numeratorb{Number}: denominator
{{floor}}
Get the Math.floor() of the given value.
Params
value{Number}returns{Number}
{{minus}}
Return the difference of a minus b.
Params
a{Number}b{Number}
{{modulo}}
Get the remainder of a division operation.
Params
a{Number}b{Number}returns{Number}
{{multiply}}
Return the product of a times b.
Params
a{Number}: factorb{Number}: multiplierreturns{Number}
{{plus}}
Add a by b.
Params
a{Number}: factorb{Number}: multiplier
{{random}}
Generate a random number between two values
Params
min{Number}max{Number}returns{String}
{{remainder}}
Get the remainder when a is divided by b.
Params
a{Number}: ab{Number}: b
{{round}}
Round the given number.
Params
number{Number}returns{Number}
{{subtract}}
Return the product of a minus b.
Params
a{Number}b{Number}returns{Number}
{{sum}}
Returns the sum of all numbers in the given array.
Params
array{Array}: Array of numbers to add up.returns{Number}
Example
{{sum "[1, 2, 3, 4, 5]"}}
<!-- results in: '15' -->{{times}}
Multiply number a by number b.
Params
a{Number}: factorb{Number}: multiplierreturns{Number}
File: docs/en-US/api/handlebars-helpers/number.md
Number
{{bytes}}
Format a number to it's equivalent in bytes. If a string is passed, it's length will be formatted and returned.
Examples:
'foo' => 3 B13661855 => 13.66 MB825399 => 825.39 kB1396 => 1.4 kB
Params
number{Number|String}returns{String}
{{addCommas}}
Add commas to numbers
Params
num{Number}returns{Number}
{{phoneNumber}}
Convert a string or number to a formatted phone number.
Params
num{Number|String}: The phone number to format, e.g.8005551212returns{Number}: Formatted phone number:(800) 555-1212
{{toAbbr}}
Abbreviate numbers to the given number of precision. This is for
general numbers, not size in bytes.
Params
number{Number}precision{Number}returns{String}
{{toExponential}}
Returns a string representing the given number in exponential notation.
Params
number{Number}fractionDigits{Number}: Optional. An integer specifying the number of digits to use after the decimal point. Defaults to as many digits as necessary to specify the number.returns{Number}
Example
{{toExponential number digits}};{{toFixed}}
Formats the given number using fixed-point notation.
Params
number{Number}digits{Number}: (Optional) The number of digits to appear after the decimal point; this may be a value between 0 and 20. If this argument is omitted, it is treated as 0.returns{String}: A string representing the given number using fixed-point notation.
Example
{{toFixed "1.1234" 2}}
//=> '1.12'{{toFloat}}
Params
number{Number}returns{Number}
{{toInt}}
Params
number{Number}returns{Number}
{{toPrecision}}
Returns a string representing the Number object to the specified precision.
Params
number{Number}precision{Number}: (Optional) An integer specifying the number of significant digits. If precison is not between 1 and 100 (inclusive), it will be coerced to0.returns{String}: A string representing a Number object in fixed-point or exponential notation rounded to precision significant digits.
Example
{{toPrecision "1.1234" 2}}
//=> '1.1'File: docs/en-US/api/handlebars-helpers/object.md
Object
{{extend}}
Extend the context with the properties of other objects.
A shallow merge is performed to avoid mutating the context.
Params
objects{Object}: One or more objects to extend.returns{Object}
{{forIn}}
Block helper that iterates over the properties of
an object, exposing each key and value on the context.
Params
context{Object}options{Object}returns{String}
{{forOwn}}
Block helper that iterates over the own properties of
an object, exposing each key and value on the context.
Params
obj{Object}: The object to iterate over.options{Object}returns{String}
{{toPath}}
Take arguments and, if they are string or number, convert them to a dot-delineated object property path.
Params
prop{String|Number}: The property segments to assemble (can be multiple).returns{String}
{{get}}
Use property paths (a.b.c) to get a value or nested value from
the context. Works as a regular helper or block helper.
Params
prop{String}: The property to get, optionally using dot notation for nested properties.context{Object}: The context objectoptions{Object}: The handlebars options object, if used as a block helper.returns{String}
{{getObject}}
Use property paths (a.b.c) to get an object from
the context. Differs from the get helper in that this
helper will return the actual object, including the
given property key. Also, this helper does not work as a
block helper.
Params
prop{String}: The property to get, optionally using dot notation for nested properties.context{Object}: The context objectreturns{String}
{{hasOwn}}
Return true if key is an own, enumerable property of the given context object.
Params
key{String}context{Object}: The context object.returns{Boolean}
Example
{{hasOwn context key}}{{isObject}}
Return true if value is an object.
Params
value{String}returns{Boolean}
Example
{{isObject "foo"}}
//=> false{{JSONparse}}
Parses the given string using JSON.parse.
Params
string{String}: The string to parse
Example
<!-- string: '{"foo": "bar"}' -->
{{JSONparse string}}
<!-- results in: { foo: 'bar' } -->{{JSONstringify}}
Stringify an object using JSON.stringify.
Params
obj{Object}: Object to stringifyreturns{String}
Example
<!-- object: { foo: 'bar' } -->
{{JSONstringify object}}
<!-- results in: '{"foo": "bar"}' -->{{merge}}
Deeply merge the properties of the given objects with the
context object.
Params
object{Object}: The target object. Pass an empty object to shallow clone.objects{Object}returns{Object}
{{pick}}
Pick properties from the context object.
Params
properties{Array|String}: One or more properties to pick.context{Object}options{Object}: Handlebars options object.returns{Object}: Returns an object with the picked values. If used as a block helper, the values are passed as context to the inner block. If no values are found, the context is passed to the inverse block.
File: docs/en-US/api/handlebars-helpers/path.md
Path
{{absolute}}
Get the directory path segment from the given filepath.
Params
ext{String}returns{String}
Example
{{absolute "docs/toc.md"}}
<!-- results in: 'docs' -->{{dirname}}
Get the directory path segment from the given filepath.
Params
ext{String}returns{String}
Example
{{dirname "docs/toc.md"}}
<!-- results in: 'docs' -->{{relative}}
Get the relative filepath from a to b.
Params
a{String}b{String}returns{String}
Example
{{relative a b}}{{basename}}
Get the file extension from the given filepath.
Params
ext{String}returns{String}
Example
{{basename "docs/toc.md"}}
<!-- results in: 'toc.md' -->{{stem}}
Get the "stem" from the given filepath.
Params
filepath{String}returns{String}
Example
{{stem "docs/toc.md"}}
<!-- results in: 'toc' -->{{extname}}
Get the file extension from the given filepath.
Params
filepath{String}returns{String}
Example
{{extname "docs/toc.md"}}
<!-- results in: '.md' -->{{resolve}}
Resolve an absolute path from the given filepath.
Params
filepath{String}returns{String}
Example
{{resolve "docs/toc.md"}}
<!-- results in: '/User/dev/docs/toc.md' -->{{segments}}
Get specific (joined) segments of a file path by passing a range of array indices.
Params
filepath{String}: The file path to split into segments.returns{String}: Returns a single, joined file path.
Example
{{segments "a/b/c/d" "2" "3"}}
<!-- results in: 'c/d' -->
{{segments "a/b/c/d" "1" "3"}}
<!-- results in: 'b/c/d' -->
{{segments "a/b/c/d" "1" "2"}}
<!-- results in: 'b/c' -->File: docs/en-US/api/handlebars-helpers/regex.md
Regex
{{toRegex}}
Convert the given string to a regular expression.
Params
str{String}returns{RegExp}
Example
{{toRegex "foo"}}
<!-- results in: /foo/ -->{{test}}
Returns true if the given str matches the given regex. A regex can be passed on the context, or using the toRegex helper as a subexpression.
Params
str{String}returns{RegExp}
Example
{{test "bar" (toRegex "foo")}}
<!-- results in: false -->
{{test "foobar" (toRegex "foo")}}
<!-- results in: true -->
{{test "foobar" (toRegex "^foo$")}}
<!-- results in: false -->File: docs/en-US/api/handlebars-helpers/string.md
String
{{append}}
Append the specified suffix to the given string.
Params
str{String}suffix{String}returns{String}
Example
<!-- given that "item.stem" is "foo" -->
{{append item.stem ".html"}}
<!-- results in: 'foo.html' -->{{camelcase}}
camelCase the characters in the given string.
Params
string{String}: The string to camelcase.returns{String}
Example
{{camelcase "foo bar baz"}};
<!-- results in: 'fooBarBaz' -->{{capitalize}}
Capitalize the first word in a sentence.
Params
str{String}returns{String}
Example
{{capitalize "foo bar baz"}}
<!-- results in: "Foo bar baz" -->{{capitalizeAll}}
Capitalize all words in a string.
Params
str{String}returns{String}
Example
{{capitalizeAll "foo bar baz"}}
<!-- results in: "Foo Bar Baz" -->{{center}}
Center a string using non-breaking spaces
Params
str{String}spaces{String}returns{String}
{{chop}}
Like trim, but removes both extraneous whitespace and non-word characters from the beginning and end of a string.
Params
string{String}: The string to chop.returns{String}
Example
{{chop "_ABC_"}}
<!-- results in: 'ABC' -->
{{chop "-ABC-"}}
<!-- results in: 'ABC' -->
{{chop " ABC "}}
<!-- results in: 'ABC' -->{{dashcase}}
dash-case the characters in string. Replaces non-word characters and periods with hyphens.
Params
string{String}returns{String}
Example
{{dashcase "a-b-c d_e"}}
<!-- results in: 'a-b-c-d-e' -->{{dotcase}}
dot.case the characters in string.
Params
string{String}returns{String}
Example
{{dotcase "a-b-c d_e"}}
<!-- results in: 'a.b.c.d.e' -->{{downcase}}
Lowercase all of the characters in the given string. Alias for lowercase.
Params
string{String}returns{String}
Example
{{downcase "aBcDeF"}}
<!-- results in: 'abcdef' -->{{ellipsis}}
Truncates a string to the specified length, and appends it with an elipsis, โฆ.
Params
str{String}length{Number}: The desired length of the returned string.returns{String}: The truncated string.
Example
{{ellipsis (sanitize "<span>foo bar baz</span>"), 7}}
<!-- results in: 'foo barโฆ' -->
{{ellipsis "foo bar baz", 7}}
<!-- results in: 'foo barโฆ' -->{{hyphenate}}
Replace spaces in a string with hyphens.
Params
str{String}returns{String}
Example
{{hyphenate "foo bar baz qux"}}
<!-- results in: "foo-bar-baz-qux" -->{{isString}}
Return true if value is a string.
Params
value{String}returns{Boolean}
Example
{{isString "foo"}}
<!-- results in: 'true' -->{{lowercase}}
Lowercase all characters in the given string.
Params
str{String}returns{String}
Example
{{lowercase "Foo BAR baZ"}}
<!-- results in: 'foo bar baz' -->{{occurrences}}
Return the number of occurrences of substring within the given string.
Params
str{String}substring{String}returns{Number}: Number of occurrences
Example
{{occurrences "foo bar foo bar baz" "foo"}}
<!-- results in: 2 -->{{pascalcase}}
PascalCase the characters in string.
Params
string{String}returns{String}
Example
{{pascalcase "foo bar baz"}}
<!-- results in: 'FooBarBaz' -->{{pathcase}}
path/case the characters in string.
Params
string{String}returns{String}
Example
{{pathcase "a-b-c d_e"}}
<!-- results in: 'a/b/c/d/e' -->{{plusify}}
Replace spaces in the given string with pluses.
Params
str{String}: The input stringreturns{String}: Input string with spaces replaced by plus signs
Example
{{plusify "foo bar baz"}}
<!-- results in: 'foo+bar+baz' -->{{prepend}}
Prepends the given string with the specified prefix.
Params
str{String}prefix{String}returns{String}
Example
<!-- given that "val" is "bar" -->
{{prepend val "foo-"}}
<!-- results in: 'foo-bar' -->{{raw}}
Render a block without processing mustache templates inside the block.
Params
options{Object}returns{String}
Example
{{{{#raw}}}}
{{foo}}
{{{{/raw}}}}
<!-- results in: '{{foo}}' -->{{remove}}
Remove all occurrences of substring from the given str.
Params
str{String}substring{String}returns{String}
Example
{{remove "a b a b a b" "a "}}
<!-- results in: 'b b b' -->{{removeFirst}}
Remove the first occurrence of substring from the given str.
Params
str{String}substring{String}returns{String}
Example
{{remove "a b a b a b" "a"}}
<!-- results in: ' b a b a b' -->{{replace}}
Replace all occurrences of substring a with substring b.
Params
str{String}a{String}b{String}returns{String}
Example
{{replace "a b a b a b" "a" "z"}}
<!-- results in: 'z b z b z b' -->{{replaceFirst}}
Replace the first occurrence of substring a with substring b.
Params
str{String}a{String}b{String}returns{String}
Example
{{replace "a b a b a b" "a" "z"}}
<!-- results in: 'z b a b a b' -->{{reverse}}
Reverse a string.
Params
str{String}returns{String}
Example
{{reverse "abcde"}}
<!-- results in: 'edcba' -->{{sentence}}
Sentence case the given string
Params
str{String}returns{String}
Example
{{sentence "hello world. goodbye world."}}
<!-- results in: 'Hello world. Goodbye world.' -->{{snakecase}}
snake_case the characters in the given string.
Params
string{String}returns{String}
Example
{{snakecase "a-b-c d_e"}}
<!-- results in: 'a_b_c_d_e' -->{{split}}
Split string by the given character.
Params
string{String}: The string to split.returns{String}character: Default is an empty string.
Example
{{split "a,b,c" ","}}
<!-- results in: ['a', 'b', 'c'] -->{{startsWith}}
Tests whether a string begins with the given prefix.
Params
prefix{String}testString{String}options{String}returns{String}
Example
{{#startsWith "Goodbye" "Hello, world!"}}
Whoops
{{else}}
Bro, do you even hello world?
{{/startsWith}}{{titleize}}
Title case the given string.
Params
str{String}returns{String}
Example
{{titleize "this is title case"}}
<!-- results in: 'This Is Title Case' -->{{trim}}
Removes extraneous whitespace from the beginning and end of a string.
Params
string{String}: The string to trim.returns{String}
Example
{{trim " ABC "}}
<!-- results in: 'ABC' -->{{trimLeft}}
Removes extraneous whitespace from the beginning of a string.
Params
string{String}: The string to trim.returns{String}
Example
{{trim " ABC "}}
<!-- results in: 'ABC ' -->{{trimRight}}
Removes extraneous whitespace from the end of a string.
Params
string{String}: The string to trim.returns{String}
Example
{{trimRight " ABC "}}
<!-- results in: ' ABC' -->{{truncate}}
Truncate a string to the specified length. Also see ellipsis.
Params
str{String}limit{Number}: The desired length of the returned string.suffix{String}: Optionally supply a string to use as a suffix to denote when the string has been truncated. Otherwise an ellipsis (โฆ) will be used.returns{String}: The truncated string.
Example
truncate("foo bar baz", 7);
<!-- results in: 'foo bar' -->
truncate(sanitize("<span>foo bar baz</span>", 7));
<!-- results in: 'foo bar' -->{{truncateWords}}
Truncate a string to have the specified number of words. Also see truncate.
Params
str{String}limit{Number}: The desired length of the returned string.suffix{String}: Optionally supply a string to use as a suffix to denote when the string has been truncated.returns{String}: The truncated string.
Example
truncateWords("foo bar baz", 1);
<!-- results in: 'fooโฆ' -->
truncateWords("foo bar baz", 2);
<!-- results in: 'foo barโฆ' -->
truncateWords("foo bar baz", 3);
<!-- results in: 'foo bar baz' -->{{upcase}}
Uppercase all of the characters in the given string. Alias for uppercase.
Params
string{String}returns{String}
Example
{{upcase "aBcDeF"}}
<!-- results in: 'ABCDEF' -->{{uppercase}}
Uppercase all of the characters in the given string. If used as a block helper it will uppercase the entire block. This helper does not support inverse blocks.
Params
str{String}: The string to uppercaseoptions{Object}: Handlebars options objectreturns{String}
Example
{{uppercase "aBcDeF"}}
<!-- results in: 'ABCDEF' -->File: docs/en-US/api/handlebars-helpers/url.md
URL
{{encodeURI}}
Encodes a Uniform Resource Identifier (URI) component
by replacing each instance of certain characters by
one, two, three, or four escape sequences representing
the UTF-8 encoding of the character.
Params
str{String}: The un-encoded stringreturns{String}: The endcoded string
{{escape}}
Escape the given string by replacing characters with escape sequences.
Useful for allowing the string to be used in a URL, etc.
Params
str{String}returns{String}: Escaped string.
{{decodeURI}}
Decode a Uniform Resource Identifier (URI) component.
Params
str{String}returns{String}
{{url_encode}}
Alias for encodeURI.
{{url_decode}}
Alias for decodeURI.
{{urlResolve}}
Take a base URL, and a href URL, and resolve them as a
browser would for an anchor tag.
Params
base{String}href{String}returns{String}
{{urlParse}}
Parses a url string into an object.
Params
str{String}: URL stringreturns{String}: Returns stringified JSON
{{stripQuerystring}}
Strip the query string from the given url.
Params
url{String}returns{String}: the url without the queryString
{{stripProtocol}}
Strip protocol from a url. Useful for displaying media that may have an 'http' protocol on secure connections.
Params
str{String}returns{String}: the url with http protocol stripped
Example
<!-- url = 'http://foo.bar' -->
{{stripProtocol url}}
<!-- results in: '//foo.bar' -->File: docs/en-US/api/http/index.md
Overview
HTTP API of NocoBase is designed based on Resource & Action, a superset of REST API. The operation includes but not limited to create, read, update and delete. Resource Action can be extended arbitrarily in NocoBase.
Resource
In NocoBase, resource has two expressions:
<collection><collection>.<association>
- Collection is the set of all abstract data
- Association is the associated data of collection
- Resource includes both collection and collection.association
Example
postsPostposts.userPost userposts.tagsPost tags
Action
Action on resource is expressed by :<action>
<collection>:<action><collection>.<association>:<action>
Built-in global actions for collection or association:
creategetlistupdatedestroymove
Built-in association actions for association only:
setaddremovetoggle
Example
posts:createCreate postposts.user:getGet post userposts.tags:addAdd tags to post (associate existing tags with post)
Request URL
<GET|POST> /api/<collection>:<action>
<GET|POST> /api/<collection>:<action>/<collectionIndex>
<GET|POST> /api/<collection>/<collectionIndex>/<association>:<action>
<GET|POST> /api/<collection>/<collectionIndex>/<association>:<action>/<associationIndex>Example
posts resource
POST /api/posts:create
GET /api/posts:list
GET /api/posts:get/1
POST /api/posts:update/1
POST /api/posts:destroy/1posts.comments resource
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/1posts.tags resource
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:removeLocate Resource
- Collection resource locates the data to be processed by
collectionIndex,collectionIndexmust be unique. - Association resource locates the data to be processed by
collectionIndexandassociationIndexjointly,associationIndexmay not be unique, but the joint index ofcollectionIndexandassociationIndexmust be unique.
When viewing details of association resource, the requested URL needs to provide both <collectionIndex> and <associationIndex>, <collectionIndex> is necessary as <associationIndex> may not be unique.
For example, tables.fields represents the fields of a data table:
GET /api/tables/table1/fields/title
GET /api/tables/table2/fields/titleBoth table1 and table2 have the title field, title is unique in one table, but other tables may also have fields of that name.
Request Parameters
Request parameters can be placed in the headers, parameters (query string), and body (GET requests do not have a body) of the request.
Some special request parameters:
filterData filtering, used in actions related to query.filterByTkFilter by tk field, used in actions to specify details of data.sortSorting, used in actions related to query.fieldsDate to output, used in actions related to queryappendsFields of additional relationship, used in actions related to query.exceptExclude some fields (not to output), used in actions related to query.whitelistFields whitelist, used in actions related to data creation and update.blacklistFields blacklist, used in actions related to data creation and update.
filter
Data filtering.
# simple
GET /api/posts?filter[status]=publish
# json string format is recommended, 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 information about filter operators
filterByTk
Filter by tk field. In the default settings:
- collection resource: tk is the primary key of the data table.
- association resource: tk is the targetKey field of the association.
GET /api/posts:get?filterByTk=1&fields=name,title&appends=tagssort
Sorting. To sort in the descending order, put - in front of the field.
# Sort createAt field in the ascending order
GET /api/posts:get?sort=createdAt
# Sort createAt field in the descending order
GET /api/posts:get?sort=-createdAt
# Sort multiple fields jointly, createAt field descending, title A-Z ascending
GET /api/posts:get?sort=-createdAt,titlefields
Data to output.
GET /api/posts:list?fields=name,title
Response 200 (application/json)
{
"data": [
{
"name": "",
"title": ""
}
],
"meta": {}
}appends
Fields of additional relationship.
except
Exclude some fields (not to output), used in actions related to query.
whitelist
Whitelist.
POST /api/posts:create?whitelist=title
{
"title": "My first post",
"date": "2022-05-19" # The date field will be filtered out and not be written to the database
}blacklist
Blacklist.
POST /api/posts:create?blacklist=date
# The date field will be filtered out and not be written to the database
{
"title": "My first post"
}Request Response
Format of the response:
type ResponseResult = {
data?: any; // Main data
meta?: any; // Additional Data
errors?: ResponseError[]; // Errors
};
type ResponseError = {
code?: string;
message: string;
};Example
View list:
GET /api/posts:list
Response 200 (application/json)
{
data: [
{
id: 1
}
],
meta: {
count: 1
page: 1,
pageSize: 1,
totalPage: 1
},
}View details:
GET /api/posts:get/1
Response 200 (application/json)
{
data: {
id: 1
}
}Error:
POST /api/posts:create
Response 400 (application/json)
{
errors: [
{
message: 'name must be required',
},
],
}File: docs/en-US/api/http/rest-api.md
REST API
HTTP API of NocoBase is a superset of REST API, and the standard CRUD API also supports the RESTful style.
Collection Resources
Create Collection
HTTP API
POST /api/<collection>:create
{} # JSON bodyREST API
POST /api/<collection>
{} # JSON bodyView Collection List
HTTP API
GET /api/<collection>:listREST API
GET /api/<collection>View Collection Details
HTTP API
GET /api/<collection>:get?filterByTk=<collectionIndex>
GET /api/<collection>:get/<collectionIndex>REST API
GET /api/<collection>/<collectionIndex>Update Collection
HTTP API
POST /api/<collection>:update?filterByTk=<collectionIndex>
{} # JSON body
# Or
POST /api/<collection>:update/<collectionIndex>
{} # JSON bodyREST API
PUT /api/<collection>/<collectionIndex>
{} # JSON bodyDelete Collection
HTTP API
POST /api/<collection>:destroy?filterByTk=<collectionIndex>
# Or
POST /api/<collection>:destroy/<collectionIndex>REST API
DELETE /api/<collection>/<collectionIndex>Association Resources
Create Association
HTTP API
POST /api/<collection>/<collectionIndex>/<association>:create
{} # JSON bodyREST API
POST /api/<collection>/<collectionIndex>/<association>
{} # JSON bodyView Association List
HTTP API
GET /api/<collection>/<collectionIndex>/<association>:listREST API
GET /api/<collection>/<collectionIndex>/<association>View Association Details
HTTP API
GET /api/<collection>/<collectionIndex>/<association>:get?filterByTk=<associationIndex>
# Or
GET /api/<collection>/<collectionIndex>/<association>:get/<associationIndex>REST API
GET /api/<collection>/<collectionIndex>/<association>:get/<associationIndex>Update Association
HTTP API
POST /api/<collection>/<collectionIndex>/<association>:update?filterByTk=<associationIndex>
{} # JSON body
# Or
POST /api/<collection>/<collectionIndex>/<association>:update/<associationIndex>
{} # JSON bodyREST API
PUT /api/<collection>/<collectionIndex>/<association>:update/<associationIndex>
{} # JSONDelete Association
HTTP API
POST /api/<collection>/<collectionIndex>/<association>:destroy?filterByTk=<associationIndex>
# Or
POST /api/<collection>/<collectionIndex>/<association>:destroy/<associationIndex>REST API
DELETE /api/<collection>/<collectionIndex>/<association>/<associationIndex>File: docs/en-US/api/resourcer/action.md
ctx.action
Overview
After the resource operation request is parsed by resourceManager.middleware(), some important request parameters are stored in ctx.action for use by subsequent middleware.
API
resourceName
ctx.action.resourceName
The name of the resource. It can take two forms:
a- Operates on resourcea.a.b- Operates on associated objectbof resourcea.
actionName
ctx.action.actionName
The name of the action.
sourceId
ctx.action.sourceId
When the operation object is an associated object of the resource, it represents the primary key value of the corresponding resource. For example: when resourceName is a.b, sourceId represents the primary key value of a.
params
Request parameters.
- URL parameters can be directly obtained from
ctx.action.params.
const { filterByTk } = ctx.action.params;- Request body parameters can be obtained using
ctx.action.params.values.
mergeParams()
Combines parameter content with request parameters.
ctx.action.mergeParams(
{
filter: {
name: 'foo',
},
fields: ['id', 'name'],
except: ['name'],
sort: ['id'],
page: 1,
pageSize: 10,
values: {
name: 'foo',
},
},
{
filter: 'and',
fields: 'union',
except: 'union',
sort: 'overwrite',
page: 'overwrite',
pageSize: 'overwrite',
values: 'deepMerge',
},
);
ctx.action.mergeParams(
{
filter: {},
},
{
filter: (x, y) => {
// ...
},
},
);Signature
mergeParams(params: ActionParams, strategies: MergeStrategies = {})
Type
export interface ActionParams {
filterByTk?: any;
fields?: string[];
appends?: string[];
except?: string[];
whitelist?: string[];
blacklist?: string[];
filter?: FilterOptions;
sort?: string[];
page?: number;
pageSize?: number;
values?: any;
[key: string]: any;
}
type MergeStrategyType =
| 'merge'
| 'deepMerge'
| 'overwrite'
| 'andMerge'
| 'orMerge'
| 'intersect'
| 'union';
type MergeStrategyFunc = (x: any, y: any) => any;
export type MergeStrategy = MergeStrategyType | MergeStrategyFunc;
export interface MergeStrategies {
[key: string]: MergeStrategy;
}Details
| Property | Type | Description |
|---|---|---|
params |
ActionParams |
Request parameters |
strategies |
{ [key: string]: MergeStrategies } |
Merge strategies for various fields in the request parameters |
Default strategies:
{
filter: 'andMerge',
fields: 'intersect',
appends: 'union',
except: 'union',
whitelist: 'intersect',
blacklist: 'intersect',
sort: 'overwrite',
};ActionParams
| Property | Type | Description |
|---|---|---|
filterByTk |
any |
The primary key value of the operated resource |
filter |
Filter |
Filtering parameters, refer to Filter Operators |
fields |
string[] |
Fields to retrieve |
except |
string[] |
Fields to exclude |
appends |
string[] |
Related fields to append |
whitelist |
string[] |
Field whitelist |
blacklist |
string[] |
Field blacklist |
sort |
string[] |
Sorting parameters |
page |
number |
Current page |
pageSize |
number |
Number of data items per page |
values |
any |
Request body |
[key: string] |
any |
Other extended configurations |
MergeStrategies
Predefined merge strategies or custom merge functions.
Predefined merge strategies:
| Strategy Name | Description |
|---|---|
merge |
Object.assign |
deepMerge |
Deep traversal merge |
overwrite |
Overwrite |
andMerge |
Merge filter parameters using the $and operator |
orMerge |
Merge filter parameters using the $or operator |
intersect |
Intersection |
union |
Union |
File: docs/en-US/api/resourcer/middleware.md
Middleware
It is similar to the middleware of Koa, but with more enhanced features for easy extensions.
The defined middleware can be inserted for use in multiple places, such as the resourcer, and it is up to the developer for when to invoke it.
Constructor
Signature
constructor(options: Function)constructor(options: MiddlewareOptions)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
options |
Function |
- | Handler function of middlware |
options |
MiddlewareOptions |
- | Configuration items of middlware |
options.only |
string[] |
- | Only the specified actions are allowed |
options.except |
string[] |
- | The specified actions are excluded |
options.handler |
Function |
- | Handler function |
Example
Simple definition:
const middleware = new Middleware((ctx, next) => {
await next();
});Definition with relevant parameters:
const middleware = new Middleware({
only: ['create', 'update'],
async handler(ctx, next) {
await next();
},
});Instance Methods
`getHandler()`
Get the orchestrated handler functions.
Example
The following middleware will output 1 and then 2 when requested.
const middleware = new Middleware((ctx, next) => {
console.log(1);
await next();
});
middleware.use(async (ctx, next) => {
console.log(2);
await next();
});
app.resourcer.use(middleware.getHandler());`use()`
Add a middleware function to the current middleware. Used to provide extension points for the middleware. See getHandler() for the examples.
Signature
use(middleware: Function)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
middleware |
Function |
- | Handler function of the middleware |
`disuse()`
Remove the middleware functions that have been added to the current middleware.
Signature
disuse(middleware: Function)
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
middleware |
Function |
- | Handler function of the middleware |
Example
The following example will only output 1 when requested, the output of 2 in fn1 will not be executed.
const middleware = new Middleware((ctx, next) => {
console.log(1);
await next();
});
async function fn1(ctx, next) {
console.log(2);
await next();
}
middleware.use(fn1);
app.resourcer.use(middleware.getHandler());
middleware.disuse(fn1);`canAccess()`
Check whether the current middleware is to be invoked for a specific action, it is usually handled by the resourcer internally.
Signature
canAccess(name: string): boolean
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
- | Name of the action |
Other Exports
`branch()`
Create a branch middleware for branching in the middleware.
Signature
branch(map: { [key: string]: Function }, reducer: Function, options): Function
Parameter
| Name | Type | Default | Description |
|---|---|---|---|
map |
{ [key: string]: Function } |
- | Mapping table of the branch handler function, key names are given by subsequent calculation functions when called |
reducer |
(ctx) => string |
- | Calculation function, it is used to calculate the key name of the branch based on the context |
options? |
Object |
- | Configuration items of the branch |
options.keyNotFound? |
Function |
ctx.throw(404) |
Handler function when key name is not found |
options.handlerNotSet? |
Function |
ctx.throw(404) |
The function when no handler function is defined |
Example
When authenticating user, determine what to do next according to the value of the authenticator parameter in the query section of the request URL.
app.resourcer.use(
branch(
{
password: async (ctx, next) => {
// ...
},
sms: async (ctx, next) => {
// ...
},
},
(ctx) => {
return ctx.action.params.authenticator ?? 'password';
},
),
);File: docs/en-US/api/resourcer/resource-manager.md
ResourceManager
Overview
ResourceManager is the resource management module of NocoBase, used to define resources and register operation methods for resources.
Class Methods
`define()`
Defines a resource.
app.resourceManager.define({
name: 'auth',
actions: {
check: async (ctx, next) => {
// ...
await next();
},
},
});Signature
define(options: ResourceOptions): Resource
Type
export interface ResourceOptions {
name: string;
type?: ResourceType;
actions?: {
[key: string]: ActionType;
};
only?: Array<ActionName>;
except?: Array<ActionName>;
middleware?: MiddlewareType;
middlewares?: MiddlewareType;
}
export type ResourceType =
| 'single'
| 'hasOne'
| 'hasMany'
| 'belongsTo'
| 'belongsToMany';
export type ActionType = HandlerType | ActionOptions;
export type HandlerType = (
ctx: ResourcerContext,
next: () => Promise<any>,
) => any;
export interface ActionOptions {
values?: any;
fields?: string[];
appends?: string[];
except?: string[];
whitelist?: string[];
blacklist?: string[];
filter?: FilterOptions;
sort?: string[];
page?: number;
pageSize?: number;
maxPageSize?: number;
middleware?: MiddlewareType;
middlewares?: MiddlewareType;
handler?: HandlerType;
[key: string]: any;
}Details
ResourceOptions
| Property | Type | Description | Default |
|---|---|---|---|
name |
string |
Resource name | - |
type |
ResourceType |
Resource type | single |
actions |
{ [key: string]: ActionType } |
Actions | - |
only |
ActionName[] |
Whitelist of actions |
- |
except |
ActionName[] |
Blacklist of actions |
- |
middleware |
MiddlewareType |
Middleware | - |
middlewares |
MiddlewareType |
Middlewares | - |
ActionType
There are two types of action methods:
HandlerType
This type directly defines the operation method through middleware. Example:
app.resourceManager.define({
name: 'users',
actions: {
updateProfile: async (ctx, next) => {
// ...
await next();
},
},
});ActionOptions
This type is mainly used to override the request parameters of a certain existing operation. Example:
app.resourceManager.define({
name: 'users',
actions: {
list: {
fields: [],
filter: {},
// ...
},
},
});| Property | Type | Description |
|---|---|---|
values |
any |
Default values for the action request |
filter |
Filter |
Filtering parameters, refer to Filter Operators |
fields |
string[] |
Fields to retrieve |
except |
string[] |
Fields to exclude |
appends |
string[] |
Related fields to append |
whitelist |
string[] |
Field whitelist |
blacklist |
string[] |
Field blacklist |
sort |
string[] |
Sorting parameters |
page |
number |
Current page |
pageSize |
number |
Number of data items per page |
maxPageSize |
number |
Maximum number of data items per page |
middleware |
MiddlewareType |
Middleware |
middlewares |
MiddlewareType |
Middlewares |
handler |
HandlerType |
Method executed for the action |
[key: string] |
any |
Other extended configurations |
`registerActionHandlers()`
Registers action methods.
Signature
registerActionHandler(name: ActionName, handler: HandlerType)
Type
export type DefaultActionType =
| 'list'
| 'create'
| 'get'
| 'update'
| 'dest