@ruiapp/rapid-core 0.1.30 → 0.1.32

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 (62) hide show
  1. package/dist/core/pluginManager.d.ts +3 -1
  2. package/dist/core/server.d.ts +4 -1
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.js +563 -134
  5. package/dist/plugins/cronJob/CronJobPlugin.d.ts +27 -0
  6. package/dist/plugins/cronJob/CronJobPluginTypes.d.ts +39 -0
  7. package/dist/plugins/cronJob/actionHandlers/index.d.ts +3 -0
  8. package/dist/plugins/cronJob/actionHandlers/runCronJob.d.ts +5 -0
  9. package/dist/plugins/cronJob/routes/index.d.ts +12 -0
  10. package/dist/plugins/cronJob/routes/runCronJob.d.ts +12 -0
  11. package/dist/plugins/sequence/SequencePluginTypes.d.ts +45 -3
  12. package/dist/plugins/sequence/SequenceService.d.ts +1 -1
  13. package/dist/plugins/sequence/segments/autoIncrement.d.ts +1 -1
  14. package/dist/plugins/sequence/segments/dayOfMonth.d.ts +1 -1
  15. package/dist/plugins/sequence/segments/literal.d.ts +1 -1
  16. package/dist/plugins/sequence/segments/month.d.ts +1 -1
  17. package/dist/plugins/sequence/segments/parameter.d.ts +1 -1
  18. package/dist/plugins/sequence/segments/year.d.ts +1 -1
  19. package/dist/plugins/stateMachine/StateMachinePlugin.d.ts +36 -0
  20. package/dist/plugins/stateMachine/StateMachinePluginTypes.d.ts +24 -0
  21. package/dist/plugins/stateMachine/StateMachineService.d.ts +3 -0
  22. package/dist/plugins/stateMachine/actionHandlers/index.d.ts +3 -0
  23. package/dist/plugins/stateMachine/actionHandlers/sendStateMachineEvent.d.ts +5 -0
  24. package/dist/plugins/stateMachine/models/StateMachine.d.ts +3 -0
  25. package/dist/plugins/stateMachine/models/index.d.ts +2 -0
  26. package/dist/plugins/stateMachine/routes/index.d.ts +12 -0
  27. package/dist/plugins/stateMachine/routes/sendStateMachineEvent.d.ts +12 -0
  28. package/dist/server.d.ts +2 -1
  29. package/dist/types.d.ts +2 -43
  30. package/package.json +4 -2
  31. package/src/core/pluginManager.ts +14 -1
  32. package/src/core/server.ts +4 -1
  33. package/src/dataAccess/entityManager.ts +6 -3
  34. package/src/index.ts +15 -0
  35. package/src/plugins/cronJob/CronJobPlugin.ts +113 -0
  36. package/src/plugins/cronJob/CronJobPluginTypes.ts +49 -0
  37. package/src/plugins/cronJob/actionHandlers/index.ts +6 -0
  38. package/src/plugins/cronJob/actionHandlers/runCronJob.ts +34 -0
  39. package/src/plugins/cronJob/routes/index.ts +5 -0
  40. package/src/plugins/cronJob/routes/runCronJob.ts +15 -0
  41. package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +7 -1
  42. package/src/plugins/sequence/SequencePlugin.ts +10 -9
  43. package/src/plugins/sequence/SequencePluginTypes.ts +65 -5
  44. package/src/plugins/sequence/SequenceService.ts +1 -2
  45. package/src/plugins/sequence/actionHandlers/generateSn.ts +0 -1
  46. package/src/plugins/sequence/segments/autoIncrement.ts +1 -1
  47. package/src/plugins/sequence/segments/dayOfMonth.ts +1 -1
  48. package/src/plugins/sequence/segments/literal.ts +1 -1
  49. package/src/plugins/sequence/segments/month.ts +1 -1
  50. package/src/plugins/sequence/segments/parameter.ts +1 -1
  51. package/src/plugins/sequence/segments/year.ts +1 -1
  52. package/src/plugins/stateMachine/StateMachinePlugin.ts +175 -0
  53. package/src/plugins/stateMachine/StateMachinePluginTypes.ts +30 -0
  54. package/src/plugins/stateMachine/StateMachineService.ts +19 -0
  55. package/src/plugins/stateMachine/actionHandlers/index.ts +6 -0
  56. package/src/plugins/stateMachine/actionHandlers/sendStateMachineEvent.ts +55 -0
  57. package/src/plugins/stateMachine/models/StateMachine.ts +42 -0
  58. package/src/plugins/stateMachine/models/index.ts +5 -0
  59. package/src/plugins/stateMachine/routes/index.ts +5 -0
  60. package/src/plugins/stateMachine/routes/sendStateMachineEvent.ts +15 -0
  61. package/src/server.ts +5 -0
  62. package/src/types.ts +2 -62
