@ruiapp/rapid-core 0.1.38 → 0.1.40

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.
@@ -24,6 +24,8 @@ declare class PluginManager {
24
24
  configureModels(applicationConfig: RpdApplicationConfig): Promise<void>;
25
25
  /** 配置模型属性 */
26
26
  configureModelProperties(applicationConfig: RpdApplicationConfig): Promise<void>;
27
+ /** 配置服务 */
28
+ configureServices(applicationConfig: RpdApplicationConfig): Promise<void>;
27
29
  /** 配置路由 */
28
30
  configureRoutes(applicationConfig: RpdApplicationConfig): Promise<void>;
29
31
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
@@ -18,6 +18,8 @@ export interface IRpdServer {
18
18
  getActionHandlerByCode(code: string): ActionHandler | undefined;
19
19
  getDataAccessor<T = any>(options: GetDataAccessorOptions): IRpdDataAccessor<T>;
20
20
  getEntityManager<TEntity = any>(singularCode: string): EntityManager<TEntity>;
21
+ registerService(name: string, service: any): any;
22
+ getService<TService>(name: string): TService;
21
23
  getApplicationConfig(): RpdApplicationConfig;
22
24
  appendApplicationConfig(config: Partial<RpdApplicationConfig>): any;
23
25
  appendModelProperties(modelSingularCode: string, properties: RpdDataModelProperty[]): any;
@@ -86,6 +88,8 @@ export interface RapidPlugin {
86
88
  configureModels?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
87
89
  /** 配置模型属性 */
88
90
  configureModelProperties?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
91
+ /** 配置服务 */
92
+ configureServices?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
89
93
  /** 配置路由 */
90
94
  configureRoutes?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
91
95
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
package/dist/index.js CHANGED
@@ -530,6 +530,14 @@ class PluginManager {
530
530
  }
531
531
  }
532
532
  }
533
+ /** 配置服务 */
534
+ async configureServices(applicationConfig) {
535
+ for (const plugin of this.#plugins) {
536
+ if (plugin.configureServices) {
537
+ await plugin.configureServices(this.#server, applicationConfig);
538
+ }
539
+ }
540
+ }
533
541
  /** 配置路由 */
534
542
  async configureRoutes(applicationConfig) {
535
543
  for (const plugin of this.#plugins) {
@@ -2455,6 +2463,7 @@ class RapidServer {
2455
2463
  #databaseAccessor;
2456
2464
  #cachedDataAccessors;
2457
2465
  #cachedEntityManager;
2466
+ #services;
2458
2467
  queryBuilder;
2459
2468
  config;
2460
2469
  databaseConfig;
@@ -2476,6 +2485,7 @@ class RapidServer {
2476
2485
  this.#databaseAccessor = options.databaseAccessor;
2477
2486
  this.#cachedDataAccessors = new Map();
2478
2487
  this.#cachedEntityManager = new Map();
2488
+ this.#services = new Map();
2479
2489
  this.queryBuilder = new QueryBuilder({
2480
2490
  dbDefaultSchema: options.databaseConfig.dbDefaultSchema,
2481
2491
  });
@@ -2601,6 +2611,12 @@ class RapidServer {
2601
2611
  // await this.configureApplication();
2602
2612
  // }
2603
2613
  }
2614
+ registerService(name, service) {
2615
+ this.#services.set(name, service);
2616
+ }
2617
+ getService(name) {
2618
+ return this.#services.get(name);
2619
+ }
2604
2620
  async start() {
2605
2621
  this.#logger.info("Starting rapid server...");
2606
2622
  const pluginManager = this.#pluginManager;
@@ -2621,6 +2637,7 @@ class RapidServer {
2621
2637
  await pluginManager.onLoadingApplication(this.#applicationConfig);
2622
2638
  await pluginManager.configureModels(this.#applicationConfig);
2623
2639
  await pluginManager.configureModelProperties(this.#applicationConfig);
2640
+ await pluginManager.configureServices(this.#applicationConfig);
2624
2641
  await pluginManager.configureRoutes(this.#applicationConfig);
2625
2642
  // TODO: check application configuration.
2626
2643
  await pluginManager.onApplicationLoaded(this.#applicationConfig);
@@ -3655,6 +3672,145 @@ class RouteManager {
3655
3672
  }
3656
3673
  }
3657
3674
 
3675
+ const code$b = "generateSn";
3676
+ async function handler$b(plugin, ctx, options) {
3677
+ const { server, routerContext } = ctx;
3678
+ const input = ctx.input;
3679
+ if (options?.ruleCode) {
3680
+ input.ruleCode = options.ruleCode;
3681
+ }
3682
+ if (!input.ruleCode) {
3683
+ throw new Error(`Rule code is required when generating sequence numbers.`);
3684
+ }
3685
+ const sequenceService = server.getService("sequenceService");
3686
+ const sequences = await sequenceService.generateSn(server, input);
3687
+ ctx.output = {
3688
+ sequences,
3689
+ };
3690
+ }
3691
+
3692
+ var generateSn$1 = /*#__PURE__*/Object.freeze({
3693
+ __proto__: null,
3694
+ code: code$b,
3695
+ handler: handler$b
3696
+ });
3697
+
3698
+ var pluginActionHandlers$4 = [
3699
+ generateSn$1,
3700
+ ];
3701
+
3702
+ var SequenceRule = {
3703
+ maintainedBy: "sequencePlugin",
3704
+ namespace: "svc",
3705
+ name: "sequence_rule",
3706
+ singularCode: "sequence_rule",
3707
+ pluralCode: "sequence_rules",
3708
+ schema: "public",
3709
+ tableName: "sequence_rules",
3710
+ properties: [
3711
+ {
3712
+ name: "id",
3713
+ code: "id",
3714
+ columnName: "id",
3715
+ type: "integer",
3716
+ required: true,
3717
+ autoIncrement: true,
3718
+ },
3719
+ {
3720
+ name: "code",
3721
+ code: "code",
3722
+ columnName: "code",
3723
+ type: "text",
3724
+ required: true,
3725
+ },
3726
+ {
3727
+ name: "description",
3728
+ code: "description",
3729
+ columnName: "description",
3730
+ type: "text",
3731
+ required: false,
3732
+ },
3733
+ {
3734
+ name: "config",
3735
+ code: "config",
3736
+ columnName: "config",
3737
+ type: "json",
3738
+ required: false,
3739
+ },
3740
+ ],
3741
+ };
3742
+
3743
+ var SequenceAutoIncrementRecord = {
3744
+ maintainedBy: "sequencePlugin",
3745
+ namespace: "svc",
3746
+ name: "sequence_auto_increment_record",
3747
+ singularCode: "sequence_auto_increment_record",
3748
+ pluralCode: "sequence_auto_increment_records",
3749
+ schema: "public",
3750
+ tableName: "sequence_auto_increment_records",
3751
+ properties: [
3752
+ {
3753
+ name: "id",
3754
+ code: "id",
3755
+ columnName: "id",
3756
+ type: "integer",
3757
+ required: true,
3758
+ autoIncrement: true,
3759
+ },
3760
+ {
3761
+ name: "ruleCode",
3762
+ code: "ruleCode",
3763
+ columnName: "rule_code",
3764
+ type: "text",
3765
+ required: true,
3766
+ },
3767
+ {
3768
+ name: "scope",
3769
+ code: "scope",
3770
+ columnName: "scope",
3771
+ type: "text",
3772
+ required: false,
3773
+ },
3774
+ {
3775
+ name: "currentValue",
3776
+ code: "currentValue",
3777
+ columnName: "current_value",
3778
+ type: "integer",
3779
+ required: true,
3780
+ },
3781
+ {
3782
+ name: "updatedAt",
3783
+ code: "updatedAt",
3784
+ columnName: "updated_at",
3785
+ type: "datetime",
3786
+ required: true,
3787
+ },
3788
+ ],
3789
+ };
3790
+
3791
+ var pluginModels$2 = [
3792
+ SequenceRule,
3793
+ SequenceAutoIncrementRecord,
3794
+ ];
3795
+
3796
+ var generateSn = {
3797
+ namespace: "svc",
3798
+ name: "svc.generateSn",
3799
+ code: "svc.generateSn",
3800
+ type: "RESTful",
3801
+ method: "POST",
3802
+ endpoint: "/svc/generateSn",
3803
+ actions: [
3804
+ {
3805
+ code: "generateSn",
3806
+ },
3807
+ ],
3808
+ };
3809
+
3810
+ var pluginRoutes$4 = [
3811
+ generateSn,
3812
+ ];
3813
+
3658
3814
  const segmentType$5 = "literal";
3659
3815
  async function resolveSegmentValue$5(server, ruleCode, config, input) {
3660
3816
  return config.content || "";
@@ -3803,190 +3959,62 @@ var segmentResolvers = [
3803
3959
  autoIncrement,
3804
3960
  ];
3805
3961
 
3806
- async function generateSn$2(server, input) {
3807
- const sequenceNumbers = [];
3808
- const { ruleCode, parameters } = input;
3809
- let { amount } = input;
3810
- if (!amount) {
3811
- amount = 1;
3962
+ class SequenceService {
3963
+ #server;
3964
+ constructor(server) {
3965
+ this.#server = server;
3812
3966
  }
3813
- const sequenceRuleDataAccessor = server.getDataAccessor({
3814
- singularCode: "sequence_rule",
3815
- });
3816
- const sequenceRule = await sequenceRuleDataAccessor.findOne({
3817
- filters: [
3818
- {
3819
- operator: "eq",
3820
- field: "code",
3821
- value: ruleCode,
3822
- }
3823
- ]
3824
- });
3825
- if (!sequenceRule) {
3826
- throw new Error(`Failed to generate sequence number. Sequence with code '${sequenceRule.code}' not found.`);
3827
- }
3828
- const sequenceConfig = sequenceRule.config;
3829
- if (!sequenceConfig || !sequenceConfig.segments) {
3830
- throw new Error("Failed to generate sequence number. Sequence not configured.");
3831
- }
3832
- for (let i = 0; i < amount; i++) {
3833
- let sequenceNumber = "";
3834
- for (const segmentConfig of sequenceConfig.segments) {
3835
- const segmentResolver = lodash.find(segmentResolvers, (item) => item.segmentType === segmentConfig.type);
3836
- if (!segmentResolver) {
3837
- // TODO: deal with unkown segment type
3838
- continue;
3967
+ async generateSn(server, input) {
3968
+ const sequenceNumbers = [];
3969
+ const { ruleCode, parameters } = input;
3970
+ let { amount } = input;
3971
+ if (!amount) {
3972
+ amount = 1;
3973
+ }
3974
+ const sequenceRuleDataAccessor = server.getDataAccessor({
3975
+ singularCode: "sequence_rule",
3976
+ });
3977
+ const sequenceRule = await sequenceRuleDataAccessor.findOne({
3978
+ filters: [
3979
+ {
3980
+ operator: "eq",
3981
+ field: "code",
3982
+ value: ruleCode,
3983
+ }
3984
+ ]
3985
+ });
3986
+ if (!sequenceRule) {
3987
+ throw new Error(`Failed to generate sequence number. Sequence with code '${sequenceRule.code}' not found.`);
3988
+ }
3989
+ const sequenceConfig = sequenceRule.config;
3990
+ if (!sequenceConfig || !sequenceConfig.segments) {
3991
+ throw new Error("Failed to generate sequence number. Sequence not configured.");
3992
+ }
3993
+ for (let i = 0; i < amount; i++) {
3994
+ let sequenceNumber = "";
3995
+ for (const segmentConfig of sequenceConfig.segments) {
3996
+ const segmentResolver = lodash.find(segmentResolvers, (item) => item.segmentType === segmentConfig.type);
3997
+ if (!segmentResolver) {
3998
+ // TODO: deal with unkown segment type
3999
+ continue;
4000
+ }
4001
+ const segment = await segmentResolver.resolveSegmentValue(server, ruleCode, segmentConfig, input);
4002
+ sequenceNumber += segment;
3839
4003
  }
3840
- const segment = await segmentResolver.resolveSegmentValue(server, ruleCode, segmentConfig, input);
3841
- sequenceNumber += segment;
4004
+ sequenceNumbers.push(sequenceNumber);
3842
4005
  }
3843
- sequenceNumbers.push(sequenceNumber);
3844
- }
3845
- return sequenceNumbers;
3846
- }
3847
-
3848
- const code$b = "generateSn";
3849
- async function handler$b(plugin, ctx, options) {
3850
- const { server, routerContext } = ctx;
3851
- const input = ctx.input;
3852
- if (options?.ruleCode) {
3853
- input.ruleCode = options.ruleCode;
3854
- }
3855
- if (!input.ruleCode) {
3856
- throw new Error(`Rule code is required when generating sequence numbers.`);
4006
+ return sequenceNumbers;
3857
4007
  }
3858
- const sequences = await generateSn$2(server, input);
3859
- ctx.output = {
3860
- sequences,
3861
- };
3862
4008
  }
3863
4009
 
3864
- var generateSn$1 = /*#__PURE__*/Object.freeze({
3865
- __proto__: null,
3866
- code: code$b,
3867
- handler: handler$b
3868
- });
3869
-
3870
- var pluginActionHandlers$4 = [
3871
- generateSn$1,
3872
- ];
3873
-
3874
- var SequenceRule = {
3875
- maintainedBy: "sequencePlugin",
3876
- namespace: "svc",
3877
- name: "sequence_rule",
3878
- singularCode: "sequence_rule",
3879
- pluralCode: "sequence_rules",
3880
- schema: "public",
3881
- tableName: "sequence_rules",
3882
- properties: [
3883
- {
3884
- name: "id",
3885
- code: "id",
3886
- columnName: "id",
3887
- type: "integer",
3888
- required: true,
3889
- autoIncrement: true,
3890
- },
3891
- {
3892
- name: "code",
3893
- code: "code",
3894
- columnName: "code",
3895
- type: "text",
3896
- required: true,
3897
- },
3898
- {
3899
- name: "description",
3900
- code: "description",
3901
- columnName: "description",
3902
- type: "text",
3903
- required: false,
3904
- },
3905
- {
3906
- name: "config",
3907
- code: "config",
3908
- columnName: "config",
3909
- type: "json",
3910
- required: false,
3911
- },
3912
- ],
3913
- };
3914
-
3915
- var SequenceAutoIncrementRecord = {
3916
- maintainedBy: "sequencePlugin",
3917
- namespace: "svc",
3918
- name: "sequence_auto_increment_record",
3919
- singularCode: "sequence_auto_increment_record",
3920
- pluralCode: "sequence_auto_increment_records",
3921
- schema: "public",
3922
- tableName: "sequence_auto_increment_records",
3923
- properties: [
3924
- {
3925
- name: "id",
3926
- code: "id",
3927
- columnName: "id",
3928
- type: "integer",
3929
- required: true,
3930
- autoIncrement: true,
3931
- },
3932
- {
3933
- name: "ruleCode",
3934
- code: "ruleCode",
3935
- columnName: "rule_code",
3936
- type: "text",
3937
- required: true,
3938
- },
3939
- {
3940
- name: "scope",
3941
- code: "scope",
3942
- columnName: "scope",
3943
- type: "text",
3944
- required: false,
3945
- },
3946
- {
3947
- name: "currentValue",
3948
- code: "currentValue",
3949
- columnName: "current_value",
3950
- type: "integer",
3951
- required: true,
3952
- },
3953
- {
3954
- name: "updatedAt",
3955
- code: "updatedAt",
3956
- columnName: "updated_at",
3957
- type: "datetime",
3958
- required: true,
3959
- },
3960
- ],
3961
- };
3962
-
3963
- var pluginModels$2 = [
3964
- SequenceRule,
3965
- SequenceAutoIncrementRecord,
3966
- ];
3967
-
3968
- var generateSn = {
3969
- namespace: "svc",
3970
- name: "svc.generateSn",
3971
- code: "svc.generateSn",
3972
- type: "RESTful",
3973
- method: "POST",
3974
- endpoint: "/svc/generateSn",
3975
- actions: [
3976
- {
3977
- code: "generateSn",
3978
- },
3979
- ],
3980
- };
3981
-
3982
- var pluginRoutes$4 = [
3983
- generateSn,
3984
- ];
3985
-
3986
4010
  /**
3987
4011
  * Sequence plugin
3988
4012
  */
3989
4013
  class SequencePlugin {
4014
+ #sequenceService;
4015
+ get sequenceService() {
4016
+ return this.#sequenceService;
4017
+ }
3990
4018
  get code() {
3991
4019
  return "sequencePlugin";
3992
4020
  }
@@ -4010,6 +4038,10 @@ class SequencePlugin {
4010
4038
  async configureModels(server, applicationConfig) {
4011
4039
  server.appendApplicationConfig({ models: pluginModels$2 });
4012
4040
  }
4041
+ async configureServices(server, applicationConfig) {
4042
+ this.#sequenceService = new SequenceService(server);
4043
+ server.registerService("sequenceService", this.#sequenceService);
4044
+ }
4013
4045
  async configureRoutes(server, applicationConfig) {
4014
4046
  server.appendApplicationConfig({ routes: pluginRoutes$4 });
4015
4047
  }
@@ -4059,7 +4091,7 @@ class SequencePlugin {
4059
4091
  sequenceConfig.enabled &&
4060
4092
  isNullOrUndefined(propertyValue)) {
4061
4093
  const ruleCode = getSequenceRuleCode(model, property);
4062
- const numbers = await generateSn$2(server, {
4094
+ const numbers = await this.#sequenceService.generateSn(server, {
4063
4095
  ruleCode,
4064
4096
  amount: 1,
4065
4097
  parameters: entity,
@@ -5042,7 +5074,7 @@ class CronJobPlugin {
5042
5074
  }
5043
5075
  }
5044
5076
 
5045
- async function getStateMachineNextSnapshot(server, options) {
5077
+ async function getStateMachineNextSnapshot(options) {
5046
5078
  const { machineConfig, currentState, event } = options;
5047
5079
  machineConfig.initial = currentState;
5048
5080
  const machine = xstate.createMachine(machineConfig);
@@ -5081,7 +5113,7 @@ async function handler(plugin, ctx, options) {
5081
5113
  throw new Error(`State machine with code '${input.code}' was not found.`);
5082
5114
  }
5083
5115
  stateMachine.config.id = input.code;
5084
- const snapshot = await getStateMachineNextSnapshot(server, {
5116
+ const snapshot = await getStateMachineNextSnapshot({
5085
5117
  machineConfig: stateMachine.config,
5086
5118
  context: input.context,
5087
5119
  currentState: input.currentState,
@@ -5293,7 +5325,7 @@ class StateMachinePlugin {
5293
5325
  throw new Error(`State machine of property '${statePropertyToUpdate.code}' not configured.`);
5294
5326
  }
5295
5327
  machineConfig.id = getStateMachineCode(model, statePropertyToUpdate);
5296
- const nextSnapshot = await getStateMachineNextSnapshot(server, {
5328
+ const nextSnapshot = await getStateMachineNextSnapshot({
5297
5329
  machineConfig,
5298
5330
  context: {},
5299
5331
  currentState: currentEntity[statePropertyToUpdate.code],
@@ -3,7 +3,10 @@
3
3
  */
4
4
  import { CreateEntityOptions, RpdApplicationConfig, RpdDataModel } from "../../types";
5
5
  import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
6
+ import SequenceService from "./SequenceService";
6
7
  declare class SequencePlugin implements RapidPlugin {
8
+ #private;
9
+ get sequenceService(): SequenceService;
7
10
  get code(): string;
8
11
  get description(): string;
9
12
  get extendingAbilities(): RpdServerPluginExtendingAbilities[];
@@ -11,6 +14,7 @@ declare class SequencePlugin implements RapidPlugin {
11
14
  get configurations(): RpdConfigurationItemOptions[];
12
15
  registerActionHandlers(server: IRpdServer): Promise<any>;
13
16
  configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
17
+ configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
14
18
  configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
15
19
  onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<void>;
16
20
  beforeCreateEntity(server: IRpdServer, model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
@@ -12,4 +12,8 @@ export interface SegmentResolver {
12
12
  segmentType: string;
13
13
  resolveSegmentValue(server: IRpdServer, ruleCode: string, config: SequenceSegmentConfig, input: GenerateSequenceNumbersInput): Promise<string>;
14
14
  }
15
- export declare function generateSn(server: IRpdServer, input: GenerateSequenceNumbersInput): Promise<string[]>;
15
+ export default class SequenceService {
16
+ #private;
17
+ constructor(server: IRpdServer);
18
+ generateSn(server: IRpdServer, input: GenerateSequenceNumbersInput): Promise<string[]>;
19
+ }
@@ -0,0 +1,3 @@
1
+ import { GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } from "./StateMachinePluginTypes";
2
+ export declare function getStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions): Promise<import("xstate").MachineSnapshot<any, import("xstate").AnyEventObject, Record<string, import("xstate").AnyActorRef>, import("xstate").StateValue, string, unknown, import("xstate").MetaObject, never>>;
3
+ export declare function tryGetStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult>;
package/dist/server.d.ts CHANGED
@@ -32,6 +32,8 @@ export declare class RapidServer implements IRpdServer {
32
32
  getEntityManager<TEntity = any>(singularCode: string): EntityManager<TEntity>;
33
33
  registerEventHandler<K extends keyof RpdServerEventTypes>(eventName: K, listener: (...args: RpdServerEventTypes[K]) => void): this;
34
34
  emitEvent<K extends keyof RpdServerEventTypes>(eventName: K, payload: RpdServerEventTypes[K][1], sender?: RapidPlugin): Promise<void>;
35
+ registerService(name: string, service: any): void;
36
+ getService<TService>(name: string): TService;
35
37
  start(): Promise<void>;
36
38
  configureApplication(): Promise<void>;
37
39
  registerFacilityFactory(factory: FacilityFactory): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.1.38",
3
+ "version": "0.1.40",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -105,6 +105,18 @@ class PluginManager {
105
105
  }
106
106
  }
107
107
 
108
+
109
+ /** 配置服务 */
110
+ async configureServices(
111
+ applicationConfig: RpdApplicationConfig,
112
+ ) {
113
+ for (const plugin of this.#plugins) {
114
+ if (plugin.configureServices) {
115
+ await plugin.configureServices(this.#server, applicationConfig);
116
+ }
117
+ }
118
+ }
119
+
108
120
  /** 配置路由 */
109
121
  async configureRoutes(
110
122
  applicationConfig: RpdApplicationConfig,
@@ -33,6 +33,8 @@ export interface IRpdServer {
33
33
  options: GetDataAccessorOptions,
34
34
  ): IRpdDataAccessor<T>;
35
35
  getEntityManager<TEntity = any>(singularCode: string): EntityManager<TEntity>;
36
+ registerService(name: string, service: any);
37
+ getService<TService>(name: string): TService;
36
38
  getApplicationConfig(): RpdApplicationConfig;
37
39
  appendApplicationConfig(config: Partial<RpdApplicationConfig>);
38
40
  appendModelProperties(modelSingularCode: string, properties: RpdDataModelProperty[]);
@@ -131,6 +133,8 @@ export interface RapidPlugin {
131
133
  configureModels?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
132
134
  /** 配置模型属性 */
133
135
  configureModelProperties?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
136
+ /** 配置服务 */
137
+ configureServices?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
134
138
  /** 配置路由 */
135
139
  configureRoutes?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
136
140
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
@@ -15,11 +15,17 @@ import pluginModels from "./models";
15
15
  import pluginRoutes from "./routes";
16
16
  import { PropertySequenceConfig } from "./SequencePluginTypes";
17
17
  import { isEqual } from "lodash";
18
- import { generateSn } from "./SequenceService";
18
+ import SequenceService from "./SequenceService";
19
19
  import { isNullOrUndefined } from "~/utilities/typeUtility";
20
20
 
21
21
 
22
22
  class SequencePlugin implements RapidPlugin {
23
+ #sequenceService!: SequenceService;
24
+
25
+ get sequenceService() {
26
+ return this.#sequenceService;
27
+ }
28
+
23
29
  get code(): string {
24
30
  return "sequencePlugin";
25
31
  }
@@ -49,6 +55,11 @@ class SequencePlugin implements RapidPlugin {
49
55
  async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
50
56
  server.appendApplicationConfig({ models: pluginModels });
51
57
  }
58
+
59
+ async configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
60
+ this.#sequenceService = new SequenceService(server);
61
+ server.registerService("sequenceService", this.#sequenceService);
62
+ }
52
63
 
53
64
  async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
54
65
  server.appendApplicationConfig({ routes: pluginRoutes });
@@ -103,7 +114,7 @@ class SequencePlugin implements RapidPlugin {
103
114
  isNullOrUndefined(propertyValue)
104
115
  ) {
105
116
  const ruleCode = getSequenceRuleCode(model, property);
106
- const numbers = await generateSn(server, {
117
+ const numbers = await this.#sequenceService.generateSn(server, {
107
118
  ruleCode,
108
119
  amount: 1,
109
120
  parameters: entity,
@@ -18,54 +18,63 @@ export interface SegmentResolver {
18
18
  resolveSegmentValue(server: IRpdServer, ruleCode: string, config: SequenceSegmentConfig, input: GenerateSequenceNumbersInput): Promise<string>;
19
19
  }
20
20
 
21
- export async function generateSn(server: IRpdServer, input: GenerateSequenceNumbersInput): Promise<string[]> {
22
- const sequenceNumbers = [];
23
- const { ruleCode, parameters } = input;
24
- let { amount } = input;
21
+ export default class SequenceService {
22
+ #server: IRpdServer;
25
23
 
26
- if (!amount) {
27
- amount = 1;
24
+ constructor(server: IRpdServer) {
25
+ this.#server = server;
28
26
  }
29
27
 
30
- const sequenceRuleDataAccessor = server.getDataAccessor({
31
- singularCode: "sequence_rule",
32
- });
33
-
34
- const sequenceRule = await sequenceRuleDataAccessor.findOne({
35
- filters: [
36
- {
37
- operator: "eq",
38
- field: "code",
39
- value: ruleCode,
40
- }
41
- ]
42
- });
43
-
44
- if (!sequenceRule) {
45
- throw new Error(`Failed to generate sequence number. Sequence with code '${sequenceRule.code}' not found.`);
46
- }
47
-
48
- const sequenceConfig: SequenceRuleConfig = sequenceRule.config;
49
- if (!sequenceConfig || !sequenceConfig.segments) {
50
- throw new Error("Failed to generate sequence number. Sequence not configured.");
51
- }
52
-
53
- for (let i = 0; i < amount; i++) {
54
- let sequenceNumber: string = "";
55
-
56
- for (const segmentConfig of sequenceConfig.segments) {
57
- const segmentResolver: SegmentResolver = find(segmentResolvers, (item) => item.segmentType === segmentConfig.type);
58
- if (!segmentResolver) {
59
- // TODO: deal with unkown segment type
60
- continue;
28
+ async generateSn(server: IRpdServer, input: GenerateSequenceNumbersInput): Promise<string[]> {
29
+ const sequenceNumbers = [];
30
+ const { ruleCode, parameters } = input;
31
+ let { amount } = input;
32
+
33
+ if (!amount) {
34
+ amount = 1;
35
+ }
36
+
37
+ const sequenceRuleDataAccessor = server.getDataAccessor({
38
+ singularCode: "sequence_rule",
39
+ });
40
+
41
+ const sequenceRule = await sequenceRuleDataAccessor.findOne({
42
+ filters: [
43
+ {
44
+ operator: "eq",
45
+ field: "code",
46
+ value: ruleCode,
47
+ }
48
+ ]
49
+ });
50
+
51
+ if (!sequenceRule) {
52
+ throw new Error(`Failed to generate sequence number. Sequence with code '${sequenceRule.code}' not found.`);
53
+ }
54
+
55
+ const sequenceConfig: SequenceRuleConfig = sequenceRule.config;
56
+ if (!sequenceConfig || !sequenceConfig.segments) {
57
+ throw new Error("Failed to generate sequence number. Sequence not configured.");
58
+ }
59
+
60
+ for (let i = 0; i < amount; i++) {
61
+ let sequenceNumber: string = "";
62
+
63
+ for (const segmentConfig of sequenceConfig.segments) {
64
+ const segmentResolver: SegmentResolver = find(segmentResolvers, (item) => item.segmentType === segmentConfig.type);
65
+ if (!segmentResolver) {
66
+ // TODO: deal with unkown segment type
67
+ continue;
68
+ }
69
+
70
+ const segment = await segmentResolver.resolveSegmentValue(server, ruleCode, segmentConfig, input);
71
+ sequenceNumber += segment;
61
72
  }
62
-
63
- const segment = await segmentResolver.resolveSegmentValue(server, ruleCode, segmentConfig, input);
64
- sequenceNumber += segment;
73
+
74
+ sequenceNumbers.push(sequenceNumber);
65
75
  }
66
-
67
- sequenceNumbers.push(sequenceNumber);
76
+
77
+ return sequenceNumbers;
68
78
  }
69
-
70
- return sequenceNumbers;
71
- }
79
+
80
+ }
@@ -1,6 +1,6 @@
1
1
  import { ActionHandlerContext } from "~/core/actionHandler";
2
2
  import { RapidPlugin } from "~/core/server";
3
- import { GenerateSequenceNumbersInput, GenerateSequenceNumbersOutput, generateSn } from "../SequenceService";
3
+ import SequenceService, { GenerateSequenceNumbersInput, GenerateSequenceNumbersOutput } from "../SequenceService";
4
4
 
5
5
  export interface GenerateSequenceNumbersOptions {
6
6
  ruleCode: string;
@@ -27,7 +27,9 @@ export async function handler(
27
27
  throw new Error(`Rule code is required when generating sequence numbers.`);
28
28
  }
29
29
 
30
- const sequences = await generateSn(server, input);
30
+ const sequenceService = server.getService<SequenceService>("sequenceService");
31
+
32
+ const sequences = await sequenceService.generateSn(server, input);
31
33
 
32
34
  ctx.output = {
33
35
  sequences,
@@ -17,7 +17,7 @@ import pluginRoutes from "./routes";
17
17
  import { filter, find, first, get, isEqual } from "lodash";
18
18
  import { PropertyStateMachineConfig } from "./StateMachinePluginTypes";
19
19
  import { isNullOrUndefined } from "~/utilities/typeUtility";
20
- import { getStateMachineNextSnapshot } from "./StateMachineService";
20
+ import { getStateMachineNextSnapshot } from "./stateMachineHelper";
21
21
 
22
22
 
23
23
  class StateMachinePlugin implements RapidPlugin {
@@ -164,7 +164,7 @@ class StateMachinePlugin implements RapidPlugin {
164
164
  }
165
165
  machineConfig.id = getStateMachineCode(model, statePropertyToUpdate);
166
166
 
167
- const nextSnapshot = await getStateMachineNextSnapshot(server, {
167
+ const nextSnapshot = await getStateMachineNextSnapshot({
168
168
  machineConfig,
169
169
  context: {},
170
170
  currentState: currentEntity[statePropertyToUpdate.code],
@@ -1,7 +1,7 @@
1
1
  import { ActionHandlerContext } from "~/core/actionHandler";
2
2
  import { RapidPlugin } from "~/core/server";
3
3
  import { SendStateMachineEventInput, SendStateMachineEventOptions } from "../StateMachinePluginTypes";
4
- import { getStateMachineNextSnapshot } from "../StateMachineService";
4
+ import { getStateMachineNextSnapshot } from "../stateMachineHelper";
5
5
 
6
6
  export const code = "sendStateMachineEvent";
7
7
 
@@ -42,7 +42,7 @@ export async function handler(
42
42
 
43
43
  stateMachine.config.id = input.code;
44
44
 
45
- const snapshot = await getStateMachineNextSnapshot(server, {
45
+ const snapshot = await getStateMachineNextSnapshot({
46
46
  machineConfig: stateMachine.config,
47
47
  context: input.context,
48
48
  currentState: input.currentState,
@@ -1,8 +1,7 @@
1
- import { IRpdServer } from "~/core/server";
2
1
  import { DefaultStateMachineSnapshot, GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } from "./StateMachinePluginTypes";
3
2
  import { createMachine, getInitialSnapshot, getNextSnapshot } from "xstate";
4
3
 
5
- export async function getStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions) {
4
+ export async function getStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions) {
6
5
  const { machineConfig, currentState, event } = options;
7
6
  machineConfig.initial = currentState;
8
7
 
@@ -17,7 +16,7 @@ export async function getStateMachineNextSnapshot(server: IRpdServer, options: G
17
16
  return nextSnapshot;
18
17
  }
19
18
 
20
- export async function tryGetStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult> {
19
+ export async function tryGetStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult> {
21
20
  const { machineConfig, currentState, event } = options;
22
21
  machineConfig.initial = currentState;
23
22
 
package/src/server.ts CHANGED
@@ -52,6 +52,7 @@ export class RapidServer implements IRpdServer {
52
52
  #databaseAccessor: IDatabaseAccessor;
53
53
  #cachedDataAccessors: Map<string, DataAccessor>;
54
54
  #cachedEntityManager: Map<string, EntityManager>;
55
+ #services: Map<string, any>;
55
56
  queryBuilder: IQueryBuilder;
56
57
  config: RapidServerConfig;
57
58
  databaseConfig: IDatabaseConfig;
@@ -78,6 +79,8 @@ export class RapidServer implements IRpdServer {
78
79
  this.#cachedDataAccessors = new Map();
79
80
  this.#cachedEntityManager = new Map();
80
81
 
82
+ this.#services = new Map();
83
+
81
84
  this.queryBuilder = new QueryBuilder({
82
85
  dbDefaultSchema: options.databaseConfig.dbDefaultSchema,
83
86
  });
@@ -233,6 +236,14 @@ export class RapidServer implements IRpdServer {
233
236
  // }
234
237
  }
235
238
 
239
+ registerService(name: string, service: any) {
240
+ this.#services.set(name, service);
241
+ }
242
+
243
+ getService<TService>(name: string): TService {
244
+ return this.#services.get(name);
245
+ }
246
+
236
247
  async start() {
237
248
  this.#logger.info("Starting rapid server...");
238
249
  const pluginManager = this.#pluginManager;
@@ -261,6 +272,7 @@ export class RapidServer implements IRpdServer {
261
272
  await pluginManager.onLoadingApplication(this.#applicationConfig);
262
273
  await pluginManager.configureModels(this.#applicationConfig);
263
274
  await pluginManager.configureModelProperties(this.#applicationConfig);
275
+ await pluginManager.configureServices(this.#applicationConfig);
264
276
  await pluginManager.configureRoutes(this.#applicationConfig);
265
277
 
266
278
  // TODO: check application configuration.
@@ -1,4 +0,0 @@
1
- import { IRpdServer } from "../../core/server";
2
- import { GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } 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>>;
4
- export declare function tryGetStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult>;