Doc: api database events (#887)
* docs: add full sequelize model event types * feat: update docs * fix: types * fix: update docs * docs: refactor db event apis * docs: add all events to db api Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
eaea8a7100
commit
4247c1b255
@ -510,22 +510,6 @@ asset(post1.authorId === author1.id); // true
|
|||||||
|
|
||||||
监听数据库事件。
|
监听数据库事件。
|
||||||
|
|
||||||
Database 除了对 sequelize 原生的事件封装以外,还提供以下可监听事件类型:
|
|
||||||
|
|
||||||
| 事件名称 | 是否异步 | 描述 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `'beforeDefineCollection'` | 否 | 定义 collection 之前触发 |
|
|
||||||
| `'afterDefineCollection'` | 否 | 定义 collection 之后触发 |
|
|
||||||
| `'beforeRemoveCollection'` | 否 | 移除 collection 之前触发 |
|
|
||||||
| `'afterRemoveCollection'` | 否 | 移除 collection 之后触发 |
|
|
||||||
| `<sequelize_model_global_event>` | - | 所有 sequelize 的全局事件均可通过此方式监听,详见示例部分,是否异步根据具体事件 |
|
|
||||||
| `<model_name>.<sequelize_model_event>` | 是 | 所有 sequelize model 的事件均可通过此方式监听,详见示例部分 |
|
|
||||||
| `<model_name>.afterCreateWithAssociations` | 是 | NocoBase 扩展的当连同关联数据一并创建记录成功后触发的事件(使用 Repository 的 create 方法会触发) |
|
|
||||||
| `<model_name>.afterUpdateWithAssociations` | 是 | NocoBase 扩展的当连同关联数据一并更新记录成功后触发的事件(使用 Repository 的 update 方法会触发) |
|
|
||||||
| `<model_name>.afterSaveWithAssociations` | 是 | NocoBase 扩展的当连同关联数据一并创建或更新记录成功后触发的事件(使用 Repository 的 create/update 方法都会触发) |
|
|
||||||
|
|
||||||
其中 `<model_name>.afterXXXWithAssociations` 事件只有在使用 Repository 的实例方法时才会被触发,所以建议大部分时候都使用 Repository 来进行数据操作。
|
|
||||||
|
|
||||||
**签名**
|
**签名**
|
||||||
|
|
||||||
* `on(event: string, listener: (...args: any[]) => void | Promise<void>): void`
|
* `on(event: string, listener: (...args: any[]) => void | Promise<void>): void`
|
||||||
@ -537,39 +521,9 @@ Database 除了对 sequelize 原生的事件封装以外,还提供以下可监
|
|||||||
| event | string | - | 事件名称 |
|
| event | string | - | 事件名称 |
|
||||||
| listener | Function | - | 事件监听器 |
|
| listener | Function | - | 事件监听器 |
|
||||||
|
|
||||||
**示例**
|
事件名称默认支持 Sequelize 的 Model 事件。针对全局事件,通过 `<sequelize_model_global_event>` 的名称方式监听,针对单 Model 事件,通过 `<model_name>.<sequelize_model_event>` 的名称方式监听。
|
||||||
|
|
||||||
监听 books 表事件,当创建新记录成功后触发:
|
所有内置的事件类型的参数说明和详细示例参考 [内置事件](#内置事件) 部分内容。
|
||||||
|
|
||||||
```ts
|
|
||||||
db.on('books.afterCreate', async (model, options) => {
|
|
||||||
const { transaction } = options;
|
|
||||||
const result = await model.constructor.findByPk(model.id, {
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
console.log(result);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
监听 books 表,当连同关联数据一并创建成功后触发的事件:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
db.on('books.afterCreateWithAssociations', async (model, options) => {
|
|
||||||
const { transaction } = options;
|
|
||||||
const result = await model.constructor.findByPk(model.id, {
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
console.log(result);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
监听任意表的删除事件:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
db.on('afterDestroy', async (model, options) => {
|
|
||||||
console.log(model);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### `off()`
|
### `off()`
|
||||||
|
|
||||||
@ -753,3 +707,424 @@ export default extend({
|
|||||||
以上两个文件如在调用 `import()` 时导入,通过 `extend()` 再次扩展以后,books 表将拥有 `title` 和 `price` 两个字段。
|
以上两个文件如在调用 `import()` 时导入,通过 `extend()` 再次扩展以后,books 表将拥有 `title` 和 `price` 两个字段。
|
||||||
|
|
||||||
此方法在扩展已有插件已定义的表结构时非常有用。
|
此方法在扩展已有插件已定义的表结构时非常有用。
|
||||||
|
|
||||||
|
## 内置事件
|
||||||
|
|
||||||
|
数据库会在相应的生命周期触发以下对应的事件,通过 `on()` 方法订阅后进行特定的处理可满足一些业务需要。
|
||||||
|
|
||||||
|
### `'beforeSync'` / `'afterSync'`
|
||||||
|
|
||||||
|
当新的表结构配置(字段、索引等)被同步到数据库前后触发,通常在执行 `collection.sync()`(内部调用)时会触发,一般用于一些特殊的字段扩展的逻辑处理。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.beforeSync` | 'beforeSync' | `${string}.afterSync` | 'afterSync', listener: SyncListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { SyncOptions, HookReturn } from 'sequelize/types';
|
||||||
|
|
||||||
|
type SyncListener = (options?: SyncOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
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'`
|
||||||
|
|
||||||
|
创建或更新数据前会有基于 collection 定义的规则对数据的验证过程,在验证前后会触发对应事件。当调用 `repository.create()` 或 `repository.update()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.beforeValidate` | 'beforeValidate' | `${string}.afterValidate` | 'afterValidate', listener: ValidateListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
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;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
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'`
|
||||||
|
|
||||||
|
创建一条数据前后会触发对应事件,当调用 `repository.create()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.beforeCreate` | 'beforeCreate' | `${string}.afterCreate` | 'afterCreate', listener: CreateListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { CreateOptions, HookReturn } from 'sequelize/types';
|
||||||
|
import type { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type CreateListener = (model: Model, options?: CreateOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
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'`
|
||||||
|
|
||||||
|
更新一条数据前后会触发对应事件,当调用 `repository.update()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.beforeUpdate` | 'beforeUpdate' | `${string}.afterUpdate` | 'afterUpdate', listener: UpdateListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { UpdateOptions, HookReturn } from 'sequelize/types';
|
||||||
|
import type { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type UpdateListener = (model: Model, options?: UpdateOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('beforeUpdate', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('books.afterUpdate', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'beforeSave'` / `'afterSave'`
|
||||||
|
|
||||||
|
创建或更新一条数据前后会触发对应事件,当调用 `repository.create()` 或 `repository.update()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.beforeSave` | 'beforeSave' | `${string}.afterSave` | 'afterSave', listener: SaveListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { SaveOptions, HookReturn } from 'sequelize/types';
|
||||||
|
import type { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type SaveListener = (model: Model, options?: SaveOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('beforeSave', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('books.afterSave', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'beforeDestroy'` / `'afterDestroy'`
|
||||||
|
|
||||||
|
删除一条数据前后会触发对应事件,当调用 `repository.destroy()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.beforeDestroy` | 'beforeDestroy' | `${string}.afterDestroy` | 'afterDestroy', listener: DestroyListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { DestroyOptions, HookReturn } from 'sequelize/types';
|
||||||
|
import type { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type DestroyListener = (model: Model, options?: DestroyOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('beforeDestroy', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('books.afterDestroy', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'afterCreateWithAssociations'`
|
||||||
|
|
||||||
|
创建一条携带层级关系数据的数据之后会触发对应事件,当调用 `repository.create()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.afterCreateWithAssociations` | 'afterCreateWithAssociations', listener: CreateWithAssociationsListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { CreateOptions, HookReturn } from 'sequelize/types';
|
||||||
|
import type { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type CreateWithAssociationsListener = (model: Model, options?: CreateOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('afterCreateWithAssociations', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('books.afterCreateWithAssociations', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'afterUpdateWithAssociations'`
|
||||||
|
|
||||||
|
更新一条携带层级关系数据的数据之后会触发对应事件,当调用 `repository.update()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.afterUpdateWithAssociations` | 'afterUpdateWithAssociations', listener: CreateWithAssociationsListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { UpdateOptions, HookReturn } from 'sequelize/types';
|
||||||
|
import type { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type UpdateWithAssociationsListener = (model: Model, options?: UpdateOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('afterUpdateWithAssociations', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('books.afterUpdateWithAssociations', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'afterSaveWithAssociations'`
|
||||||
|
|
||||||
|
创建或更新一条携带层级关系数据的数据之后会触发对应事件,当调用 `repository.create()` 或 `repository.update()` 时会触发。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: `${string}.afterSaveWithAssociations` | 'afterSaveWithAssociations', listener: SaveWithAssociationsListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { SaveOptions, HookReturn } from 'sequelize/types';
|
||||||
|
import type { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type SaveWithAssociationsListener = (model: Model, options?: SaveOptions) => HookReturn;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('afterSaveWithAssociations', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('books.afterSaveWithAssociations', async (model, options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'beforeDefineCollection'`
|
||||||
|
|
||||||
|
当定义一个数据表之前触发,如调用 `db.collection()` 时。
|
||||||
|
|
||||||
|
注:该事件是同步事件。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: 'beforeDefineCollection', listener: BeforeDefineCollectionListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { CollectionOptions } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type BeforeDefineCollectionListener = (options: CollectionOptions) => void;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('beforeDefineCollection', (options) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'afterDefineCollection'`
|
||||||
|
|
||||||
|
当定义一个数据表之后触发,如调用 `db.collection()` 时。
|
||||||
|
|
||||||
|
注:该事件是同步事件。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: 'afterDefineCollection', listener: AfterDefineCollectionListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { Collection } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type AfterDefineCollectionListener = (options: Collection) => void;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('afterDefineCollection', (collection) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### `'beforeRemoveCollection'` / `'afterRemoveCollection'`
|
||||||
|
|
||||||
|
当从内存中移除一个数据表前后触发,如调用 `db.removeCollection()` 时。
|
||||||
|
|
||||||
|
注:该事件是同步事件。
|
||||||
|
|
||||||
|
**签名**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
on(eventName: 'beforeRemoveCollection' | 'afterRemoveCollection', listener: RemoveCollectionListener): this
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { Collection } from '@nocobase/database';
|
||||||
|
|
||||||
|
export type RemoveCollectionListener = (options: Collection) => void;
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
db.on('beforeRemoveCollection', (collection) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('afterRemoveCollection', (collection) => {
|
||||||
|
// do something
|
||||||
|
});
|
||||||
|
```
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
"temp-dir": "2.0.0",
|
"temp-dir": "2.0.0",
|
||||||
"through2": "3.0.1",
|
"through2": "3.0.1",
|
||||||
"ts-loader": "^8.0.7",
|
"ts-loader": "^8.0.7",
|
||||||
"typescript": "^4.0.5",
|
"typescript": "4.5.5",
|
||||||
"update-notifier": "3.0.0",
|
"update-notifier": "3.0.0",
|
||||||
"vinyl-fs": "3.0.3",
|
"vinyl-fs": "3.0.3",
|
||||||
"yargs-parser": "13.1.2"
|
"yargs-parser": "13.1.2"
|
||||||
|
@ -65,7 +65,7 @@ export class Collection<
|
|||||||
return this.context.database;
|
return this.context.database;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(options: CollectionOptions, context?: CollectionContext) {
|
constructor(options: CollectionOptions, context: CollectionContext) {
|
||||||
super();
|
super();
|
||||||
this.checkOptions(options);
|
this.checkOptions(options);
|
||||||
|
|
||||||
|
@ -27,6 +27,33 @@ import { ModelHook } from './model-hook';
|
|||||||
import extendOperators from './operators';
|
import extendOperators from './operators';
|
||||||
import { RelationRepository } from './relation-repository/relation-repository';
|
import { RelationRepository } from './relation-repository/relation-repository';
|
||||||
import { Repository } from './repository';
|
import { Repository } from './repository';
|
||||||
|
import {
|
||||||
|
AfterDefineCollectionListener,
|
||||||
|
BeforeDefineCollectionListener,
|
||||||
|
CreateListener,
|
||||||
|
CreateWithAssociationsListener,
|
||||||
|
DatabaseAfterDefineCollectionEventType,
|
||||||
|
DatabaseAfterRemoveCollectionEventType,
|
||||||
|
DatabaseBeforeDefineCollectionEventType,
|
||||||
|
DatabaseBeforeRemoveCollectionEventType,
|
||||||
|
DestroyListener,
|
||||||
|
EventType,
|
||||||
|
ModelCreateEventTypes,
|
||||||
|
ModelCreateWithAssociationsEventTypes,
|
||||||
|
ModelDestroyEventTypes,
|
||||||
|
ModelSaveEventTypes,
|
||||||
|
ModelSaveWithAssociationsEventTypes,
|
||||||
|
ModelUpdateEventTypes,
|
||||||
|
ModelUpdateWithAssociationsEventTypes,
|
||||||
|
ModelValidateEventTypes,
|
||||||
|
RemoveCollectionListener,
|
||||||
|
SaveListener,
|
||||||
|
SaveWithAssociationsListener,
|
||||||
|
SyncListener,
|
||||||
|
UpdateListener,
|
||||||
|
UpdateWithAssociationsListener,
|
||||||
|
ValidateListener
|
||||||
|
} from './types';
|
||||||
|
|
||||||
export interface MergeOptions extends merge.Options {}
|
export interface MergeOptions extends merge.Options {}
|
||||||
|
|
||||||
@ -448,7 +475,20 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
|||||||
return this.sequelize.close();
|
return this.sequelize.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
on(event: string | symbol, listener): this {
|
on(event: EventType, listener: any): this;
|
||||||
|
on(event: ModelValidateEventTypes, listener: SyncListener): this;
|
||||||
|
on(event: ModelValidateEventTypes, listener: ValidateListener): this;
|
||||||
|
on(event: ModelCreateEventTypes, listener: CreateListener): this;
|
||||||
|
on(event: ModelUpdateEventTypes, listener: UpdateListener): this;
|
||||||
|
on(event: ModelSaveEventTypes, listener: SaveListener): this;
|
||||||
|
on(event: ModelDestroyEventTypes, listener: DestroyListener): this;
|
||||||
|
on(event: ModelCreateWithAssociationsEventTypes, listener: CreateWithAssociationsListener): this;
|
||||||
|
on(event: ModelUpdateWithAssociationsEventTypes, listener: UpdateWithAssociationsListener): this;
|
||||||
|
on(event: ModelSaveWithAssociationsEventTypes, listener: SaveWithAssociationsListener): this;
|
||||||
|
on(event: DatabaseBeforeDefineCollectionEventType, listener: BeforeDefineCollectionListener): this;
|
||||||
|
on(event: DatabaseAfterDefineCollectionEventType, listener: AfterDefineCollectionListener): this;
|
||||||
|
on(event: DatabaseBeforeRemoveCollectionEventType | DatabaseAfterRemoveCollectionEventType, listener: RemoveCollectionListener): this;
|
||||||
|
on(event: EventType, listener: any): this {
|
||||||
// NOTE: to match if event is a sequelize or model type
|
// NOTE: to match if event is a sequelize or model type
|
||||||
const type = this.modelHook.match(event);
|
const type = this.modelHook.match(event);
|
||||||
|
|
||||||
|
@ -9,14 +9,12 @@ export class ContextField extends Field {
|
|||||||
return DataTypes[type.toUpperCase()] || DataTypes.STRING;
|
return DataTypes[type.toUpperCase()] || DataTypes.STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
listener = async (model: Model, options) => {
|
||||||
const { name, dataIndex } = this.options;
|
const { name, dataIndex } = this.options;
|
||||||
this.listener = async (model: Model, options) => {
|
|
||||||
const { context } = options;
|
const { context } = options;
|
||||||
model.set(name, lodash.get(context, dataIndex));
|
model.set(name, lodash.get(context, dataIndex));
|
||||||
model.changed(name, true);
|
model.changed(name, true);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
bind() {
|
bind() {
|
||||||
super.bind();
|
super.bind();
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
} from 'sequelize';
|
} from 'sequelize';
|
||||||
import { Collection } from '../collection';
|
import { Collection } from '../collection';
|
||||||
import { Database } from '../database';
|
import { Database } from '../database';
|
||||||
|
import { ModelEventTypes } from '../types';
|
||||||
import { checkIdentifier } from '../utils';
|
import { checkIdentifier } from '../utils';
|
||||||
|
|
||||||
export interface FieldContext {
|
export interface FieldContext {
|
||||||
@ -68,7 +69,7 @@ export abstract class Field {
|
|||||||
// code
|
// code
|
||||||
}
|
}
|
||||||
|
|
||||||
on(eventName: string, listener: (...args: any[]) => void) {
|
on(eventName: ModelEventTypes, listener: (...args: any[]) => void) {
|
||||||
this.database.on(`${this.collection.name}.${eventName}`, listener);
|
this.database.on(`${this.collection.name}.${eventName}`, listener);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,10 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
|
|||||||
transaction,
|
transaction,
|
||||||
};
|
};
|
||||||
|
|
||||||
return [await this.find(options), await this.count(options)];
|
const count = await this.count(options);
|
||||||
|
const results = count ? await this.find(options) : [];
|
||||||
|
|
||||||
|
return [results, count];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
64
packages/core/database/src/types.ts
Normal file
64
packages/core/database/src/types.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import type { Model } from './model';
|
||||||
|
import type { ValidationOptions } from 'sequelize/types/lib/instance-validator';
|
||||||
|
import type { HookReturn } from 'sequelize/types/lib/hooks';
|
||||||
|
import type { CreateOptions, DestroyOptions, SaveOptions, SyncOptions, UpdateOptions } from 'sequelize/types';
|
||||||
|
import { Collection, CollectionOptions } from './collection';
|
||||||
|
|
||||||
|
export type CollectionNameType = string;
|
||||||
|
|
||||||
|
export type ModelSyncEventType = 'beforeSync' | 'afterSync';
|
||||||
|
export type ModelValidateEventType = 'beforeValidate' | 'afterValidate';
|
||||||
|
export type ModelCreateEventType = 'beforeCreate' | 'afterCreate';
|
||||||
|
export type ModelUpdateEventType = 'beforeUpdate' | 'afterUpdate';
|
||||||
|
export type ModelSaveEventType = 'beforeSave' | 'afterSave';
|
||||||
|
export type ModelDestroyEventType = 'beforeDestroy' | 'afterDestroy';
|
||||||
|
export type ModelCreateWithAssociationsEventType = 'afterCreateWithAssociations';
|
||||||
|
export type ModelUpdateWithAssociationsEventType = 'afterUpdateWithAssociations';
|
||||||
|
export type ModelSaveWithAssociationsEventType = 'afterSaveWithAssociations';
|
||||||
|
|
||||||
|
export type ModelValidateEventTypes = ModelValidateEventType | `${CollectionNameType}.${ModelValidateEventType}`;
|
||||||
|
export type ModelCreateEventTypes = ModelCreateEventType | `${CollectionNameType}.${ModelCreateEventType}`;
|
||||||
|
export type ModelUpdateEventTypes = ModelUpdateEventType | `${CollectionNameType}.${ModelUpdateEventType}`;
|
||||||
|
export type ModelSaveEventTypes = ModelSaveEventType | `${CollectionNameType}.${ModelSaveEventType}`;
|
||||||
|
export type ModelDestroyEventTypes = ModelDestroyEventType | `${CollectionNameType}.${ModelDestroyEventType}`;
|
||||||
|
export type ModelCreateWithAssociationsEventTypes = ModelCreateWithAssociationsEventType | `${CollectionNameType}.${ModelCreateWithAssociationsEventType}`;
|
||||||
|
export type ModelUpdateWithAssociationsEventTypes = ModelUpdateWithAssociationsEventType | `${CollectionNameType}.${ModelUpdateWithAssociationsEventType}`;
|
||||||
|
export type ModelSaveWithAssociationsEventTypes = ModelSaveWithAssociationsEventType | `${CollectionNameType}.${ModelSaveWithAssociationsEventType}`;
|
||||||
|
|
||||||
|
export type ModelEventTypes = ModelSyncEventType
|
||||||
|
| ModelValidateEventTypes
|
||||||
|
| ModelCreateEventTypes
|
||||||
|
| ModelUpdateEventTypes
|
||||||
|
| ModelSaveEventTypes
|
||||||
|
| ModelDestroyEventTypes
|
||||||
|
| ModelCreateWithAssociationsEventTypes
|
||||||
|
| ModelUpdateWithAssociationsEventTypes
|
||||||
|
| ModelSaveWithAssociationsEventTypes;
|
||||||
|
|
||||||
|
export type DatabaseBeforeDefineCollectionEventType = 'beforeDefineCollection';
|
||||||
|
export type DatabaseAfterDefineCollectionEventType = 'afterDefineCollection';
|
||||||
|
export type DatabaseBeforeRemoveCollectionEventType = 'beforeRemoveCollection';
|
||||||
|
export type DatabaseAfterRemoveCollectionEventType = 'afterRemoveCollection';
|
||||||
|
|
||||||
|
export type DatabaseEventTypes = DatabaseBeforeDefineCollectionEventType
|
||||||
|
| DatabaseAfterDefineCollectionEventType
|
||||||
|
| DatabaseBeforeRemoveCollectionEventType
|
||||||
|
| DatabaseAfterRemoveCollectionEventType;
|
||||||
|
|
||||||
|
export type EventType = ModelEventTypes | DatabaseEventTypes | string;
|
||||||
|
|
||||||
|
export type { HookReturn };
|
||||||
|
|
||||||
|
export type SyncListener = (options?: SyncOptions) => HookReturn;
|
||||||
|
export type ValidateListener = (model: Model, options?: ValidationOptions) => HookReturn;
|
||||||
|
export type CreateListener = (model: Model, options?: CreateOptions) => HookReturn;
|
||||||
|
export type UpdateListener = (model: Model, options?: UpdateOptions) => HookReturn;
|
||||||
|
export type SaveListener = (model: Model, options?: SaveOptions) => HookReturn;
|
||||||
|
export type DestroyListener = (model: Model, options?: DestroyOptions) => HookReturn;
|
||||||
|
export type CreateWithAssociationsListener = (model: Model, options?: CreateOptions) => HookReturn;
|
||||||
|
export type UpdateWithAssociationsListener = (model: Model, options?: UpdateOptions) => HookReturn;
|
||||||
|
export type SaveWithAssociationsListener = (model: Model, options?: SaveOptions) => HookReturn;
|
||||||
|
|
||||||
|
export type BeforeDefineCollectionListener = (options: CollectionOptions) => void;
|
||||||
|
export type AfterDefineCollectionListener = (collection: Collection) => void;
|
||||||
|
export type RemoveCollectionListener = (collection: Collection) => void;
|
@ -55,18 +55,11 @@ export class CollectionManagerPlugin extends Plugin {
|
|||||||
this.app.db.on('fields.beforeCreate', beforeCreateForChildrenCollection(this.app.db));
|
this.app.db.on('fields.beforeCreate', beforeCreateForChildrenCollection(this.app.db));
|
||||||
this.app.db.on('fields.beforeCreate', async (model, options) => {
|
this.app.db.on('fields.beforeCreate', async (model, options) => {
|
||||||
const type = model.get('type');
|
const type = model.get('type');
|
||||||
await this.app.db.emitAsync(`fields.${type}.beforeInitOptions`, model, {
|
const fn = beforeInitOptions[type];
|
||||||
...options,
|
if (fn) {
|
||||||
database: this.app.db,
|
await fn(model, { database: this.app.db });
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const key in beforeInitOptions) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(beforeInitOptions, key)) {
|
|
||||||
const fn = beforeInitOptions[key];
|
|
||||||
this.app.db.on(`fields.${key}.beforeInitOptions`, fn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.app.db.on('fields.afterCreate', afterCreateForReverseField(this.app.db));
|
this.app.db.on('fields.afterCreate', afterCreateForReverseField(this.app.db));
|
||||||
|
|
||||||
|
@ -22052,11 +22052,6 @@ typescript@^3.7.2:
|
|||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8"
|
resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8"
|
||||||
integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
|
integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
|
||||||
|
|
||||||
typescript@^4.0.5:
|
|
||||||
version "4.6.4"
|
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9"
|
|
||||||
integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==
|
|
||||||
|
|
||||||
uglify-js@^2.6.2, uglify-js@^2.8.22:
|
uglify-js@^2.6.2, uglify-js@^2.8.22:
|
||||||
version "2.8.29"
|
version "2.8.29"
|
||||||
resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
|
resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
|
||||||
|
Loading…
Reference in New Issue
Block a user