@@ -0,0 +1,27 @@
1
+ import type { RpdApplicationConfig } from "../../types";
2
+ import { CronJobConfiguration, CronJobPluginInitOptions } from "./CronJobPluginTypes";
3
+ import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
4
+ declare class CronJobPlugin implements RapidPlugin {
5
+ #private;
6
+ constructor(options: CronJobPluginInitOptions);
7
+ get code(): string;
8
+ get description(): string;
9
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[];
10
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[];
11
+ get configurations(): RpdConfigurationItemOptions[];
12
+ initPlugin(server: IRpdServer): Promise<any>;
13
+ registerMiddlewares(server: IRpdServer): Promise<any>;
14
+ registerActionHandlers(server: IRpdServer): Promise<any>;
15
+ registerEventHandlers(server: IRpdServer): Promise<any>;
16
+ registerMessageHandlers(server: IRpdServer): Promise<any>;
17
+ registerTaskProcessors(server: IRpdServer): Promise<any>;
18
+ onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
19
+ configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
20
+ configureModelProperties(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
21
+ configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
22
+ onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
23
+ onApplicationReady(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
24
+ getJobConfigurationByCode(code: string): CronJobConfiguration;
25
+ executeJob(server: IRpdServer, job: CronJobConfiguration): Promise<void>;
26
+ }
27
+ export default CronJobPlugin;
@@ -0,0 +1,39 @@
1
+ import { ActionHandlerContext } from "../../core/actionHandler";
2
+ export interface CronJobConfiguration {
3
+ /**
4
+ * 定时任务编号
5
+ */
6
+ code: string;
7
+ /**
8
+ * 定时任务描述
9
+ */
10
+ description?: string;
11
+ /**
12
+ * crontab 表达式
13
+ */
14
+ cronTime: string;
15
+ /**
16
+ * 任务处理程序编号。当指定处理程序编号时,忽略 handler 配置。
17
+ */
18
+ actionHandlerCode?: string;
19
+ /**
20
+ * 定时任务处理程序
21
+ * @param ctx
22
+ * @param options
23
+ * @returns
24
+ */
25
+ handler?: (ctx: ActionHandlerContext, options: any) => Promise<void>;
26
+ /**
27
+ * 处理定时任务时的设置选项
28
+ */
29
+ handleOptions?: any;
30
+ }
31
+ export interface CronJobPluginInitOptions {
32
+ jobs: CronJobConfiguration[];
33
+ }
34
+ export type RunCronJobActionHandlerOptions = {
35
+ code?: string;
36
+ };
37
+ export type RunCronJobInput = {
38
+ code?: string;
39
+ };
@@ -0,0 +1,3 @@
1
+ import * as runCronJob from "./runCronJob";
2
+ declare const _default: (typeof runCronJob)[];
3
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { ActionHandlerContext } from "../../../core/actionHandler";
2
+ import { RunCronJobActionHandlerOptions } from "../CronJobPluginTypes";
3
+ import type CronJobPlugin from "../CronJobPlugin";
4
+ export declare const code = "runCronJob";
5
+ export declare function handler(plugin: CronJobPlugin, ctx: ActionHandlerContext, options: RunCronJobActionHandlerOptions): Promise<void>;
@@ -0,0 +1,12 @@
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "POST";
7
+ endpoint: string;
8
+ actions: {
9
+ code: string;
10
+ }[];
11
+ }[];
12
+ export default _default;
@@ -0,0 +1,12 @@
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "POST";
7
+ endpoint: string;
8
+ actions: {
9
+ code: string;
10
+ }[];
11
+ };
12
+ export default _default;
@@ -1,8 +1,50 @@
1
- import { SequenceSegmentConfig } from "../../types";
2
1
  export type PropertySequenceConfig = {
3
- autoGenerate: boolean;
4
- ruleConfig: SequenceRuleConfig;
2
+ enabled: boolean;
3
+ config: SequenceRuleConfig;
5
4
  };
