feat: upgrade plugin-notifications
This commit is contained in:
parent
30e31a2e79
commit
17b5839f51
@ -4,6 +4,6 @@ export * from './utils';
|
|||||||
export { Database as default } from './database';
|
export { Database as default } from './database';
|
||||||
export * from './relation-repository/belongs-to-many-repository';
|
export * from './relation-repository/belongs-to-many-repository';
|
||||||
export * from './relation-repository/belongs-to-repository';
|
export * from './relation-repository/belongs-to-repository';
|
||||||
export { Model } from 'sequelize';
|
export { Model, ModelCtor } from 'sequelize';
|
||||||
export * from './fields';
|
export * from './fields';
|
||||||
export * from './update-associations';
|
export * from './update-associations';
|
@ -56,9 +56,7 @@ export type WhiteList = string[];
|
|||||||
export type BlackList = string[];
|
export type BlackList = string[];
|
||||||
export type AssociationKeysToBeUpdate = string[];
|
export type AssociationKeysToBeUpdate = string[];
|
||||||
|
|
||||||
export type Values = {
|
export type Values = any;
|
||||||
[key: string]: string | number | Values | Array<number | string | Values>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface CountOptions extends Omit<SequelizeCreateOptions, 'distinct' | 'where' | 'include'>, TransactionAble {
|
export interface CountOptions extends Omit<SequelizeCreateOptions, 'distinct' | 'where' | 'include'>, TransactionAble {
|
||||||
fields?: Fields;
|
fields?: Fields;
|
||||||
|
7
packages/plugin-notifications/.npmignore
Normal file
7
packages/plugin-notifications/.npmignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
node_modules
|
||||||
|
*.log
|
||||||
|
docs
|
||||||
|
__tests__
|
||||||
|
tsconfig.json
|
||||||
|
src
|
||||||
|
.fatherrc.ts
|
19
packages/plugin-notifications/package.json
Normal file
19
packages/plugin-notifications/package.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "@nocobase/plugin-notifications",
|
||||||
|
"version": "0.6.0-alpha.0",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rimraf -rf lib esm dist && npm run build:cjs && npm run build:esm",
|
||||||
|
"build:cjs": "tsc --project tsconfig.build.json",
|
||||||
|
"build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir esm"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"nodemailer": "^6.6.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/nodemailer": "6.4.4",
|
||||||
|
"nodemailer-mock": "^1.5.11"
|
||||||
|
},
|
||||||
|
"gitHead": "f0b335ac30f29f25c95d7d137655fa64d8d67f1e"
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
import Database from '@nocobase/database';
|
||||||
|
import { Notification, NotificationService } from '../models';
|
||||||
|
import nodemailerMock from 'nodemailer-mock';
|
||||||
|
import { mockServer } from '@nocobase/test';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import plugin from '../server';
|
||||||
|
|
||||||
|
jest.setTimeout(300000);
|
||||||
|
|
||||||
|
describe('notifications', () => {
|
||||||
|
let db: Database;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const app = mockServer();
|
||||||
|
app.plugin(plugin);
|
||||||
|
await app.load();
|
||||||
|
db = app.db;
|
||||||
|
await db.sync();
|
||||||
|
NotificationService.createTransport = nodemailerMock.createTransport;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => db.close());
|
||||||
|
|
||||||
|
it('create', async () => {
|
||||||
|
const Notification = db.getCollection('notifications');
|
||||||
|
const notification = await Notification.repository.create({
|
||||||
|
values: {
|
||||||
|
subject: 'Subject',
|
||||||
|
body: 'hell world',
|
||||||
|
receiver_options: {
|
||||||
|
data: 'to@nocobase.com',
|
||||||
|
fromTable: 'users',
|
||||||
|
filter: {},
|
||||||
|
dataField: 'email',
|
||||||
|
},
|
||||||
|
service: {
|
||||||
|
type: 'email',
|
||||||
|
title: '阿里云邮件推送',
|
||||||
|
options: {
|
||||||
|
host: 'smtpdm.aliyun.com',
|
||||||
|
port: 465,
|
||||||
|
secure: true,
|
||||||
|
auth: {
|
||||||
|
user: 'from@nocobase.com',
|
||||||
|
pass: 'pass',
|
||||||
|
},
|
||||||
|
from: 'NocoBase<from@nocobase.com>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}) as Notification;
|
||||||
|
await notification.send();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,25 @@
|
|||||||
|
import { CollectionOptions } from '@nocobase/database';
|
||||||
|
import { NotificationLog } from '../models';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'notification_logs',
|
||||||
|
model: NotificationLog,
|
||||||
|
title: '通知日志',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
title: '接收人',
|
||||||
|
type: 'json',
|
||||||
|
name: 'receiver',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
type: 'string',
|
||||||
|
name: 'state',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '详情',
|
||||||
|
type: 'json',
|
||||||
|
name: 'response',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} as CollectionOptions;
|
@ -0,0 +1,25 @@
|
|||||||
|
import { CollectionOptions } from '@nocobase/database';
|
||||||
|
import { NotificationService } from '../models';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'notification_services',
|
||||||
|
model: NotificationService,
|
||||||
|
title: '通知服务',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
type: 'string',
|
||||||
|
name: 'type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '服务名称',
|
||||||
|
type: 'string',
|
||||||
|
name: 'title',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '配置信息',
|
||||||
|
type: 'json',
|
||||||
|
name: 'options',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} as CollectionOptions;
|
@ -0,0 +1,42 @@
|
|||||||
|
import { CollectionOptions } from '@nocobase/database';
|
||||||
|
import { Notification } from '../models';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'notifications',
|
||||||
|
model: Notification,
|
||||||
|
title: '通知',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'uid',
|
||||||
|
name: 'name',
|
||||||
|
prefix: 'n_',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '主题',
|
||||||
|
type: 'string',
|
||||||
|
name: 'subject',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '内容',
|
||||||
|
type: 'text',
|
||||||
|
name: 'body',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '接收人配置',
|
||||||
|
type: 'json',
|
||||||
|
name: 'receiver_options',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '发送服务',
|
||||||
|
type: 'belongsTo',
|
||||||
|
name: 'service',
|
||||||
|
target: 'notification_services',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '日志',
|
||||||
|
type: 'hasMany',
|
||||||
|
name: 'logs',
|
||||||
|
target: 'notification_logs',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} as CollectionOptions;
|
74
packages/plugin-notifications/src/models/Notification.ts
Normal file
74
packages/plugin-notifications/src/models/Notification.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import Database, { Model } from '@nocobase/database';
|
||||||
|
import { NotificationService } from './NotificationService';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
export class Notification extends Model {
|
||||||
|
|
||||||
|
[key: string]: any;
|
||||||
|
|
||||||
|
get db(): Database {
|
||||||
|
return this.constructor['database'];
|
||||||
|
}
|
||||||
|
|
||||||
|
async getReceiversByOptions(): Promise<any[]> {
|
||||||
|
const { data, fromTable, filter, dataField } = this.receiver_options;
|
||||||
|
let receivers = [];
|
||||||
|
if (data) {
|
||||||
|
receivers = Array.isArray(data) ? data : [data];
|
||||||
|
} else if (fromTable) {
|
||||||
|
const collection = this.db.getCollection(fromTable);
|
||||||
|
const rows = await collection.repository.find({
|
||||||
|
filter,
|
||||||
|
});
|
||||||
|
receivers = rows.map(row => row[dataField]);
|
||||||
|
}
|
||||||
|
return receivers;
|
||||||
|
}
|
||||||
|
|
||||||
|
async send(options: any = {}) {
|
||||||
|
if (!this.service) {
|
||||||
|
this.service = await this.getService();
|
||||||
|
}
|
||||||
|
const receivers = await this.getReceiversByOptions();
|
||||||
|
let { to } = options;
|
||||||
|
if (to) {
|
||||||
|
to = Array.isArray(to) ? to : [to];
|
||||||
|
receivers.push(...to);
|
||||||
|
}
|
||||||
|
console.log(receivers)
|
||||||
|
for (const receiver of receivers) {
|
||||||
|
try {
|
||||||
|
const response = await (this.service as NotificationService).send({
|
||||||
|
to: receiver,
|
||||||
|
subject: this.getSubject(),
|
||||||
|
html: this.getBody(options),
|
||||||
|
});
|
||||||
|
await this.createLog({
|
||||||
|
receiver,
|
||||||
|
state: 'success',
|
||||||
|
response,
|
||||||
|
});
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, 100);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
await this.createLog({
|
||||||
|
receiver,
|
||||||
|
state: 'fail',
|
||||||
|
response: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSubject() {
|
||||||
|
return this.subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBody(data) {
|
||||||
|
const compiled = _.template(this.body)
|
||||||
|
const body = compiled(data);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
import { Model } from '@nocobase/database';
|
||||||
|
|
||||||
|
export class NotificationLog extends Model {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Model } from '@nocobase/database';
|
||||||
|
import nodemailer from 'nodemailer';
|
||||||
|
|
||||||
|
export class NotificationService extends Model {
|
||||||
|
[key: string]: any;
|
||||||
|
|
||||||
|
static createTransport = nodemailer.createTransport;
|
||||||
|
|
||||||
|
private _transporter = null;
|
||||||
|
|
||||||
|
get transporter() {
|
||||||
|
if (this._transporter) {
|
||||||
|
return this._transporter;
|
||||||
|
}
|
||||||
|
return this._transporter = NotificationService.createTransport(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
async send(options) {
|
||||||
|
const { from } = this.options;
|
||||||
|
const mailOptions = {
|
||||||
|
from,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
return this.transporter.sendMail(mailOptions);
|
||||||
|
}
|
||||||
|
}
|
3
packages/plugin-notifications/src/models/index.ts
Normal file
3
packages/plugin-notifications/src/models/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './Notification';
|
||||||
|
export * from './NotificationLog';
|
||||||
|
export * from './NotificationService';
|
11
packages/plugin-notifications/src/server.ts
Normal file
11
packages/plugin-notifications/src/server.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import { PluginOptions } from '@nocobase/server';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'notifications',
|
||||||
|
async load() {
|
||||||
|
await this.app.db.import({
|
||||||
|
directory: path.resolve(__dirname, 'collections'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} as PluginOptions
|
9
packages/plugin-notifications/tsconfig.build.json
Normal file
9
packages/plugin-notifications/tsconfig.build.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.build.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./lib",
|
||||||
|
"declaration": true
|
||||||
|
},
|
||||||
|
"include": ["./src/**/*.ts", "./src/**/*.tsx"],
|
||||||
|
"exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
|
||||||
|
}
|
5
packages/plugin-notifications/tsconfig.json
Normal file
5
packages/plugin-notifications/tsconfig.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"include": ["./src/**/*.ts", "./src/**/*.tsx"],
|
||||||
|
"exclude": ["./esm/*", "./lib/*"]
|
||||||
|
}
|
20
yarn.lock
20
yarn.lock
@ -2437,6 +2437,13 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/node/-/node-14.17.34.tgz#fe4b38b3f07617c0fa31ae923fca9249641038f0"
|
resolved "https://registry.npmjs.org/@types/node/-/node-14.17.34.tgz#fe4b38b3f07617c0fa31ae923fca9249641038f0"
|
||||||
integrity sha512-USUftMYpmuMzeWobskoPfzDi+vkpe0dvcOBRNOscFrGxVp4jomnRxWuVohgqBow2xyIPC0S3gjxV/5079jhmDg==
|
integrity sha512-USUftMYpmuMzeWobskoPfzDi+vkpe0dvcOBRNOscFrGxVp4jomnRxWuVohgqBow2xyIPC0S3gjxV/5079jhmDg==
|
||||||
|
|
||||||
|
"@types/nodemailer@6.4.4":
|
||||||
|
version "6.4.4"
|
||||||
|
resolved "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b"
|
||||||
|
integrity sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/normalize-package-data@^2.4.0":
|
"@types/normalize-package-data@^2.4.0":
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
|
resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
|
||||||
@ -9584,6 +9591,19 @@ node-releases@^2.0.1:
|
|||||||
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
|
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
|
||||||
integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
|
integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
|
||||||
|
|
||||||
|
nodemailer-mock@^1.5.11:
|
||||||
|
version "1.5.11"
|
||||||
|
resolved "https://registry.npmjs.org/nodemailer-mock/-/nodemailer-mock-1.5.11.tgz#1bb6b9af44e9007380191d32e33555ea136a819f"
|
||||||
|
integrity sha512-RbqkppKkptTgSzry3q8u/YD8pxulln/hYQ30O5brFRki8gEKv7KoAYGwfErZM2VsI7nGNBYRo5IOLnMW3NXBcw==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.3.2"
|
||||||
|
nodemailer "^6.x"
|
||||||
|
|
||||||
|
nodemailer@^6.6.1, nodemailer@^6.x:
|
||||||
|
version "6.7.2"
|
||||||
|
resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.2.tgz#44b2ad5f7ed71b7067f7a21c4fedabaec62b85e0"
|
||||||
|
integrity sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q==
|
||||||
|
|
||||||
"nopt@2 || 3":
|
"nopt@2 || 3":
|
||||||
version "3.0.6"
|
version "3.0.6"
|
||||||
resolved "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
|
resolved "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
|
||||||
|
Loading…
Reference in New Issue
Block a user