@ruiapp/rapid-core 0.2.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/core/routeContext.d.ts +2 -2
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.js +236 -21
  4. package/dist/plugins/mail/MailPlugin.d.ts +23 -0
  5. package/dist/plugins/mail/MailPluginTypes.d.ts +24 -0
  6. package/dist/plugins/mail/MailService.d.ts +8 -0
  7. package/dist/plugins/mail/actionHandlers/index.d.ts +2 -0
  8. package/dist/plugins/mail/models/index.d.ts +2 -0
  9. package/dist/plugins/mail/routes/index.d.ts +2 -0
  10. package/dist/plugins/notification/NotificationPlugin.d.ts +21 -0
  11. package/dist/plugins/notification/NotificationPluginTypes.d.ts +12 -0
  12. package/dist/plugins/notification/NotificationService.d.ts +8 -0
  13. package/dist/plugins/notification/actionHandlers/index.d.ts +2 -0
  14. package/dist/plugins/notification/models/Notification.d.ts +3 -0
  15. package/dist/plugins/notification/models/index.d.ts +2 -0
  16. package/dist/plugins/notification/routes/index.d.ts +2 -0
  17. package/package.json +3 -1
  18. package/src/core/routeContext.ts +9 -5
  19. package/src/dataAccess/entityManager.ts +8 -2
  20. package/src/index.ts +6 -0
  21. package/src/plugins/mail/MailPlugin.ts +74 -0
  22. package/src/plugins/mail/MailPluginTypes.ts +27 -0
  23. package/src/plugins/mail/MailService.ts +38 -0
  24. package/src/plugins/mail/actionHandlers/index.ts +3 -0
  25. package/src/plugins/mail/models/index.ts +1 -0
  26. package/src/plugins/mail/routes/index.ts +1 -0
  27. package/src/plugins/notification/NotificationPlugin.ts +68 -0
  28. package/src/plugins/notification/NotificationPluginTypes.ts +13 -0
  29. package/src/plugins/notification/NotificationService.ts +25 -0
  30. package/src/plugins/notification/actionHandlers/index.ts +3 -0
  31. package/src/plugins/notification/models/Notification.ts +57 -0
  32. package/src/plugins/notification/models/index.ts +3 -0
  33. package/src/plugins/notification/routes/index.ts +1 -0
@@ -4,7 +4,6 @@ import { HttpStatus } from "./http-types";
4
4
  import { IRpdServer } from "./server";
5
5
  export type Next = () => Promise<void>;