6
5
  export type SequenceRuleConfig = {
7
6
  segments: SequenceSegmentConfig[];
8
7
  };
8
+ export type SequenceSegmentConfig = SequenceLiteralSegmentConfig | SequenceYearSegmentConfig | SequenceMonthSegmentConfig | SequenceDayOfMonthSegmentConfig | SequenceDayOfWeekSegmentConfig | SequenceDayOfYearSegmentConfig | SequenceParameterSegmentConfig | SequenceAutoIncrementSegmentConfig;
9
+ export type SequenceLiteralSegmentConfig = {
10
+ type: "literal";
11
+ content: string;
12
+ };
13
+ export type SequenceYearSegmentConfig = {
14
+ type: "year";
15
+ padding?: string;
16
+ length?: number;
17
+ };
18
+ export type SequenceMonthSegmentConfig = {
19
+ type: "month";
20
+ padding?: string;
21
+ length?: number;
22
+ };
23
+ export type SequenceDayOfMonthSegmentConfig = {
24
+ type: "dayOfMonth";
25
+ padding?: string;
26
+ length?: number;
27
+ };
28
+ export type SequenceDayOfWeekSegmentConfig = {
29
+ type: "dayOfWeek";
30
+ padding?: string;
31
+ length?: number;
32
+ };
33
+ export type SequenceDayOfYearSegmentConfig = {
34
+ type: "dayOfYear";
35
+ padding?: string;
36
+ length?: number;
37
+ };
38
+ export type SequenceParameterSegmentConfig = {
39
+ type: "parameter";
40
+ parameterName: string;
41
+ padding?: string;
42
+ length?: number;
43
+ };
44
+ export type SequenceAutoIncrementSegmentConfig = {
45
+ type: "autoIncrement";
46
+ scope?: string;
47
+ period?: "forever" | "day" | "month" | "year";
48
+ padding?: string;
49
+ length?: number;
50
+ };
@@ -1,5 +1,5 @@
1
1
  import { IRpdServer } from "../../core/server";
2
- import { SequenceSegmentConfig } from "../../types";
2
+ import { SequenceSegmentConfig } from "./SequencePluginTypes";
3
3
  export interface GenerateSequenceNumbersInput {
4
4
  ruleCode: string;
5
5
  parameters: Record<string, string>;
@@ -1,5 +1,5 @@
1
- import { SequenceAutoIncrementSegmentConfig } from "../../../types";
2
1
  import { GenerateSequenceNumbersInput } from "../SequenceService";
3
2
  import { IRpdServer } from "../../../core/server";
3
+ import { SequenceAutoIncrementSegmentConfig } from "../SequencePluginTypes";
4
4
  export declare const segmentType = "autoIncrement";
5
5
  export declare function resolveSegmentValue(server: IRpdServer, ruleCode: string, config: SequenceAutoIncrementSegmentConfig, input: GenerateSequenceNumbersInput): Promise<string>;
@@ -1,4 +1,4 @@
1
- import { SequenceDayOfMonthSegmentConfig } from "../../../types";
1
+ import { SequenceDayOfMonthSegmentConfig } from "../SequencePluginTypes";
2
2
  import { GenerateSequenceNumbersInput } from "../SequenceService";
3
3
  import { IRpdServer } from "../../../core/server";
4
4
  export declare const segmentType = "dayOfMonth";
@@ -1,4 +1,4 @@
1
- import { SequenceLiteralSegmentConfig } from "../../../types";
1
+ import { SequenceLiteralSegmentConfig } from "../SequencePluginTypes";
2
2
  import { GenerateSequenceNumbersInput } from "../SequenceService";
3
3
  import { IRpdServer } from "../../../core/server";
4
4
  export declare const segmentType = "literal";
@@ -1,4 +1,4 @@
1
- import { SequenceMonthSegmentConfig } from "../../../types";
1
+ import { SequenceMonthSegmentConfig } from "../SequencePluginTypes";
2
2
  import { GenerateSequenceNumbersInput } from "../SequenceService";
3
3
  import { IRpdServer } from "../../../core/server";
4
4
  export declare const segmentType = "month";
@@ -1,4 +1,4 @@
1
- import { SequenceParameterSegmentConfig } from "../../../types";
1
+ import { SequenceParameterSegmentConfig } from "../SequencePluginTypes";
2
2
  import { GenerateSequenceNumbersInput } from "../SequenceService";
3
3
  import { IRpdServer } from "../../../core/server";
4
4
  export declare const segmentType = "parameter";
@@ -1,4 +1,4 @@
1
- import { SequenceYearSegmentConfig } from "../../../types";
1
+ import { SequenceYearSegmentConfig } from "../SequencePluginTypes";
2
2
  import { GenerateSequenceNumbersInput } from "../SequenceService";
3
3
  import { IRpdServer } from "../../../core/server";
4
4
  export declare const segmentType = "year";
@@ -0,0 +1,36 @@
1
+ /**
2
+ * State machine plugin
3
+ */
4
+ import { CreateEntityOptions, RpdApplicationConfig, RpdDataModel, UpdateEntityByIdOptions } from "../../types";
5
+ import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
6
+ declare class StateMachinePlugin implements RapidPlugin {
7
+ get code(): string;
8
+ get description(): string;
9
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[];
10
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[];
11
+ get configurations(): RpdConfigurationItemOptions[];
12
+ registerActionHandlers(server: IRpdServer): Promise<any>;
13
+ configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
14
+ configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
15
+ onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<void>;
16
+ /**
17
+ * 创建实体前的处理。
18
+ * 当属性启用了状态机管理,如创建实体时没有指定该属性的状态值,则应将该属性设置为 stateMachine.config.initial 。
19
+ * @param server
20
+ * @param model
21
+ * @param options
22
+ */
23
+ beforeCreateEntity(server: IRpdServer, model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
24
+ /**
25
+ * 更新实体前的处理。
26
+ * 1. 对所有启用了状态机管理,且 transferControl 为 true 的属性,应禁止直接更新这些属性
27
+ * 2. 当更新实体时指定了operation,则查找启用了状态机管理的属性。
28
+ * 如果一个模型中存在多个属性启用了状态机管理,则以 options.stateProperty 中指定的为准。
29
+ * 对于该状态属性应用 options.operation,使其转换到下一状态。
30
+ * @param server
31
+ * @param model
32
+ * @param options
33
+ */
34
+ beforeUpdateEntity(server: IRpdServer, model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
35
+ }
36
+ export default StateMachinePlugin;
@@ -0,0 +1,24 @@
1
+ import { MachineConfig } from "xstate";
2
+ export type PropertyStateMachineConfig = {
3
+ enabled: boolean;
4
+ config: MachineConfig<any, any>;
5
+ transferControl?: boolean;
6
+ };
7
+ export type SendStateMachineEventOptions = {
8
+ code: string;
9
+ };
10
+ export type SendStateMachineEventInput = {
11
+ code?: string;
12
+ context: any;
13
+ currentState: string;
14
+ event: StateMachineEvent;
15
+ };
16
+ export type StateMachineEvent = {
17
+ type: string;
18
+ };
19
+ export type GetStateMachineNextSnapshotOptions = {
20
+ machineConfig: MachineConfig<any, any>;
21
+ context: any;
22
+ currentState: string;
23
+ event: StateMachineEvent;
24
+ };
@@ -0,0 +1,3 @@
1
+ import { IRpdServer } from "../../core/server";
2
+ import { GetStateMachineNextSnapshotOptions } from "./StateMachinePluginTypes";
3
+ export declare function getStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions): Promise<import("xstate").MachineSnapshot<any, import("xstate").AnyEventObject, Record<string, import("xstate").AnyActorRef>, import("xstate").StateValue, string, unknown, import("xstate").MetaObject, never>>;
@@ -0,0 +1,3 @@
1
+ import * as sendStateMachineEvent from "./sendStateMachineEvent";
2
+ declare const _default: (typeof sendStateMachineEvent)[];
3
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { ActionHandlerContext } from "../../../core/actionHandler";
2
+ import { RapidPlugin } from "../../../core/server";
3
+ import { SendStateMachineEventOptions } from "../StateMachinePluginTypes";
4
+ export declare const code = "sendStateMachineEvent";
5
+ export declare function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: SendStateMachineEventOptions): Promise<void>;
@@ -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,12 @@
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "POST";
7
+ endpoint: string;
8
+ actions: {
9
+ code: string;
10
+ }[];
11
+ }[];
12
+ export default _default;
@@ -0,0 +1,12 @@
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "POST";
7
+ endpoint: string;
8
+ actions: {
9
+ code: string;
10
+ }[];
11
+ };
12
+ export default _default;
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { GetDataAccessorOptions, GetModelOptions, IDatabaseAccessor, IDatabaseConfig, IQueryBuilder, IRpdDataAccessor, RpdApplicationConfig, RpdDataModel, RpdServerEventTypes, RapidServerConfig, RpdDataModelProperty, CreateEntityOptions } from "./types";
1
+ import { GetDataAccessorOptions, GetModelOptions, IDatabaseAccessor, IDatabaseConfig, IQueryBuilder, IRpdDataAccessor, RpdApplicationConfig, RpdDataModel, RpdServerEventTypes, RapidServerConfig, RpdDataModelProperty, CreateEntityOptions, UpdateEntityByIdOptions } from "./types";
2
2
  import { ActionHandler, ActionHandlerContext, IPluginActionHandler } from "./core/actionHandler";