6
6
  export declare class RouteContext {
7
- #private;
8
7
  readonly request: RapidRequest;
9
8
  readonly response: RapidResponse;
10
9
  readonly state: Record<string, any>;
@@ -12,7 +11,8 @@ export declare class RouteContext {
12
11
  path: string;
13
12
  params: Record<string, string>;
14
13
  routeConfig: any;
15
- constructor(server: IRpdServer, request: RapidRequest);
14
+ static newSystemOperationContext(server: IRpdServer): RouteContext;
15
+ constructor(server: IRpdServer, request?: RapidRequest);
16
16
  set(headerName: string, headerValue: string): void;
17
17
  json(obj: any, status?: HttpStatus, headers?: HeadersInit): void;
18
18
  redirect(url: string, status?: HttpStatus): void;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,10 @@ export * from "./plugins/sequence/SequencePluginTypes";
16
16
  export { default as WebhooksPlugin } from "./plugins/webhooks/WebhooksPlugin";
17
17
  export { default as AuthPlugin } from "./plugins/auth/AuthPlugin";
18
18
  export { default as FileManagePlugin } from "./plugins/fileManage/FileManagePlugin";
19
+ export { default as MailPlugin } from "./plugins/mail/MailPlugin";
20
+ export * from "./plugins/mail/MailPluginTypes";
21
+ export { default as NotificationPlugin } from "./plugins/notification/NotificationPlugin";
22
+ export * from "./plugins/notification/NotificationPluginTypes";
19
23
  export { default as ServerOperationPlugin } from "./plugins/serverOperation/ServerOperationPlugin";
20
24
  export * from "./plugins/serverOperation/ServerOperationPluginTypes";
21
25
  export { default as SettingPlugin } from "./plugins/setting/SettingPlugin";
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ var bcrypt = require('bcrypt');
13
13
  var path = require('path');
14
14
  var fs = require('fs');
15
15
  var uuid = require('uuid');
16
+ var nodemailer = require('nodemailer');
16
17
  var cron = require('cron');
17
18
  var xstate = require('xstate');
18
19
 
@@ -43,6 +44,7 @@ var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
43
44
  var bcrypt__default = /*#__PURE__*/_interopDefaultLegacy(bcrypt);
44
45
  var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
45
46
  var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
47
+ var nodemailer__default = /*#__PURE__*/_interopDefaultLegacy(nodemailer);
46
48
  var cron__namespace = /*#__PURE__*/_interopNamespace(cron);
47
49
 
48
50
  function fixBigIntJSONSerialize() {
@@ -1040,7 +1042,6 @@ class RapidResponse {
1040
1042
  }
1041
1043
 
1042
1044
  class RouteContext {
1043
- #logger;
1044
1045
  request;
1045
1046
  response;
1046
1047
  state;
@@ -1048,14 +1049,18 @@ class RouteContext {
1048
1049
  path;
1049
1050
  params;
1050
1051
  routeConfig;
1052
+ static newSystemOperationContext(server) {
1053
+ return new RouteContext(server);
1054
+ }
1051
1055
  constructor(server, request) {
1052
- this.#logger = server.getLogger();
1053
1056
  this.request = request;
1054
1057
  this.state = {};
1055
1058
  this.response = new RapidResponse();
1056
1059
  // `method` and `path` are used by `koa-tree-router` to match route
1057
- this.method = request.method;
1058
- this.path = request.url.pathname;
1060
+ if (this.request) {
1061
+ this.method = request.method;
1062
+ this.path = request.url.pathname;
1063
+ }
1059
1064
  }
1060
1065
  // `koa-tree-router` uses this method to set headers
1061
1066
  set(headerName, headerValue) {
@@ -2548,11 +2553,16 @@ async function findEntities(server, dataAccessor, options) {
2548
2553
  return entities;
2549
2554
  }
2550
2555
  async function findEntity(server, dataAccessor, options) {
2551
- const entities = await findEntities(server, dataAccessor, options);
2556
+ const entities = await findEntities(server, dataAccessor, {
2557
+ ...options,
2558
+ ...{
2559
+ limit: 1,
2560
+ },
2561
+ });
2552
2562
  return lodash.first(entities);
2553
2563
  }
2554
2564
  async function findById(server, dataAccessor, options) {
2555
- const { id, properties, keepNonPropertyFields, routeContext } = options;
2565
+ const { id, properties, relations, keepNonPropertyFields, routeContext } = options;
2556
2566
  return await findEntity(server, dataAccessor, {
2557
2567
  filters: [
2558
2568
  {
@@ -2562,6 +2572,7 @@ async function findById(server, dataAccessor, options) {
2562
2572
  },
2563
2573
  ],
2564
2574
  properties,
2575
+ relations,
2565
2576
  keepNonPropertyFields,
2566
2577
  routeContext,
2567
2578
  });
@@ -5361,7 +5372,7 @@ var generateSn$1 = /*#__PURE__*/Object.freeze({
5361
5372
  handler: handler$e
5362
5373
  });
5363
5374
 
5364
- var pluginActionHandlers$5 = [generateSn$1];
5375
+ var pluginActionHandlers$7 = [generateSn$1];
5365
5376
 
5366
5377
  var SequenceRule = {
5367
5378
  maintainedBy: "sequencePlugin",
@@ -5452,7 +5463,7 @@ var SequenceAutoIncrementRecord = {
5452
5463
  ],
5453
5464
  };
5454
5465
 
5455
- var pluginModels$3 = [SequenceRule, SequenceAutoIncrementRecord];
5466
+ var pluginModels$5 = [SequenceRule, SequenceAutoIncrementRecord];
5456
5467
 
5457
5468
  var generateSn = {
5458
5469
  namespace: "svc",
@@ -5468,7 +5479,7 @@ var generateSn = {
5468
5479
  ],
5469
5480
  };
5470
5481
 
5471
- var pluginRoutes$5 = [generateSn];
5482
+ var pluginRoutes$7 = [generateSn];
5472
5483
 
5473
5484
  const segmentType$5 = "literal";
5474
5485
  async function resolveSegmentValue$5(server, ruleCode, config, input) {
@@ -5664,7 +5675,7 @@ class SequenceService {
5664
5675
  /**
5665
5676
  * Sequence plugin
5666
5677
  */
5667
- class SequencePlugin {
5678
+ class SequencePlugin$1 {
5668
5679
  #sequenceService;
5669
5680
  get sequenceService() {
5670
5681
  return this.#sequenceService;
@@ -5685,19 +5696,19 @@ class SequencePlugin {
5685
5696
  return [];
5686
5697
  }
5687
5698
  async registerActionHandlers(server) {
5688
- for (const actionHandler of pluginActionHandlers$5) {
5699
+ for (const actionHandler of pluginActionHandlers$7) {
5689
5700
  server.registerActionHandler(this, actionHandler);
5690
5701
  }
5691
5702
  }
5692
5703
  async configureModels(server, applicationConfig) {
5693
- server.appendApplicationConfig({ models: pluginModels$3 });
5704
+ server.appendApplicationConfig({ models: pluginModels$5 });
5694
5705
  }
5695
5706
  async configureServices(server, applicationConfig) {
5696
5707
  this.#sequenceService = new SequenceService(server);
5697
5708
  server.registerService("sequenceService", this.#sequenceService);
5698
5709
  }
5699
5710
  async configureRoutes(server, applicationConfig) {
5700
- server.appendApplicationConfig({ routes: pluginRoutes$5 });
5711
+ server.appendApplicationConfig({ routes: pluginRoutes$7 });
5701
5712
  }
5702
5713
  async onApplicationLoaded(server, applicationConfig) {
5703
5714
  const models = server.getApplicationConfig().models;
@@ -6118,7 +6129,7 @@ var resetPassword$1 = /*#__PURE__*/Object.freeze({
6118
6129
  handler: handler$9
6119
6130
  });
6120
6131
 
6121
- var pluginActionHandlers$4 = [changePassword$1, createSession, deleteSession, getMyProfile$2, resetPassword$1];
6132
+ var pluginActionHandlers$6 = [changePassword$1, createSession, deleteSession, getMyProfile$2, resetPassword$1];
6122
6133
 
6123
6134
  var AccessToken = {
6124
6135
  maintainedBy: "authManager",
@@ -6175,7 +6186,7 @@ var AccessToken = {
6175
6186
  ],
6176
6187
  };
6177
6188
 
6178
- var pluginModels$2 = [AccessToken];
6189
+ var pluginModels$4 = [AccessToken];
6179
6190
 
6180
6191
  var changePassword = {
6181
6192
  namespace: "auth",
@@ -6247,7 +6258,7 @@ var signout$1 = {
6247
6258
  ],
6248
6259
  };
6249
6260
 
6250
- var pluginRoutes$4 = [changePassword, getMyProfile$1, resetPassword, signin$1, signout$1];
6261
+ var pluginRoutes$6 = [changePassword, getMyProfile$1, resetPassword, signin$1, signout$1];
6251
6262
 
6252
6263
  /**
6253
6264
  * Auth manager plugin
@@ -6269,15 +6280,15 @@ class AuthPlugin {
6269
6280
  return [];
6270
6281
  }
6271
6282
  async registerActionHandlers(server) {
6272
- for (const actionHandler of pluginActionHandlers$4) {
6283
+ for (const actionHandler of pluginActionHandlers$6) {
6273
6284
  server.registerActionHandler(this, actionHandler);
6274
6285
  }
6275
6286
  }
6276
6287
  async configureModels(server, applicationConfig) {
6277
- server.appendApplicationConfig({ models: pluginModels$2 });
6288
+ server.appendApplicationConfig({ models: pluginModels$4 });
6278
6289
  }
6279
6290
  async configureRoutes(server, applicationConfig) {
6280
- server.appendApplicationConfig({ routes: pluginRoutes$4 });
6291
+ server.appendApplicationConfig({ routes: pluginRoutes$6 });
6281
6292
  }
6282
6293
  async onPrepareRouteContext(server, routeContext) {
6283
6294
  const request = routeContext.request;
@@ -6498,7 +6509,7 @@ var signout = {
6498
6509
  ],
6499
6510
  };
6500
6511
 
6501
- var pluginRoutes$3 = [getMyProfile, signin, signout];
6512
+ var pluginRoutes$5 = [getMyProfile, signin, signout];
6502
6513
 
6503
6514
  /**
6504
6515
  * File manager plugin
@@ -6524,9 +6535,211 @@ class FileManager {
6524
6535
  server.registerActionHandler(this, downloadFileActionHandler);
6525
6536
  server.registerActionHandler(this, uploadFileActionHandler);
6526
6537
  }
6538
+ async configureRoutes(server, applicationConfig) {
6539
+ server.appendApplicationConfig({ routes: pluginRoutes$5 });
6540
+ }
6541
+ }
6542
+
6543
+ var pluginActionHandlers$5 = [];
6544
+
6545
+ var pluginModels$3 = [];
6546
+
6547
+ var pluginRoutes$4 = [];
6548
+
6549
+ class MailService {
6550
+ #server;
6551
+ #smtpServer;
6552
+ constructor(server, smtpServer) {
6553
+ this.#server = server;
6554
+ this.#smtpServer = smtpServer;
6555
+ }
6556
+ async sendMail(routeContext, server, options) {
6557
+ const smtpServer = this.#smtpServer;
6558
+ const transporter = nodemailer__default["default"].createTransport({
6559
+ host: smtpServer.host,
6560
+ port: smtpServer.port,
6561
+ secure: smtpServer.secure,
6562
+ auth: {
6563
+ user: smtpServer.username,
6564
+ pass: smtpServer.password,
6565
+ },
6566
+ });
6567
+ const info = await transporter.sendMail({
6568
+ from: options.from,
6569
+ to: options.to,
6570
+ subject: options.subject,
6571
+ text: options.text,
6572
+ html: options.html,
6573
+ });
6574
+ return info;
6575
+ }
6576
+ }
6577
+
6578
+ /**
6579
+ * Mail plugin
6580
+ */
6581
+ class MailPlugin {
6582
+ #mailService;
6583
+ #config;
6584
+ constructor(config) {
6585
+ this.#config = config;
6586
+ }
6587
+ get mailService() {
6588
+ return this.#mailService;
6589
+ }
6590
+ get code() {
6591
+ return "mail";
6592
+ }
6593
+ get description() {
6594
+ return null;
6595
+ }
6596
+ get extendingAbilities() {
6597
+ return [];
6598
+ }
6599
+ get configurableTargets() {
6600
+ return [];
6601
+ }
6602
+ get configurations() {
6603
+ return [];
6604
+ }
6605
+ async registerActionHandlers(server) {
6606
+ for (const actionHandler of pluginActionHandlers$5) {
6607
+ server.registerActionHandler(this, actionHandler);
6608
+ }
6609
+ }
6610
+ async configureModels(server, applicationConfig) {
6611
+ server.appendApplicationConfig({ models: pluginModels$3 });
6612
+ }
6613
+ async configureServices(server, applicationConfig) {
6614
+ this.#mailService = new MailService(server, this.#config.smtpServer);
6615
+ server.registerService("mailService", this.#mailService);
6616
+ }
6617
+ async configureRoutes(server, applicationConfig) {
6618
+ server.appendApplicationConfig({ routes: pluginRoutes$4 });
6619
+ }
6620
+ async onApplicationLoaded(server, applicationConfig) { }
6621
+ }
6622
+
6623
+ var pluginActionHandlers$4 = [];
6624
+
6625
+ var Notification = {
6626
+ maintainedBy: "notification",
6627
+ namespace: "svc",
6628
+ name: "notification",
6629
+ singularCode: "notification",
6630
+ pluralCode: "notifications",
6631
+ schema: "public",
6632
+ tableName: "notifications",
6633
+ properties: [
6634
+ {
6635
+ name: "id",
6636
+ code: "id",
6637
+ columnName: "id",
6638
+ type: "integer",
6639
+ required: true,
6640
+ autoIncrement: true,
6641
+ },
6642
+ {
6643
+ name: "标题",
6644
+ code: "title",
6645
+ columnName: "title",
6646
+ type: "text",
6647
+ required: true,
6648
+ },
6649
+ {
6650
+ name: "内容",
6651
+ code: "content",
6652
+ columnName: "content",
6653
+ type: "text",
6654
+ required: false,
6655
+ },
6656
+ {
6657
+ name: "已读",
6658
+ code: "read",
6659
+ columnName: "read",
6660
+ type: "boolean",
6661
+ required: false,
6662
+ defaultValue: "false",
6663
+ },
6664
+ {
6665
+ name: "详细信息",
6666
+ code: "details",
6667
+ columnName: "details",
6668
+ description: '{"url": "", "actions": [{"text": "", "url": ""}]}',
6669
+ type: "json",
6670
+ },
6671
+ {
6672
+ name: "用户",
6673
+ code: "user",
6674
+ type: "relation",
6675
+ targetSingularCode: "oc_user",
6676
+ targetIdColumnName: "user_id",
6677
+ },
6678
+ ],
6679
+ };
6680
+
6681
+ var pluginModels$2 = [Notification];
6682
+
6683
+ var pluginRoutes$3 = [];
6684
+
6685
+ class NotificationService {
6686
+ #server;
6687
+ constructor(server) {
6688
+ this.#server = server;
6689
+ }
6690
+ async sendNotification(routeContext, server, options) {
6691
+ const notificationManager = server.getEntityManager("notification");
6692
+ return await notificationManager.createEntity({
6693
+ routeContext,
6694
+ entity: {
6695
+ title: options.title,
6696
+ content: options.content,
6697
+ details: options.details,
6698
+ user: options.userId,
6699
+ },
6700
+ });
6701
+ }
6702
+ }
6703
+
6704
+ /**
6705
+ * Notification plugin
6706
+ */
6707
+ class SequencePlugin {
6708
+ #notificationService;
6709
+ get notificationService() {
6710
+ return this.#notificationService;
6711
+ }
6712
+ get code() {
6713
+ return "notification";
6714
+ }
6715
+ get description() {
6716
+ return null;
6717
+ }
6718
+ get extendingAbilities() {
6719
+ return [];
6720
+ }
6721
+ get configurableTargets() {
6722
+ return [];
6723
+ }
6724
+ get configurations() {
6725
+ return [];
6726
+ }
6727
+ async registerActionHandlers(server) {
6728
+ for (const actionHandler of pluginActionHandlers$4) {
6729
+ server.registerActionHandler(this, actionHandler);
6730
+ }
6731
+ }
6732
+ async configureModels(server, applicationConfig) {
6733
+ server.appendApplicationConfig({ models: pluginModels$2 });
6734
+ }
6735
+ async configureServices(server, applicationConfig) {
6736
+ this.#notificationService = new NotificationService(server);
6737
+ server.registerService("notificationService", this.#notificationService);
6738
+ }
6527
6739
  async configureRoutes(server, applicationConfig) {
6528
6740
  server.appendApplicationConfig({ routes: pluginRoutes$3 });
6529
6741
  }
6742
+ async onApplicationLoaded(server, applicationConfig) { }
6530
6743
  }
6531
6744
 
6532
6745
  const code$5 = "runServerOperation";
@@ -7825,12 +8038,14 @@ exports.DataManagePlugin = DataManager;
7825
8038
  exports.EntityAccessControlPlugin = EntityAccessControlPlugin;
7826
8039
  exports.FileManagePlugin = FileManager;
7827
8040
  exports.GlobalRequest = GlobalRequest;
8041
+ exports.MailPlugin = MailPlugin;
7828
8042
  exports.MetaManagePlugin = MetaManager;
8043
+ exports.NotificationPlugin = SequencePlugin;
7829
8044
  exports.RapidRequest = RapidRequest;
7830
8045
  exports.RapidServer = RapidServer;
7831
8046
  exports.RouteContext = RouteContext;
7832
8047
  exports.RouteManagePlugin = RouteManager;
7833
- exports.SequencePlugin = SequencePlugin;
8048
+ exports.SequencePlugin = SequencePlugin$1;
7834
8049
  exports.ServerOperationPlugin = ServerOperationPlugin;
7835
8050
  exports.SettingPlugin = SettingPlugin;
7836
8051
  exports.StateMachinePlugin = StateMachinePlugin;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Mail plugin
3
+ */
4
+ import { RpdApplicationConfig } from "../../types";
5
+ import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
6
+ import MailService from "./MailService";
7
+ import { MailPluginConfig } from "./MailPluginTypes";
8
+ declare class MailPlugin implements RapidPlugin {
9
+ #private;
10
+ constructor(config: MailPluginConfig);
11
+ get mailService(): MailService;
12
+ get code(): string;
13
+ get description(): string;
14
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[];
15
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[];
16
+ get configurations(): RpdConfigurationItemOptions[];
17
+ registerActionHandlers(server: IRpdServer): Promise<any>;
18
+ configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
19
+ configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
20
+ configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
21
+ onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<void>;
22
+ }
23
+ export default MailPlugin;
@@ -0,0 +1,24 @@
1
+ export type MailPluginConfig = {
2
+ smtpServer: RpdMailSmtpServer;
3
+ };
4
+ export type RpdMailSmtpServer = {
5
+ host: string;
6
+ port: number;
7
+ secure: boolean;
8
+ username: string;
9
+ password: string;
10
+ };
11
+ export type RpdMail = {
12
+ from?: string;
13
+ to?: string;
14
+ subject?: string;
15
+ text?: string;
16
+ html?: string;
17
+ };
18
+ export type SendMailOptions = {
19
+ from?: string;
20
+ to?: string;
21
+ subject?: string;
22
+ text?: string;
23
+ html?: string;
24
+ };
@@ -0,0 +1,8 @@
1
+ import { IRpdServer } from "../../core/server";
2
+ import { RpdMailSmtpServer, SendMailOptions } from "./MailPluginTypes";
3
+ import { RouteContext } from "../../core/routeContext";
4
+ export default class MailService {
5
+ #private;
6
+ constructor(server: IRpdServer, smtpServer: RpdMailSmtpServer);
7
+ sendMail(routeContext: RouteContext, server: IRpdServer, options: SendMailOptions): Promise<any>;
8
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: any[];
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: any[];
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: any[];
2
+ export default _default;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Notification plugin
3
+ */
4
+ import { RpdApplicationConfig } from "../../types";
5
+ import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
6
+ import NotificationService from "./NotificationService";
7
+ declare class SequencePlugin implements RapidPlugin {
8
+ #private;
9
+ get notificationService(): NotificationService;
10
+ get code(): string;
11
+ get description(): string;
12
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[];
13
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[];
14
+ get configurations(): RpdConfigurationItemOptions[];
15
+ registerActionHandlers(server: IRpdServer): Promise<any>;
16
+ configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
17
+ configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
18
+ configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
19
+ onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<void>;
20
+ }
21
+ export default SequencePlugin;
@@ -0,0 +1,12 @@
1
+ export type RpdNotification = {
2
+ id?: number;
3
+ title: string;
4
+ content?: string;
5
+ details?: any;
6
+ };
7
+ export type SendNotificationOptions = {
8
+ userId: number;
9
+ title: string;
10
+ content?: string;
11
+ details?: any;
12
+ };
@@ -0,0 +1,8 @@
1
+ import { IRpdServer } from "../../core/server";
2
+ import { SendNotificationOptions, RpdNotification } from "./NotificationPluginTypes";
3
+ import { RouteContext } from "../../core/routeContext";
4
+ export default class NotificationService {
5
+ #private;
6
+ constructor(server: IRpdServer);
7
+ sendNotification(routeContext: RouteContext, server: IRpdServer, options: SendNotificationOptions): Promise<RpdNotification>;
8
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: any[];
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import { RpdDataModel } from "../../../types";
2
+ declare const _default: RpdDataModel;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("../../..").RpdDataModel[];
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: any[];
2
+ export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.2.13",
3
+ "version": "0.3.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,6 +11,7 @@
11
11
  "@types/jsonwebtoken": "^9.0.5",
12
12
  "@types/lodash": "^4.14.186",
13
13
  "@types/node": "^20.11.16",
14
+ "@types/nodemailer": "^6.4.16",
14
15
  "rimraf": "^3.0.2",
15
16
  "rollup": "^2.79.1",
16
17
  "rollup-plugin-tsc-alias": "^1.1.2",
@@ -29,6 +30,7 @@
29
30
  "xstate": "^5.13.0"
30
31
  },
31
32
  "peerDependencies": {
33
+ "nodemailer": "^6.9.15",
32
34
  "winston": "^3.11.0"
33
35
  },
34
36
  "scripts": {
@@ -8,7 +8,6 @@ import { Logger } from "~/facilities/log/LogFacility";
8
8
  export type Next = () => Promise<void>;
9
9
 
10
10
  export class RouteContext {
11
- #logger: Logger;
12
11
  readonly request: RapidRequest;
13
12
  readonly response: RapidResponse;
14
13
  readonly state: Record<string, any>;
@@ -17,15 +16,20 @@ export class RouteContext {
17
16
  params: Record<string, string>;
18
17
  routeConfig: any;
19
18
 
20
- constructor(server: IRpdServer, request: RapidRequest) {
21
- this.#logger = server.getLogger();
19
+ static newSystemOperationContext(server: IRpdServer) {
20
+ return new RouteContext(server);
21
+ }
22
+
23
+ constructor(server: IRpdServer, request?: RapidRequest) {
22
24
  this.request = request;
23
25
  this.state = {};
24
26
  this.response = new RapidResponse();
25
27
 
26
28
  // `method` and `path` are used by `koa-tree-router` to match route
27
- this.method = request.method;
28
- this.path = request.url.pathname;
29
+ if (this.request) {
30
+ this.method = request.method;
31
+ this.path = request.url.pathname;
32
+ }
29
33
  }
30
34
 
31
35
  // `koa-tree-router` uses this method to set headers
@@ -347,12 +347,17 @@ async function findEntities(server: IRpdServer, dataAccessor: IRpdDataAccessor,
347
347
  }
348
348
 
349
349
  async function findEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor, options: FindEntityOptions) {
350
- const entities = await findEntities(server, dataAccessor, options);
350
+ const entities = await findEntities(server, dataAccessor, {
351
+ ...options,
352
+ ...{
353
+ limit: 1,
354
+ },
355
+ });
351
356
  return first(entities);
352
357
  }
353
358
 
354
359
  async function findById(server: IRpdServer, dataAccessor: IRpdDataAccessor, options: FindEntityByIdOptions): Promise<any> {
355
- const { id, properties, keepNonPropertyFields, routeContext } = options;
360
+ const { id, properties, relations, keepNonPropertyFields, routeContext } = options;
356
361
  return await findEntity(server, dataAccessor, {
357
362
  filters: [
358
363
  {
@@ -362,6 +367,7 @@ async function findById(server: IRpdServer, dataAccessor: IRpdDataAccessor, opti
362
367
  },
363
368
  ],
364
369
  properties,
370
+ relations,
365
371
  keepNonPropertyFields,
366
372
  routeContext,
367
373
  });
package/src/index.ts CHANGED
@@ -31,6 +31,12 @@ export { default as AuthPlugin } from "./plugins/auth/AuthPlugin";
31
31
 
32
32
  export { default as FileManagePlugin } from "./plugins/fileManage/FileManagePlugin";
33
33
 
34
+ export { default as MailPlugin } from "./plugins/mail/MailPlugin";
35
+ export * from "./plugins/mail/MailPluginTypes";
36
+
37
+ export { default as NotificationPlugin } from "./plugins/notification/NotificationPlugin";
38
+ export * from "./plugins/notification/NotificationPluginTypes";
39
+
34
40
  export { default as ServerOperationPlugin } from "./plugins/serverOperation/ServerOperationPlugin";
35
41
  export * from "./plugins/serverOperation/ServerOperationPluginTypes";
36
42
 
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Mail plugin
3
+ */
4
+
5
+ import { RpdApplicationConfig } from "~/types";
6
+ import {
7
+ IRpdServer,
8
+ RapidPlugin,
9
+ RpdConfigurationItemOptions,
10
+ RpdServerPluginConfigurableTargetOptions,
11
+ RpdServerPluginExtendingAbilities,
12
+ } from "~/core/server";
13
+
14
+ import pluginActionHandlers from "./actionHandlers";
15
+ import pluginModels from "./models";
16
+ import pluginRoutes from "./routes";
17
+ import MailService from "./MailService";
18
+ import { MailPluginConfig } from "./MailPluginTypes";
19
+
20
+ class MailPlugin implements RapidPlugin {
21
+ #mailService!: MailService;
22
+ #config: MailPluginConfig;
23
+
24
+ constructor(config: MailPluginConfig) {
25
+ this.#config = config;
26
+ }
27
+
28
+ get mailService() {
29
+ return this.#mailService;
30
+ }
31
+
32
+ get code(): string {
33
+ return "mail";
34
+ }
35
+
36
+ get description(): string {
37
+ return null;
38
+ }
39
+
40
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[] {
41
+ return [];
42
+ }
43
+
44
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[] {
45
+ return [];
46
+ }
47
+
48
+ get configurations(): RpdConfigurationItemOptions[] {
49
+ return [];
50
+ }
51
+
52
+ async registerActionHandlers(server: IRpdServer): Promise<any> {
53
+ for (const actionHandler of pluginActionHandlers) {
54
+ server.registerActionHandler(this, actionHandler);
55
+ }
56
+ }
57
+
58
+ async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
59
+ server.appendApplicationConfig({ models: pluginModels });
60
+ }
61
+
62
+ async configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
63
+ this.#mailService = new MailService(server, this.#config.smtpServer);
64
+ server.registerService("mailService", this.#mailService);
65
+ }
66
+
67
+ async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
68
+ server.appendApplicationConfig({ routes: pluginRoutes });
69
+ }
70
+
71
+ async onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig) {}
72
+ }
73
+
74
+ export default MailPlugin;
@@ -0,0 +1,27 @@
1
+ export type MailPluginConfig = {
2
+ smtpServer: RpdMailSmtpServer;
3
+ };
4
+
5
+ export type RpdMailSmtpServer = {
6
+ host: string;
7
+ port: number;
8
+ secure: boolean; // true for port 465, false for other ports (normally 587).
9
+ username: string;
10
+ password: string;
11
+ };
12
+
13
+ export type RpdMail = {
14
+ from?: string;
15
+ to?: string;
16
+ subject?: string;
17
+ text?: string;
18
+ html?: string;
19
+ };
20
+
21
+ export type SendMailOptions = {
22
+ from?: string;
23
+ to?: string;
24
+ subject?: string;
25
+ text?: string;
26
+ html?: string;
27
+ };
@@ -0,0 +1,38 @@
1
+ import { IRpdServer } from "~/core/server";
2
+ import { RpdMailSmtpServer, SendMailOptions } from "./MailPluginTypes";
3
+ import { RouteContext } from "~/core/routeContext";
4
+ import nodemailer from "nodemailer";
5
+
6
+ export default class MailService {
7
+ #server: IRpdServer;
8
+ #smtpServer: RpdMailSmtpServer;
9
+
10
+ constructor(server: IRpdServer, smtpServer: RpdMailSmtpServer) {
11
+ this.#server = server;
12
+ this.#smtpServer = smtpServer;
13
+ }
14
+
15
+ async sendMail(routeContext: RouteContext, server: IRpdServer, options: SendMailOptions): Promise<any> {
16
+ const smtpServer = this.#smtpServer;
17
+
18
+ const transporter = nodemailer.createTransport({
19
+ host: smtpServer.host,
20
+ port: smtpServer.port,
21
+ secure: smtpServer.secure, // true for port 465, false for other ports
22
+ auth: {
23
+ user: smtpServer.username,
24
+ pass: smtpServer.password,
25
+ },
26
+ });
27
+
28
+ const info = await transporter.sendMail({
29
+ from: options.from,
30
+ to: options.to,
31
+ subject: options.subject,
32
+ text: options.text,
33
+ html: options.html,
34
+ });
35
+
36
+ return info;
37
+ }
38
+ }
@@ -0,0 +1,3 @@
1
+ import { IPluginActionHandler } from "~/core/actionHandler";
2
+
3
+ export default [] satisfies IPluginActionHandler[];
@@ -0,0 +1 @@
1
+ export default [];
@@ -0,0 +1 @@
1
+ export default [];
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Notification plugin
3
+ */
4
+
5
+ import { RpdApplicationConfig } from "~/types";
6
+ import {
7
+ IRpdServer,
8
+ RapidPlugin,
9
+ RpdConfigurationItemOptions,
10
+ RpdServerPluginConfigurableTargetOptions,
11
+ RpdServerPluginExtendingAbilities,
12
+ } from "~/core/server";
13
+
14
+ import pluginActionHandlers from "./actionHandlers";
15
+ import pluginModels from "./models";
16
+ import pluginRoutes from "./routes";
17
+ import NotificationService from "./NotificationService";
18
+
19
+ class SequencePlugin implements RapidPlugin {
20
+ #notificationService!: NotificationService;
21
+
22
+ get notificationService() {
23
+ return this.#notificationService;
24
+ }
25
+
26
+ get code(): string {
27
+ return "notification";
28
+ }
29
+
30
+ get description(): string {
31
+ return null;
32
+ }
33
+
34
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[] {
35
+ return [];
36
+ }
37
+
38
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[] {
39
+ return [];
40
+ }
41
+
42
+ get configurations(): RpdConfigurationItemOptions[] {
43
+ return [];
44
+ }
45
+
46
+ async registerActionHandlers(server: IRpdServer): Promise<any> {
47
+ for (const actionHandler of pluginActionHandlers) {
48
+ server.registerActionHandler(this, actionHandler);
49
+ }
50
+ }
51
+
52
+ async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
53
+ server.appendApplicationConfig({ models: pluginModels });
54
+ }
55
+
56
+ async configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
57
+ this.#notificationService = new NotificationService(server);
58
+ server.registerService("notificationService", this.#notificationService);
59
+ }
60
+
61
+ async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
62
+ server.appendApplicationConfig({ routes: pluginRoutes });
63
+ }
64
+
65
+ async onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig) {}
66
+ }
67
+
68
+ export default SequencePlugin;
@@ -0,0 +1,13 @@
1
+ export type RpdNotification = {
2
+ id?: number;
3
+ title: string;
4
+ content?: string;
5
+ details?: any;
6
+ };
7
+
8
+ export type SendNotificationOptions = {
9
+ userId: number;
10
+ title: string;
11
+ content?: string;
12
+ details?: any;
13
+ };
@@ -0,0 +1,25 @@
1
+ import { IRpdServer } from "~/core/server";
2
+ import { SendNotificationOptions, RpdNotification } from "./NotificationPluginTypes";
3
+ import { RouteContext } from "~/core/routeContext";
4
+
5
+ export default class NotificationService {
6
+ #server: IRpdServer;
7
+
8
+ constructor(server: IRpdServer) {
9
+ this.#server = server;
10
+ }
11
+
12
+ async sendNotification(routeContext: RouteContext, server: IRpdServer, options: SendNotificationOptions): Promise<RpdNotification> {
13
+ const notificationManager = server.getEntityManager("notification");
14
+
15
+ return await notificationManager.createEntity({
16
+ routeContext,
17
+ entity: {
18
+ title: options.title,
19
+ content: options.content,
20
+ details: options.details,
21
+ user: options.userId,
22
+ },
23
+ });
24
+ }
25
+ }
@@ -0,0 +1,3 @@
1
+ import { IPluginActionHandler } from "~/core/actionHandler";
2
+
3
+ export default [] satisfies IPluginActionHandler[];
@@ -0,0 +1,57 @@
1
+ import { RpdDataModel } from "~/types";
2
+
3
+ export default {
4
+ maintainedBy: "notification",
5
+ namespace: "svc",
6
+ name: "notification",
7
+ singularCode: "notification",
8
+ pluralCode: "notifications",
9
+ schema: "public",
10
+ tableName: "notifications",
11
+ properties: [
12
+ {
13
+ name: "id",
14
+ code: "id",
15
+ columnName: "id",
16
+ type: "integer",
17
+ required: true,
18
+ autoIncrement: true,
19
+ },
20
+ {
21
+ name: "标题",
22
+ code: "title",
23
+ columnName: "title",
24
+ type: "text",
25
+ required: true,
26
+ },
27
+ {
28
+ name: "内容",
29
+ code: "content",
30
+ columnName: "content",
31
+ type: "text",
32
+ required: false,
33
+ },
34
+ {
35
+ name: "已读",
36
+ code: "read",
37
+ columnName: "read",
38
+ type: "boolean",
39
+ required: false,
40
+ defaultValue: "false",
41
+ },
42
+ {
43
+ name: "详细信息",
44
+ code: "details",
45
+ columnName: "details",
46
+ description: '{"url": "", "actions": [{"text": "", "url": ""}]}',
47
+ type: "json",
48
+ },
49
+ {
50
+ name: "用户",
51
+ code: "user",
52
+ type: "relation",
53
+ targetSingularCode: "oc_user",
54
+ targetIdColumnName: "user_id",
55
+ },
56
+ ],
57
+ } as RpdDataModel;
@@ -0,0 +1,3 @@
1
+ import Notification from "./Notification";
2
+
3
+ export default [Notification];
@@ -0,0 +1 @@
1
+ export default [];