3
3
  import { IRpdServer, RapidPlugin } from "./core/server";
4
4
  import { Next } from "./core/routeContext";
@@ -42,4 +42,5 @@ export declare class RapidServer implements IRpdServer {
42
42
  handleRequest(request: Request, next: Next): Promise<Response>;
43
43
  beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
44
44
  beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
45
+ beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
45
46
  }
package/dist/types.d.ts CHANGED
@@ -335,6 +335,8 @@ export interface UpdateEntityOptions {
335
335
  export interface UpdateEntityByIdOptions {
336
336
  id: any;
337
337
  entityToSave: any;
338
+ operation?: any;
339
+ stateProperty?: string;
338
340
  }
339
341
  export interface DeleteEntityOptions {
340
342
  filters?: EntityFilterOptions[];
@@ -355,46 +357,3 @@ export interface RemoveEntityRelationsOptions {
355
357
  [k: string]: any;
356
358
  }[];
357
359
  }
358
- export type SequenceSegmentConfig = SequenceLiteralSegmentConfig | SequenceYearSegmentConfig | SequenceMonthSegmentConfig | SequenceDayOfMonthSegmentConfig | SequenceDayOfWeekSegmentConfig | SequenceDayOfYearSegmentConfig | SequenceParameterSegmentConfig | SequenceAutoIncrementSegmentConfig;
359
- export type SequenceLiteralSegmentConfig = {
360
- type: "literal";
361
- content: string;
362
- };
363
- export type SequenceYearSegmentConfig = {
364
- type: "year";
365
- padding?: string;
366
- length?: number;
367
- };
368
- export type SequenceMonthSegmentConfig = {
369
- type: "month";
370
- padding?: string;
371
- length?: number;
372
- };
373
- export type SequenceDayOfMonthSegmentConfig = {
374
- type: "dayOfMonth";
375
- padding?: string;
376
- length?: number;
377
- };
378
- export type SequenceDayOfWeekSegmentConfig = {
379
- type: "dayOfWeek";
380
- padding?: string;
381
- length?: number;
382
- };
383
- export type SequenceDayOfYearSegmentConfig = {
384
- type: "dayOfYear";
385
- padding?: string;
386
- length?: number;
387
- };
388
- export type SequenceParameterSegmentConfig = {
389
- type: "parameter";
390
- parameterName: string;
391
- padding?: string;
392
- length?: number;
393
- };
394
- export type SequenceAutoIncrementSegmentConfig = {
395
- type: "autoIncrement";
396
- scope: string;
397
- period: "forever" | "day" | "month" | "year";
398
- padding?: string;
399
- length?: number;
400
- };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,12 +19,14 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "bcrypt": "^5.1.1",
22
+ "cron": "^3.1.7",
22
23
  "dayjs": "^1.11.7",
23
24
  "jsonwebtoken": "^9.0.2",
24
25
  "koa-tree-router": "^0.12.1",
25
26
  "lodash": "^4.17.21",
26
27
  "qs": "^6.11.0",
27
- "uuid": "^9.0.1"
28
+ "uuid": "^9.0.1",
29
+ "xstate": "^5.13.0"
28
30
  },
29
31
  "peerDependencies": {
30
32
  "winston": "^3.11.0"
@@ -1,4 +1,4 @@
1
- import { CreateEntityOptions, RpdApplicationConfig, RpdDataModel } from "~/types";
1
+ import { CreateEntityOptions, RpdApplicationConfig, RpdDataModel, UpdateEntityByIdOptions } from "~/types";
2
2
  import { IRpdServer, RapidPlugin } from "./server";
3
3
  import { RouteContext } from "./routeContext";
4
4
  import { ActionHandlerContext } from "./actionHandler";
@@ -171,6 +171,19 @@ class PluginManager {
171
171
  }
172
172
  }
173
173
  }
174
+
175
+ /** 在更新实体前调用。 */
176
+ async beforeUpdateEntity(
177
+ model: RpdDataModel,
178
+ options: UpdateEntityByIdOptions,
179
+ currentEntity: any,
180
+ ) {
181
+ for (const plugin of this.#plugins) {
182
+ if (plugin.beforeUpdateEntity) {
183
+ await plugin.beforeUpdateEntity(this.#server, model, options, currentEntity);
184
+ }
185
+ }
186
+ }
174
187
  }
175
188
 
176
189
  export default PluginManager;
@@ -1,4 +1,4 @@
1
- import { CreateEntityOptions, GetDataAccessorOptions, GetModelOptions, IDatabaseConfig, IQueryBuilder, IRpdDataAccessor, RapidServerConfig, RpdApplicationConfig, RpdDataModel, RpdDataModelProperty, RpdServerEventTypes } from "~/types";
1
+ import { CreateEntityOptions, GetDataAccessorOptions, GetModelOptions, IDatabaseConfig, IQueryBuilder, IRpdDataAccessor, RapidServerConfig, RpdApplicationConfig, RpdDataModel, RpdDataModelProperty, RpdServerEventTypes, UpdateEntityByIdOptions } from "~/types";
2
2
  import { IPluginActionHandler, ActionHandler, ActionHandlerContext } from "./actionHandler";
3
3
  import { Next, RouteContext } from "./routeContext";
4
4
  import EntityManager from "~/dataAccess/entityManager";
@@ -49,6 +49,7 @@ export interface IRpdServer {
49
49
  handleRequest(request: Request, next: Next): Promise<Response>;
50
50
  beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
51
51
  beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
52
+ beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
52
53
  }
53
54
 
54
55
 
@@ -142,4 +143,6 @@ export interface RapidPlugin {
142
143
  beforeRunRouteActions?: (server: IRpdServer, handlerContext: ActionHandlerContext) => Promise<any>;
143
144
  /** 在创建实体前调用。 */
144
145
  beforeCreateEntity?: (server: IRpdServer, model: RpdDataModel, options: CreateEntityOptions) => Promise<any>;
146
+ /** 在更新实体前调用。 */
147
+ beforeUpdateEntity?: (server: IRpdServer, model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any) => Promise<any>;
145
148
  }
@@ -574,11 +574,15 @@ async function updateEntityById(
574
574
  throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
575
575
  }
576
576
 
577
- const changes = getEntityPartChanges(entity, entityToSave);
578
- if (!changes) {
577
+ let changes = getEntityPartChanges(entity, entityToSave);
578
+ if (!changes && !options.operation) {
579
579
  return entity;
580
580
  }
581
581
 
582
+ options.entityToSave = changes || {};
583
+ await server.beforeUpdateEntity(model, options, entity);
584
+ changes = options.entityToSave;
585
+
582
586
  const oneRelationPropertiesToUpdate: RpdDataModelProperty[] = [];
583
587
  const manyRelationPropertiesToUpdate: RpdDataModelProperty[] = [];
584
588
  keys(changes).forEach((propertyCode) => {
@@ -691,7 +695,6 @@ async function updateEntityById(
691
695
  updatedEntity[property.code] = relatedEntities;
692
696
  }
693
697
 
694
-
695
698
  server.emitEvent(
696
699
  "entity.update",
697
700
  {
package/src/index.ts CHANGED
@@ -15,15 +15,30 @@ export * from "./utilities/jwtUtility";
15
15
  export * as bootstrapApplicationConfig from "./bootstrapApplicationConfig";
16
16
 
17
17
  export { default as MetaManagePlugin } from "./plugins/metaManage/MetaManagePlugin";
18
+
18
19
  export { default as DataManagePlugin } from "./plugins/dataManage/DataManagePlugin";
20
+
19
21
  export { default as RouteManagePlugin } from "./plugins/routeManage/RouteManagePlugin";
22
+
20
23
  export { default as SequencePlugin } from "./plugins/sequence/SequencePlugin";
21
24
  export * from "./plugins/sequence/SequencePluginTypes";
25
+
22
26
  export { default as WebhooksPlugin } from "./plugins/webhooks/WebhooksPlugin";
27
+
23
28
  export { default as AuthPlugin } from "./plugins/auth/AuthPlugin";
29
+
24
30
  export { default as FileManagePlugin } from "./plugins/fileManage/FileManagePlugin";
31
+
25
32
  export { default as ServerOperationPlugin } from "./plugins/serverOperation/ServerOperationPlugin";
26
33
  export * from "./plugins/serverOperation/ServerOperationPluginTypes";
34
+
35
+ export { default as CronJobPlugin } from "./plugins/cronJob/CronJobPlugin";
36
+ export * from "./plugins/cronJob/CronJobPluginTypes";
37
+
38
+ export { default as StateMachinePlugin } from "./plugins/stateMachine/StateMachinePlugin";
39
+ export * from "./plugins/stateMachine/StateMachinePluginTypes";
40
+
27
41
  export { default as EntityWatchPlugin } from "./plugins/entityWatch/EntityWatchPlugin";
28
42
  export * from "./plugins/entityWatch/EntityWatchPluginTypes";
43
+
29
44
  export { default as EntityAccessControlPlugin } from "./plugins/entityAccessControl/EntityAccessControlPlugin";
@@ -0,0 +1,113 @@
1
+ import * as cron from 'cron';
2
+ import type { RpdApplicationConfig } from "~/types";
3
+ import pluginActionHandlers from "./actionHandlers";
4
+ import pluginRoutes from "./routes";
5
+ import { CronJobConfiguration, CronJobPluginInitOptions } from "./CronJobPluginTypes";
6
+ import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "~/core/server";
7
+ import { ActionHandlerContext } from '~/core/actionHandler';
8
+ import { find } from 'lodash';
9
+
10
+ class CronJobPlugin implements RapidPlugin {
11
+ #jobs: CronJobConfiguration[];
12
+
13
+ constructor(options: CronJobPluginInitOptions) {
14
+ this.#jobs = options.jobs || [];
15
+ }
16
+
17
+ get code(): string {
18
+ return "cronJob";
19
+ }
20
+
21
+ get description(): string {
22
+ return "";
23
+ }
24
+
25
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[] {
26
+ return [];
27
+ }
28
+
29
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[] {
30
+ return [];
31
+ }
32
+
33
+ get configurations(): RpdConfigurationItemOptions[] {
34
+ return [];
35
+ }
36
+
37
+ async initPlugin(server: IRpdServer): Promise<any> {
38
+ }
39
+
40
+ async registerMiddlewares(server: IRpdServer): Promise<any> {
41
+ }
42
+
43
+ async registerActionHandlers(server: IRpdServer): Promise<any> {
44
+ for (const actionHandler of pluginActionHandlers) {
45
+ server.registerActionHandler(this, actionHandler);
46
+ }
47
+ }
48
+
49
+ async registerEventHandlers(server: IRpdServer): Promise<any> {
50
+ }
51
+
52
+ async registerMessageHandlers(server: IRpdServer): Promise<any> {
53
+ }
54
+
55
+ async registerTaskProcessors(server: IRpdServer): Promise<any> {
56
+ }
57
+
58
+ async onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
59
+ }
60
+
61
+ async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
62
+ }
63
+
64
+ async configureModelProperties(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
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): Promise<any> {
72
+ }
73
+
74
+ async onApplicationReady(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
75
+ for (const job of this.#jobs) {
76
+ const jobInstance = cron.CronJob.from({
77
+ cronTime: job.cronTime,
78
+ onTick: async () => {
79
+ await this.executeJob(server, job);
80
+ },
81
+ });
82
+ }
83
+ }
84
+
85
+ getJobConfigurationByCode(code: string) {
86
+ return find(this.#jobs, (job) => job.code === code);
87
+ }
88
+
89
+ async executeJob(server: IRpdServer, job: CronJobConfiguration) {
90
+ const logger = server.getLogger();
91
+ try {
92
+ let handlerContext: ActionHandlerContext = {
93
+ logger,
94
+ routerContext: null,
95
+ next: null,
96
+ server,
97
+ applicationConfig: null,
98
+ input: null,
99
+ };
100
+
101
+ if (job.actionHandlerCode) {
102
+ const actionHandler = server.getActionHandlerByCode(job.code);
103
+ await actionHandler(handlerContext, job.handleOptions);
104
+ } else {
105
+ await job.handler(handlerContext, job.handleOptions);
106
+ }
107
+ } catch (ex) {
108
+ logger.error("Cron job execution error: " + ex.message);
109
+ }
110
+ }
111
+ }
112
+
113
+ export default CronJobPlugin;